Calculating the difference in months between two dates is a useful skill for C# developers. Having this knowledge helps us in tasks such as subscription management and tracking course durations. In this article, we learn how to use DateOnly, DateTime, and TimeSpan structs to calculate the difference in months between two dates for scenarios like these.

To download the source code for this article, you can visit our GitHub repository.

Let’s begin.

Understanding Month Calculations

Month calculations are not as straightforward as they may seem. Calculating the difference in months between two dates is challenging due to varying month lengths and leap years. To overcome these challenges we create two methods: one for calculating the difference in complete months and another for calculating month differences including partial months.

Support Code Maze on Patreon to get rid of ads and get the best discounts on our products!
Become a patron at Patreon!

It’s important to define what we mean by “complete months”. In this article, a “complete month” starts on a specific day of one month and extends to the day before the same date in the following month. For example, March 15, 2023, to April 14, 2023, is one complete month. Similarly, March 15, 2023, to May 14, 2023, represents two complete months.

Calculate the Difference Between Two Dates in Complete Months

Let’s imagine we operate an e-learning platform and want to know how long each user has been a subscriber in complete months.

First, we establish the user’s subscription start date:

var subscriptionStart = new DateOnly(2023, 5, 14);
var subscriptionEndDate = DateOnly.FromDateTime(DateTime.Today);

Here, we create a DateOnly struct called subscriptionStart representing the date the user began their subscription. Next, we define subscriptionEndDate and set it to today’s date using DateOnly.FromDateTime(DateTime.Today). The method DateOnly.FromDateTime is used to change a DateTime struct, which includes both date and time, into a DateOnly struct. That way, we can just focus on the date and not the time.

To learn more, check out our other articles DateTime Format In C# and DateOnly and TimeOnly in C#

Implement the Calculation Method

With our start and end dates defined, we calculate the difference: 

public static int CalculateSubscriptionDuration(DateOnly subscriptionStart, DateOnly endDate)
{
    if (subscriptionStart > endDate)
    {
        throw new ArgumentOutOfRangeException(nameof(subscriptionStart),
            "The subscription start date must be before the end date.");
    }

    int months = (endDate.Year - subscriptionStart.Year) * 12 + endDate.Month - subscriptionStart.Month;

    if (endDate.Day < subscriptionStart.Day - 1)
    {
        months--;
    }

    if (subscriptionStart.Day == 1 && DateTime.DaysInMonth(endDate.Year, endDate.Month) == endDate.Day)
    {
        months++;
    }

    return months;
}

In the CalculateSubscriptionDuration() we first need to check whether the start date is after the end date since it would be pretty unusual to be subscribed for a negative number of months. If that’s the case, we will throw an ArgumentOutOfRangeException.

If our end date is indeed after the start date, then we are safe to initialize months. This variable represents the total months elapsed, in terms of years, with the formula (endDate.Year - subscriptionStart.Year) * 12. Then, we adjust for the additional months within the incomplete year using + endDate.Month - subscriptionStart.Month.

However, since we are only calculating full months, it’s important to check if the endDate.Day is less than the day before the subscriptionStart.Day (that’s why we subtract 1). To do this, we use the Day property of the DateOnly struct which gives us an integer representing the particular day of the month. If it’s true, we should subtract one month.

To make sure we account for all complete months, we also consider situations where the subscription starts on the first day of the month and ends on the last day of a particular month. To do this, we first check if the start day is the first day of the month. Then, using the DateTime.DaysInMonth() method, we check if the total days in that month match the end date’s day. If they are equal, we add one more month to our count.

Lastly, we return the total number of months.

Getting the Result

Now that we can calculate the total number of months, let’s see our code in action:

int totalMonthsSubscribed = NumberOfMonthsBetweenTwoDates.CalculateSubscriptionDuration(
    subscriptionStart, subscriptionEndDate);
Console.WriteLine($"User has been subscribed for {totalMonthsSubscribed} months.");

Here, we initialize totalMonthsSubscribed using the CalculateSubscriptionDuration() method we just created.

Assuming today’s date is January 23, 2024, let’s see the output:

User has been subscribed for 8 months.

Now we can see how many months a user has been a subscriber of our e-learning site. But what if we wanted to know how many months, including partial months? For instance, this user subscribed on May 14, 2023, so they have been a subscriber for 8 months and 9 days, or approximately 8.35 months. 

Calculate the Difference Between Two Dates in Approximate Months

Let’s think back to our e-learning platform. Now, instead of wanting to know how long someone’s been a subscriber, we want to know how long one of our courses has been “live” on the site.

Course duration in this scenario is the total time in months (as a double) between two dates (courseStart and courseEndDate). Similar to before, we calculate one month as the span between the start date’s day and the date preceding that day in the following month.

First, we start with the date that we released our course: 

var courseStart = new DateTime(2023, 9, 12);
var courseEndDate = DateTime.Today;

Similar to before, we need to initialize start and end dates. We utilize the DateTime constructor to initialize courseStart, the date we first released our course (September 12, 2023). Then, we use courseEndDate to represent today’s date.

Create the Method to Calculate the Difference in Months Between Two Dates

With both start and end dates defined, let’s look at how to calculate the approximate months between dates:

public static double CalculateCourseDuration(DateTime courseStart, DateTime endDate)
{
    var courseStartUtc = courseStart.ToUniversalTime();
    var endDateUtc = endDate.ToUniversalTime();

    if (courseStartUtc > endDateUtc)
    {
        throw new ArgumentOutOfRangeException(nameof(courseStart),
            "The course start date must be before the end date.");
    }

    double totalDays = (endDateUtc - courseStartUtc).TotalDays;

    return totalDays / (365.2425 / 12);
}

Here, we have a new method called CalculateCourseDuration(). First, we need to convert our courseStart and endDate into UTC to ensure the time zone is consistent throughout the calculation.

Then, just like we did in our subscription calculation example, we ensure the start date is after the end date, throwing an ArgumentOutOfRangeException if not.

Our next goal is to calculate the totalDays (including the start date, but excluding the end date) between the two dates. We start by subtracting courseStartUtc from endDateUtc, which results in a TimeSpan object. Then, we use the TotalDays property of the TimeSpan struct to get the entire duration between those two dates in days (represented as a double). This includes whole days and the fractional part of a day if any.

To learn more about TimeSpan, don’t miss our article TimeSpan in C#.

Finally, we return the total number of months between the two dates. This is done by dividing totalDays by the average number of days in a month. To calculate the average number of days in a month, we divide the average number of days per year 365.2425 (considering leap years) by 12 (the number of months in a year). 

Now, let’s look at how we can use our method: 

double courseDuration = NumberOfMonthsBetweenTwoDates.CalculateCourseDuration(courseStart, courseEndDate);
Console.WriteLine($"This course has been online for {courseDuration:F2} months.");

Here, we define courseDuration which uses our new method CalculateCourseDuration().

Assuming today’s date is January 23, 2024, let’s see how many months our course has been on the platform: 

This course has been online for 4.37 months.

Now we know approximately how many months our course has been “live”. This knowledge is useful to evaluate the course performance, assess its profitability, or even help plan content updates.

Conclusion

The ability to calculate time differences between dates is a valuable skill in C#. By understanding the different techniques for month calculations, we can enhance the functionality and precision of our applications. Whether it’s for monitoring subscription durations or checking how long a course has been online, there are infinite use cases. Can you think of scenarios where these monthly calculation methods would be useful? Feel free to let us know in the comments below.

Liked it? Take a second to support Code Maze on Patreon and get the ad free reading experience!
Become a patron at Patreon!