438

How to calculate the difference in months between two dates in C#?

Is there is equivalent of VB's DateDiff() method in C#. I need to find difference in months between two dates that are years apart. The documentation says that I can use TimeSpan like:

TimeSpan ts = date1 - date2; 

but this gives me data in Days. I don't want to divide this number by 30 because not every month is 30 days and since the two operand values are quite apart from each other, I am afraid dividing by 30 might give me a wrong value.

Any suggestions?

8
  • 32
    Define "difference in months", what's the difference in months between "May 1,2010" and "June 16,2010"? 1.5, 1 or something else? Commented Jan 9, 2011 at 12:04
  • 8
    Or, to stress this point further, what's the difference in months between 31 December 2010 and 1 Jan 2011? Depending on the daytime this could be a difference of only 1 second; would you count this as a difference of one month? Commented Jan 9, 2011 at 12:36
  • 17
    Danny: 1 month and 15 days. stakx: 0 months and 1 day. The point is to get the month component. This seems pretty obvious to me and is a good question. Commented Feb 9, 2012 at 17:30
  • 1
    DateDiff implantation: referencesource.microsoft.com/#Microsoft.VisualBasic/…. Commented Jun 28, 2015 at 10:04
  • 5
    I think since OP mentions vb's DateDiff, all these questions are answered. The answers happen to be the same as w/ SQL Server's datediff. Just answer the question... To be clear, its the number of month boundaries that are crossed between the two dates, (inclusive) Commented Mar 31, 2020 at 14:28

47 Answers 47

591

Assuming the day of the month is irrelevant (i.e. the diff between 2011.1.1 and 2010.12.31 is 1), with date1 > date2 giving a positive value and date2 > date1 a negative value

((date1.Year - date2.Year) * 12) + date1.Month - date2.Month 

Or, assuming you want an approximate number of 'average months' between the two dates, the following should work for all but very huge date differences.

date1.Subtract(date2).Days / (365.25 / 12) 

Note, if you were to use the latter solution then your unit tests should state the widest date range which your application is designed to work with and validate the results of the calculation accordingly.


Update (with thanks to Gary)

If using the 'average months' method, a slightly more accurate number to use for the 'average number of days per year' is 365.2425.

Sign up to request clarification or add additional context in comments.

16 Comments

I think it is necessary to consider Day component. Something like this (date1.Year - date2.Year) * 12 + date1.Month - date2.Month + (date1.Day >= date2.Day ? 0 : -1)
@DrunkCoder it depends on the requirements of a given system. In some cases your solution may indeed be the best choice. E.g. it's important to consider what happens when two dates span a 31 day month, a 30 day month, a 28 day February or a 29 day February. If the results of your formula deliver what the system requires then it's clearly the right choice. If not, then something else is required.
To second what Adam said, I spent years writing code for Acturaries. Some calculations were divide by number of days, round up by 30 to get monthly figure. Sometimes counting months assumed every date starts on the first of the month, count whole months accordingly. There is no best method when it comes to calculating dates. Unless you are the customer you're writing code for, push this back up the chain and get it clarified, possibly by you customers accountant.
365.2425 is slightly more accurate number of days in a Gregorian Calendar, if that is what you are using. However, by DateTime.MaxValue (January 1, 10000) that's only about 59 days difference. Also, the definition of a year can be much different depending on your perspective en.wikipedia.org/wiki/Year.
For those who suggested using the Microsoft.VisualBasic.dll it should be made known that the suggestion by @AdamRalph matches the code in the dll pretty much verbatim: case DateInterval.Month: { Calendar currentCalendar = CurrentCalendar; return (currentCalendar.GetYear(Date2) - currentCalendar.GetYear(Date1)) * 12 + currentCalendar.GetMonth(Date2) - currentCalendar.GetMonth(Date1); }
|
238

Here is a comprehensive solution to return a DateTimeSpan, similar to a TimeSpan, except that it includes all the date components in addition to the time components.

Usage:

void Main() { DateTime compareTo = DateTime.Parse("8/13/2010 8:33:21 AM"); DateTime now = DateTime.Parse("2/9/2012 10:10:11 AM"); var dateSpan = DateTimeSpan.CompareDates(compareTo, now); Console.WriteLine("Years: " + dateSpan.Years); Console.WriteLine("Months: " + dateSpan.Months); Console.WriteLine("Days: " + dateSpan.Days); Console.WriteLine("Hours: " + dateSpan.Hours); Console.WriteLine("Minutes: " + dateSpan.Minutes); Console.WriteLine("Seconds: " + dateSpan.Seconds); Console.WriteLine("Milliseconds: " + dateSpan.Milliseconds); } 

Outputs:

Years: 1
Months: 5
Days: 27
Hours: 1
Minutes: 36
Seconds: 50
Milliseconds: 0

For convenience, I've lumped the logic into the DateTimeSpan struct, but you may move the method CompareDates wherever you see fit. Also note, it doesn't matter which date comes before the other.

public struct DateTimeSpan { public int Years { get; } public int Months { get; } public int Days { get; } public int Hours { get; } public int Minutes { get; } public int Seconds { get; } public int Milliseconds { get; } public DateTimeSpan(int years, int months, int days, int hours, int minutes, int seconds, int milliseconds) { Years = years; Months = months; Days = days; Hours = hours; Minutes = minutes; Seconds = seconds; Milliseconds = milliseconds; } enum Phase { Years, Months, Days, Done } public static DateTimeSpan CompareDates(DateTime date1, DateTime date2) { if (date2 < date1) { var sub = date1; date1 = date2; date2 = sub; } DateTime current = date1; int years = 0; int months = 0; int days = 0; Phase phase = Phase.Years; DateTimeSpan span = new DateTimeSpan(); int officialDay = current.Day; while (phase != Phase.Done) { switch (phase) { case Phase.Years: if (current.AddYears(years + 1) > date2) { phase = Phase.Months; current = current.AddYears(years); } else { years++; } break; case Phase.Months: if (current.AddMonths(months + 1) > date2) { phase = Phase.Days; current = current.AddMonths(months); if (current.Day < officialDay && officialDay <= DateTime.DaysInMonth(current.Year, current.Month)) current = current.AddDays(officialDay - current.Day); } else { months++; } break; case Phase.Days: if (current.AddDays(days + 1) > date2) { current = current.AddDays(days); var timespan = date2 - current; span = new DateTimeSpan(years, months, days, timespan.Hours, timespan.Minutes, timespan.Seconds, timespan.Milliseconds); phase = Phase.Done; } else { days++; } break; } } return span; } } 

3 Comments

I wrote an answer stackoverflow.com/a/17537472/1737957 to a similar question which tested proposed answers (and found that most of them don't work). This answer is one of the few that does work (according to my test suite). Link to github on my answer.
Very cool, but please note this algorithm has some edge-case issues. If you happen to use DateTime.MinValue or DateTime.MaxValuein date values this will fall over. e.g. System.ArgumentOutOfRangeException': "The added or subtracted value results in an un-representable DateTime."
There is way of calculating it in O(1) where you are doing it in O(n) where n depends on the number of years, months and days. In other words you can do it without loop nad being a lot faster. But I really like the idea of doing a DateTimeDiff and have fields like yours.
56

You could do

if ( date1.AddMonths(x) > date2 ) 

3 Comments

What if date1 = 2018-10-28 and date2 = 2018-12-21 ? Answer will be 2. while correct answer should be 3. Because of date range is for 3 months. if we count only months ignoring days. So this answer is NOT correct.
More logical would be: if ( date1.AddMonths(x).Month == date2.Month ) then you just use x + 1 as months count
Am I missing something... this is a true / false check on whether the dates differ by at least the given number of months, not a calculation of that number of months, which is what I thought the o/p asked for.
38

If you want the exact number of full months, always positive (2000-01-15, 2000-02-14 returns 0), considering a full month is when you reach the same day the next month (something like the age calculation)

public static int GetMonthsBetween(DateTime from, DateTime to) { if (from > to) return GetMonthsBetween(to, from); var monthDiff = Math.Abs((to.Year * 12 + (to.Month - 1)) - (from.Year * 12 + (from.Month - 1))); if (from.AddMonths(monthDiff) > to || to.Day < from.Day) { return monthDiff - 1; } else { return monthDiff; } } 

Edit reason: the old code was not correct in some cases like :

new { From = new DateTime(1900, 8, 31), To = new DateTime(1901, 8, 30), Result = 11 }, Test cases I used to test the function: var tests = new[] { new { From = new DateTime(1900, 1, 1), To = new DateTime(1900, 1, 1), Result = 0 }, new { From = new DateTime(1900, 1, 1), To = new DateTime(1900, 1, 2), Result = 0 }, new { From = new DateTime(1900, 1, 2), To = new DateTime(1900, 1, 1), Result = 0 }, new { From = new DateTime(1900, 1, 1), To = new DateTime(1900, 2, 1), Result = 1 }, new { From = new DateTime(1900, 2, 1), To = new DateTime(1900, 1, 1), Result = 1 }, new { From = new DateTime(1900, 1, 31), To = new DateTime(1900, 2, 1), Result = 0 }, new { From = new DateTime(1900, 8, 31), To = new DateTime(1900, 9, 30), Result = 0 }, new { From = new DateTime(1900, 8, 31), To = new DateTime(1900, 10, 1), Result = 1 }, new { From = new DateTime(1900, 1, 1), To = new DateTime(1901, 1, 1), Result = 12 }, new { From = new DateTime(1900, 1, 1), To = new DateTime(1911, 1, 1), Result = 132 }, new { From = new DateTime(1900, 8, 31), To = new DateTime(1901, 8, 30), Result = 11 }, }; 

8 Comments

Just so as to avoid confusion for other people, I think this solution is not correct. Using the test case: new { From = new DateTime(2015, 12, 31), To = new DateTime(2015, 6, 30), Result = 6 } the test will fail as the result is 5.
Added a quick gist with the fix I propose here
I'm not sure I get it, my function returns 6 as it should: dotnetfiddle.net/MRZNnC
I copied the test case here by hand and It has a mistake. The failing spec should be: new { From = new DateTime(2015, 12, 31), To = new DateTime(2016, 06, 30), Result = 6 }. The "bug" lies in the to.Day < from.Day code which doesn't take into account that months can end in a different "day of the month". In this case from December 31st 2015, until June 30 2016, 6 complete months will have passed (since June has 30 days) but your code would return 5.
It's expected behavior in my opinion, well or it's the behavior I do expect at least. I precised a complete month is when you reach the same day (or the next month like in this case).
|
25

I checked the usage of this method in VB.NET via MSDN and it seems that it has a lot of usages. There is no such a built-in method in C#. (Even it's not a good idea) you can call VB's in C#.

  1. Add Microsoft.VisualBasic.dll to your project as a reference
  2. use Microsoft.VisualBasic.DateAndTime.DateDiff in your code

11 Comments

Why do you think it's not a good idea? Intuitively, I would guess that the library is 'just another .NET library' to the runtime. Note, I am playing devil's advocate here, I would also be relunctant to do this since it just 'feels wrong' (kind of cheating) but I wonder if there is any convincing technical reason not to do this.
@AdamRalph: No reason at all not to do it. Those libraries are implemented in 100% managed code, so it's all the same as everything else. The only conceivable difference is that the Microsoft.VisualBasic.dll module has to be loaded, but the time it takes to do that is negligible. There's no reason to cheat yourself out of thoroughly tested and useful features just because you've chosen to write your program in C#. (This goes for things like My.Application.SplashScreen as well.)
Would you change your mind if you knew that it was written in C#? It was. By the same logic, using System.Data and PresentationFramework is cheating too, substantial parts of it written in C++/CLI.
@AdamRalph: Any particular examples of that "strange baggage" that spring to mind? Or are you saying that purely hypothetically? And yeah, it might mess with the minds of some of your C# buddies who have been writing an epic amount of code to do something that you can do in one line with the right using statement, but I doubt there'll be any serious damage.
@Cody Gray: agreed, the example is trivial as you illustrate. It's the extra code 'noise' introduced by calling such an unusual (from a C# POV) method that I'd be keen to avoid. In a well organised team such things would anyway be picked up in code review and can be easily avoided. BTW - I'm not trying to attack VB6/VB.NET. I described such methods as 'strange' only because, from a .NET POV, there's no reason for DateAndTime.Year() to exist, given that DateTime has a Year property. It only exists to make VB.NET appear more like VB6. As a former VB6 programmer, I can appreciate this ;-)
|
11

To get difference in months (both start and end inclusive), irrespective of dates:

DateTime start = new DateTime(2013, 1, 1); DateTime end = new DateTime(2014, 2, 1); var diffMonths = (end.Month + end.Year * 12) - (start.Month + start.Year * 12); 

4 Comments

Imagine start and end are identical. Then you get a result of 1. How is that right? Why do you add 1 to the result? Who is up-voting this answer :-/ ?
For identical dates, it will give output as 1. Basically, it will count all the months inclusive start and end months.
doesn't sound like the difference between two items to me. What is the difference between 2 and 2? Is it really 1? I would suggest the difference is 0.
I can't wrap my head around how this works, but I put it in excel and it does. I added the +1 at the end because for my purposes, 8/2023 - 8/2023 = 1 month. His solution does say "start and end inclusive".
11

Use Noda Time:

LocalDate start = new LocalDate(2013, 1, 5); LocalDate end = new LocalDate(2014, 6, 1); Period period = Period.Between(start, end, PeriodUnits.Months); Console.WriteLine(period.Months); // 16 

(example source)

Comments

8

I just needed something simple to cater for e.g. employment dates where only the month/year is entered, so wanted distinct years and months worked in. This is what I use, here for usefullness only

public static YearsMonths YearMonthDiff(DateTime startDate, DateTime endDate) { int monthDiff = ((endDate.Year * 12) + endDate.Month) - ((startDate.Year * 12) + startDate.Month) + 1; int years = (int)Math.Floor((decimal) (monthDiff / 12)); int months = monthDiff % 12; return new YearsMonths { TotalMonths = monthDiff, Years = years, Months = months }; } 

.NET Fiddle

Comments

6

Here is my contribution to get difference in Months that I've found to be accurate:

namespace System { public static class DateTimeExtensions { public static Int32 DiffMonths( this DateTime start, DateTime end ) { Int32 months = 0; DateTime tmp = start; while ( tmp < end ) { months++; tmp = tmp.AddMonths( 1 ); } return months; } } } 

Usage:

Int32 months = DateTime.Now.DiffMonths( DateTime.Now.AddYears( 5 ) ); 

You can create another method called DiffYears and apply exactly the same logic as above and AddYears instead of AddMonths in the while loop.

Comments

4

You can use the DateDiff class of the Time Period Library for .NET:

// ---------------------------------------------------------------------- public void DateDiffSample() { DateTime date1 = new DateTime( 2009, 11, 8, 7, 13, 59 ); DateTime date2 = new DateTime( 2011, 3, 20, 19, 55, 28 ); DateDiff dateDiff = new DateDiff( date1, date2 ); // differences Console.WriteLine( "DateDiff.Months: {0}", dateDiff.Months ); // > DateDiff.Months: 16 // elapsed Console.WriteLine( "DateDiff.ElapsedMonths: {0}", dateDiff.ElapsedMonths ); // > DateDiff.ElapsedMonths: 4 // description Console.WriteLine( "DateDiff.GetDescription(6): {0}", dateDiff.GetDescription( 6 ) ); // > DateDiff.GetDescription(6): 1 Year 4 Months 12 Days 12 Hours 41 Mins 29 Secs } // DateDiffSample 

Comments

4

You can use Noda Time https://nodatime.org/

LocalDate start = new LocalDate(2010, 1, 5); LocalDate end = new LocalDate(2012, 6, 1); Period period = Period.Between(start, end, PeriodUnits.Months); Console.WriteLine(period.Months); 

Comments

3

My understanding of the total months difference between 2 dates has an integral and a fractional part (the date matters).

The integral part is the full months difference.

The fractional part, for me, is the difference of the % of the day (to the full days of month) between the starting and ending months.

public static class DateTimeExtensions { public static double TotalMonthsDifference(this DateTime from, DateTime to) { //Compute full months difference between dates var fullMonthsDiff = (to.Year - from.Year)*12 + to.Month - from.Month; //Compute difference between the % of day to full days of each month var fractionMonthsDiff = ((double)(to.Day-1) / (DateTime.DaysInMonth(to.Year, to.Month)-1)) - ((double)(from.Day-1)/ (DateTime.DaysInMonth(from.Year, from.Month)-1)); return fullMonthsDiff + fractionMonthsDiff; } } 

With this extension, those are the results:

2/29/2000 TotalMonthsDifference 2/28/2001 => 12 2/28/2000 TotalMonthsDifference 2/28/2001 => 12.035714285714286 01/01/2000 TotalMonthsDifference 01/16/2000 => 0.5 01/31/2000 TotalMonthsDifference 01/01/2000 => -1.0 01/31/2000 TotalMonthsDifference 02/29/2000 => 1.0 01/31/2000 TotalMonthsDifference 02/28/2000 => 0.9642857142857143 01/31/2001 TotalMonthsDifference 02/28/2001 => 1.0 

1 Comment

nice approach regarding percentage of month
3

one line solution

For first, check if both dates are in the current year, if not get months of whole years and then add months from the start and end year.

DateTime dateFrom = new DateTime(2019, 2, 1); DateTime dateTo = new DateTime(2021, 5, 25); 

With the first month

var monthCount = dateFrom.Year != dateTo.Year ? ((dateTo.Year - dateFrom.Year - 1) * 12) + (13 - dateFrom.Month + dateTo.Month) : dateTo.Month - dateFrom.Month + 1; 

result = 28

Without first month

monthCount = dateFrom.Year != dateTo.Year ? ((dateTo.Year - dateFrom.Year - 1) * 12) + (12 - dateFrom.Month + dateTo.Month) : dateTo.Month - dateFrom.Month; 

result = 27

Comments

2

This worked for what I needed it for. The day of month didn't matter in my case because it always happens to be the last day of the month.

public static int MonthDiff(DateTime d1, DateTime d2){ int retVal = 0; if (d1.Month<d2.Month) { retVal = (d1.Month + 12) - d2.Month; retVal += ((d1.Year - 1) - d2.Year)*12; } else { retVal = d1.Month - d2.Month; retVal += (d1.Year - d2.Year)*12; } //// Calculate the number of years represented and multiply by 12 //// Substract the month number from the total //// Substract the difference of the second month and 12 from the total //retVal = (d1.Year - d2.Year) * 12; //retVal = retVal - d1.Month; //retVal = retVal - (12 - d2.Month); return retVal; } 

Comments

2

There's 3 cases: same year, previous year and other years.

If the day of the month does not matter...

public int GetTotalNumberOfMonths(DateTime start, DateTime end) { // work with dates in the right order if (start > end) { var swapper = start; start = end; end = swapper; } switch (end.Year - start.Year) { case 0: // Same year return end.Month - start.Month; case 1: // last year return (12 - start.Month) + end.Month; default: return 12 * (3 - (end.Year - start.Year)) + (12 - start.Month) + end.Month; } } 

1 Comment

If the day of the month does not matter, So the default section should be this: 12 * (end.Year - start.Year) - start.Month + end.Month;
2

The most precise way is this that return difference in months by fraction :

private double ReturnDiffereceBetweenTwoDatesInMonths(DateTime startDateTime, DateTime endDateTime) { double result = 0; double days = 0; DateTime currentDateTime = startDateTime; while (endDateTime > currentDateTime.AddMonths(1)) { result ++; currentDateTime = currentDateTime.AddMonths(1); } if (endDateTime > currentDateTime) { days = endDateTime.Subtract(currentDateTime).TotalDays; } return result + days/endDateTime.GetMonthDays; } 

Comments

2

Here is a simple solution that works at least for me. It's probably not the fastest though because it uses the cool DateTime's AddMonth feature in a loop:

public static int GetMonthsDiff(DateTime start, DateTime end) { if (start > end) return GetMonthsDiff(end, start); int months = 0; do { start = start.AddMonths(1); if (start > end) return months; months++; } while (true); } 

Comments

2

This simple static function calculates the fraction of months between two Datetimes, e.g.

  • 1.1. to 31.1. = 1.0
  • 1.4. to 15.4. = 0.5
  • 16.4. to 30.4. = 0.5
  • 1.3. to 1.4. = 1 + 1/30

The function assumes that the first date is smaller than the second date. To deal with negative time intervals one can modify the function easily by introducing a sign and a variable swap at the beginning.

public static double GetDeltaMonths(DateTime t0, DateTime t1) { DateTime t = t0; double months = 0; while(t<=t1) { int daysInMonth = DateTime.DaysInMonth(t.Year, t.Month); DateTime endOfMonth = new DateTime(t.Year, t.Month, daysInMonth); int cutDay = endOfMonth <= t1 ? daysInMonth : t1.Day; months += (cutDay - t.Day + 1) / (double) daysInMonth; t = new DateTime(t.Year, t.Month, 1).AddMonths(1); } return Math.Round(months,2); } 

Comments

2

I was working on a project that only dealt in years and months.

/// <summary> /// Get the total months between two date. This will count whole months and not care about the day. /// </summary> /// <param name="firstDate">First date.</param> /// <param name="lastDate">Last date.</param> /// <returns>Number of month apart.</returns> private static int GetTotalMonths(DateOnly firstDate, DateOnly lastDate) { int yearsApart = lastDate.Year - firstDate.Year; int monthsApart = lastDate.Month - firstDate.Month; return (yearsApart * 12) + monthsApart; } private static int GetTotalMonths(DateTime firstDate, DateTime lastDate) { return GetTotalMonths(DateOnly.FromDateTime(firstDate), DateOnly.FromDateTime(lastDate)); } 

Comments

2

Someone must have done it))

The extension method returns the number of full months between the given dates. No matter in what order the dates are received, a natural number will always be returned.No approximate calculations as in the "correct" answer.

 /// <summary> /// Returns the difference between dates in months. /// </summary> /// <param name="current">First considered date.</param> /// <param name="another">Second considered date.</param> /// <returns>The number of full months between the given dates.</returns> public static int DifferenceInMonths(this DateTime current, DateTime another) { DateTime previous, next; if (current > another) { previous = another; next = current; } else { previous = current; next = another; } return (next.Year - previous.Year) * 12 // multiply the difference in years by 12 months + next.Month - previous.Month // add difference in months + (previous.Day <= next.Day ? 0 : -1); // if the day of the next date has not reached the day of the previous one, then the last month has not yet ended } 

But if you still want to get the fractional parts of the months, you just need to add one more term to the return:

+ (next.Day - previous.Day) / DateTime.DaysInMonth(previous.Year, previous.Month)

Comments

2

Um, actually, the OP asked for something like VB's DateDiff(). It turns out that that function works very simply for months:

((LastDate.Year - FirstDate.Year) * 12) + LastDate.Month - FirstDate.Month 

seems to emulate it perfectly.

(Unless I be mistaken. I'll welcome anyone pointing out a mistake.)

Comments

1
Public Class ClassDateOperation Private prop_DifferenceInDay As Integer Private prop_DifferenceInMonth As Integer Private prop_DifferenceInYear As Integer Public Function DayMonthYearFromTwoDate(ByVal DateStart As Date, ByVal DateEnd As Date) As ClassDateOperation Dim differenceInDay As Integer Dim differenceInMonth As Integer Dim differenceInYear As Integer Dim myDate As Date DateEnd = DateEnd.AddDays(1) differenceInYear = DateEnd.Year - DateStart.Year If DateStart.Month <= DateEnd.Month Then differenceInMonth = DateEnd.Month - DateStart.Month Else differenceInYear -= 1 differenceInMonth = (12 - DateStart.Month) + DateEnd.Month End If If DateStart.Day <= DateEnd.Day Then differenceInDay = DateEnd.Day - DateStart.Day Else myDate = CDate("01/" & DateStart.AddMonths(1).Month & "/" & DateStart.Year).AddDays(-1) If differenceInMonth <> 0 Then differenceInMonth -= 1 Else differenceInMonth = 11 differenceInYear -= 1 End If differenceInDay = myDate.Day - DateStart.Day + DateEnd.Day End If prop_DifferenceInDay = differenceInDay prop_DifferenceInMonth = differenceInMonth prop_DifferenceInYear = differenceInYear Return Me End Function Public ReadOnly Property DifferenceInDay() As Integer Get Return prop_DifferenceInDay End Get End Property Public ReadOnly Property DifferenceInMonth As Integer Get Return prop_DifferenceInMonth End Get End Property Public ReadOnly Property DifferenceInYear As Integer Get Return prop_DifferenceInYear End Get End Property End Class 

Comments

1

This is from my own library, will return the difference of months between two dates.

public static int MonthDiff(DateTime d1, DateTime d2) { int retVal = 0; // Calculate the number of years represented and multiply by 12 // Substract the month number from the total // Substract the difference of the second month and 12 from the total retVal = (d1.Year - d2.Year) * 12; retVal = retVal - d1.Month; retVal = retVal - (12 - d2.Month); return retVal; } 

1 Comment

Does this work? I keep getting 11 on paper for Jan-31-2014 and Dec-31-2013
1

You can have a function something like this.

For Example, from 2012/12/27 to 2012/12/29 becomes 3 days. Likewise, from 2012/12/15 to 2013/01/15 becomes 2 months, because up to 2013/01/14 it's 1 month. from 15th it's 2nd month started.

You can remove the "=" in the second if condition, if you do not want to include both days in the calculation. i.e, from 2012/12/15 to 2013/01/15 is 1 month.

public int GetMonths(DateTime startDate, DateTime endDate) { if (startDate > endDate) { throw new Exception("Start Date is greater than the End Date"); } int months = ((endDate.Year * 12) + endDate.Month) - ((startDate.Year * 12) + startDate.Month); if (endDate.Day >= startDate.Day) { months++; } return months; } 

Comments

1

you can use the following extension: Code

public static class Ext { #region Public Methods public static int GetAge(this DateTime @this) { var today = DateTime.Today; return ((((today.Year - @this.Year) * 100) + (today.Month - @this.Month)) * 100 + today.Day - @this.Day) / 10000; } public static int DiffMonths(this DateTime @from, DateTime @to) { return (((((@to.Year - @from.Year) * 12) + (@to.Month - @from.Month)) * 100 + @to.Day - @from.Day) / 100); } public static int DiffYears(this DateTime @from, DateTime @to) { return ((((@to.Year - @from.Year) * 100) + (@to.Month - @from.Month)) * 100 + @to.Day - @from.Day) / 10000; } #endregion Public Methods } 

Implementation !

int Age; int years; int Months; //Replace your own date var d1 = new DateTime(2000, 10, 22); var d2 = new DateTime(2003, 10, 20); //Age Age = d1.GetAge(); Age = d2.GetAge(); //positive years = d1.DiffYears(d2); Months = d1.DiffMonths(d2); //negative years = d2.DiffYears(d1); Months = d2.DiffMonths(d1); //Or Months = Ext.DiffMonths(d1, d2); years = Ext.DiffYears(d1, d2); 

Comments

1

Here's a much more concise solution using VB.Net DateDiff for Year, Month, Day only. You can load the DateDiff library in C# as well.

date1 must be <= date2

VB.NET

Dim date1 = Now.AddDays(-2000) Dim date2 = Now Dim diffYears = DateDiff(DateInterval.Year, date1, date2) - If(date1.DayOfYear > date2.DayOfYear, 1, 0) Dim diffMonths = DateDiff(DateInterval.Month, date1, date2) - diffYears * 12 - If(date1.Day > date2.Day, 1, 0) Dim diffDays = If(date2.Day >= date1.Day, date2.Day - date1.Day, date2.Day + (Date.DaysInMonth(date1.Year, date1.Month) - date1.Day)) 

C#

DateTime date1 = Now.AddDays(-2000); DateTime date2 = Now; int diffYears = DateDiff(DateInterval.Year, date1, date2) - date1.DayOfYear > date2.DayOfYear ? 1 : 0; int diffMonths = DateDiff(DateInterval.Month, date1, date2) - diffYears * 12 - date1.Day > date2.Day ? 1 : 0; int diffDays = date2.Day >= date1.Day ? date2.Day - date1.Day : date2.Day + (System.DateTime.DaysInMonth(date1.Year, date1.Month) - date1.Day); 

Comments

1

This is in response to Kirk Woll's answer. I don't have enough reputation points to reply to a comment yet...

I liked Kirk's solution and was going to shamelessly rip it off and use it in my code, but when I looked through it I realized it's way too complicated. Unnecessary switching and looping, and a public constructor that is pointless to use.

Here's my rewrite:

public class DateTimeSpan { private DateTime _date1; private DateTime _date2; private int _years; private int _months; private int _days; private int _hours; private int _minutes; private int _seconds; private int _milliseconds; public int Years { get { return _years; } } public int Months { get { return _months; } } public int Days { get { return _days; } } public int Hours { get { return _hours; } } public int Minutes { get { return _minutes; } } public int Seconds { get { return _seconds; } } public int Milliseconds { get { return _milliseconds; } } public DateTimeSpan(DateTime date1, DateTime date2) { _date1 = (date1 > date2) ? date1 : date2; _date2 = (date2 < date1) ? date2 : date1; _years = _date1.Year - _date2.Year; _months = (_years * 12) + _date1.Month - _date2.Month; TimeSpan t = (_date2 - _date1); _days = t.Days; _hours = t.Hours; _minutes = t.Minutes; _seconds = t.Seconds; _milliseconds = t.Milliseconds; } public static DateTimeSpan CompareDates(DateTime date1, DateTime date2) { return new DateTimeSpan(date1, date2); } } 

Usage1, pretty much the same:

void Main() { DateTime compareTo = DateTime.Parse("8/13/2010 8:33:21 AM"); DateTime now = DateTime.Parse("2/9/2012 10:10:11 AM"); var dateSpan = new DateTimeSpan(compareTo, now); Console.WriteLine("Years: " + dateSpan.Years); Console.WriteLine("Months: " + dateSpan.Months); Console.WriteLine("Days: " + dateSpan.Days); Console.WriteLine("Hours: " + dateSpan.Hours); Console.WriteLine("Minutes: " + dateSpan.Minutes); Console.WriteLine("Seconds: " + dateSpan.Seconds); Console.WriteLine("Milliseconds: " + dateSpan.Milliseconds); } 

Usage2, similar:

void Main() { DateTime compareTo = DateTime.Parse("8/13/2010 8:33:21 AM"); DateTime now = DateTime.Parse("2/9/2012 10:10:11 AM"); Console.WriteLine("Years: " + DateTimeSpan.CompareDates(compareTo, now).Years); Console.WriteLine("Months: " + DateTimeSpan.CompareDates(compareTo, now).Months); Console.WriteLine("Days: " + DateTimeSpan.CompareDates(compareTo, now).Days); Console.WriteLine("Hours: " + DateTimeSpan.CompareDates(compareTo, now).Hours); Console.WriteLine("Minutes: " + DateTimeSpan.CompareDates(compareTo, now).Minutes); Console.WriteLine("Seconds: " + DateTimeSpan.CompareDates(compareTo, now).Seconds); Console.WriteLine("Milliseconds: " + DateTimeSpan.CompareDates(compareTo, now).Milliseconds); } 

Comments

1

In my case it is required to calculate the complete month from the start date to the day prior to this day in the next month or from start to end of month.


Ex: from 1/1/2018 to 31/1/2018 is a complete month
Ex2: from 5/1/2018 to 4/2/2018 is a complete month

so based on this here is my solution:

public static DateTime GetMonthEnd(DateTime StartDate, int MonthsCount = 1) { return StartDate.AddMonths(MonthsCount).AddDays(-1); } public static Tuple<int, int> CalcPeriod(DateTime StartDate, DateTime EndDate) { int MonthsCount = 0; Tuple<int, int> Period; while (true) { if (GetMonthEnd(StartDate) > EndDate) break; else { MonthsCount += 1; StartDate = StartDate.AddMonths(1); } } int RemainingDays = (EndDate - StartDate).Days + 1; Period = new Tuple<int, int>(MonthsCount, RemainingDays); return Period; } 

Usage:

Tuple<int, int> Period = CalcPeriod(FromDate, ToDate); 

Note: in my case it was required to calculate the remaining days after the complete months so if it's not your case you could ignore the days result or even you could change the method return from tuple to integer.

Comments

1
public static int PayableMonthsInDuration(DateTime StartDate, DateTime EndDate) { int sy = StartDate.Year; int sm = StartDate.Month; int count = 0; do { count++;if ((sy == EndDate.Year) && (sm >= EndDate.Month)) { break; } sm++;if (sm == 13) { sm = 1; sy++; } } while ((EndDate.Year >= sy) || (EndDate.Month >= sm)); return (count); } 

This solution is for Rental/subscription calculation, where difference doesn't means to be subtraction, it's meant to be the span in within those two dates.

Comments

1

I wrote a function to accomplish this, because the others ways weren't working for me.

public string getEndDate (DateTime startDate,decimal monthCount) { int y = startDate.Year; int m = startDate.Month; for (decimal i = monthCount; i > 1; i--) { m++; if (m == 12) { y++; m = 1; } } return string.Format("{0}-{1}-{2}", y.ToString(), m.ToString(), startDate.Day.ToString()); } 

3 Comments

Please answer in English (vs any invented language ...)
Why not just do startDate.AddMonths(monthCount).ToShortDateString()? This doesn't answer the original question that was asked anyway!
oh, sorry @TabbyCool , this code works good in my program! programmers rule says: first code works and then optimization! tanx for ur comment :)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.