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.
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.
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.
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.
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.