Différence en mois entre deux dates

Comment calculer la différence en mois entre deux dates en C #?

Est-ce qu’il y a l’équivalent de la méthode DateDiff() de VB en C #. Je dois trouver la différence en mois entre deux dates séparées par des années. La documentation dit que je peux utiliser TimeSpan comme:

 TimeSpan ts = date1 - date2; 

mais cela me donne des données en jours. Je ne veux pas diviser ce nombre par 30 parce que tous les mois ne sont pas 30 jours et que les deux valeurs d’opérande sont assez éloignées l’une de l’autre, j’ai bien peur que la division par 30 me donne une mauvaise valeur.

Aucune suggestion?

En supposant que le jour du mois est sans importance (c’est-à-dire que le diff entre 2011.1.1 et 2010.12.31 est 1), avec date1> date2 donnant une valeur positive et date2> date1 une valeur négative

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

Ou, en supposant que vous vouliez un nombre approximatif de «mois moyens» entre les deux dates, les éléments suivants devraient fonctionner pour toutes les différences de dates, sauf très grandes.

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

Notez que si vous utilisiez cette dernière solution, vos tests unitaires devraient indiquer la plage de dates la plus large avec laquelle votre application est conçue pour fonctionner et valider les résultats du calcul en conséquence.


Mise à jour (avec merci à Gary )

Si vous utilisez la méthode des «mois moyens», le nombre à utiliser pour le «nombre moyen de jours par an» est de 365,2425 .

Voici une solution complète pour retourner un DateTimeSpan , similaire à un TimeSpan , sauf qu’il inclut tous les composants de date en plus des composants de temps.

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); } 

Les sorties:

Années: 1
Mois: 5
Jours: 27
Heures: 1
Minutes: 36
Secondes: 50
Millisecondes: 0

Pour plus de commodité, j’ai regroupé la logique dans la structure DateTimeSpan , mais vous pouvez déplacer la méthode CompareDates où bon vous semble. Notez également que peu importe la date qui précède l’autre.

 public struct DateTimeSpan { private readonly int years; private readonly int months; private readonly int days; private readonly int hours; private readonly int minutes; private readonly int seconds; private readonly int milliseconds; public DateTimeSpan(int years, int months, int days, int hours, int minutes, int seconds, int milliseconds) { this.years = years; this.months = months; this.days = days; this.hours = hours; this.minutes = minutes; this.seconds = seconds; this.milliseconds = 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; } } 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; } } 

Si vous voulez le nombre exact de mois complets, toujours positif (2000-01-15, 2000-02-14 renvoie 0), le fait de considérer un mois entier correspond au jour où vous arrivez le même mois (un peu comme le calcul de l’âge)

 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; } } 

Modifier la raison: l'ancien code n'était pas correct dans certains cas comme:

 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 }, }; 

Vous pourriez faire

 if ( date1.AddMonths(x) > date2 ) 

J’ai vérifié l’utilisation de cette méthode dans VB.NET via MSDN et il semble y avoir beaucoup d’utilisations. Il n’y a pas de méthode intégrée dans C #. (Même si ce n’est pas une bonne idée), vous pouvez appeler les VB en C #.

  1. Ajouter Microsoft.VisualBasic.dll à votre projet comme référence
  2. utiliser Microsoft.VisualBasic.DateAndTime.DateDiff dans votre code

Pour obtenir la différence en mois (début et fin inclus), indépendamment des 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); 

J’avais juste besoin de quelque chose de simple pour répondre, par exemple, aux dates d’emploi où seul le mois / année est inscrit, donc je voulais des années et des mois distincts.

 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 }; } 

Violon .NET

Vous pouvez utiliser la classe DateDiff de la bibliothèque de périodes pour .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 

Utilisez 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 

(exemple de source)

Cela a fonctionné pour ce que j’en avais besoin. Le jour du mois n’a pas d’importance dans mon cas, car il arrive toujours que ce soit le dernier jour du mois.

 public static int MonthDiff(DateTime d1, DateTime d2){ int retVal = 0; if (d1.Month 

La manière la plus précise est la suivante: la différence de rendement en mois par 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; } 

Voici une solution simple qui fonctionne au moins pour moi. Ce n’est probablement pas le plus rapide car il utilise la fonctionnalité AddMonth de DateTime dans une boucle:

 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); } 
 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 

Ceci est de ma propre bibliothèque, retournera la différence de mois entre deux 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; } 

Vous pouvez avoir une fonction comme celle-ci.

Par exemple, du 2012/12/27 au 2012/12/29 devient 3 jours. De même, de 2012/12/15 à 2013/01/15 devient 2 mois, car jusqu’en 2013/01/14, c’est 1 mois. à partir du 15 c’est le 2ème mois a commencé.

Vous pouvez supprimer le “=” dans la deuxième condition si vous ne souhaitez pas inclure les deux jours dans le calcul. Par exemple, de 2012/12/15 à 2013/01/15 est de 1 mois.

 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; } 

vous pouvez utiliser l’extension suivante: 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 } 

La mise en oeuvre !

 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); 

Voici une solution beaucoup plus concise utilisant VB.Net DateDiff pour l’année, le mois et le jour seulement. Vous pouvez également charger la bibliothèque DateDiff en C #.

date1 doit être < = 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); 

Voici ma consortingbution pour obtenir une différence dans les mois que j’ai trouvé exacts:

 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 ) ); 

Vous pouvez créer une autre méthode appelée DiffYears et appliquer exactement la même logique que ci-dessus et AddYears au lieu de AddMonths dans la boucle while.

Ceci est en réponse à la réponse de Kirk Woll. Je n’ai pas assez de points de réputation pour répondre à un commentaire …

J’aimais bien la solution de Kirk et j’allais la déchirer sans vergogne et l’utiliser dans mon code, mais quand je l’ai parcourue, j’ai réalisé que c’était trop compliqué. Commutation et boucle inutiles, et constructeur public inutile à utiliser.

Voici ma réécriture:

 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); } } 

Utilisation1, à peu près la même chose:

 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, similaire:

 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); } 

Dans mon cas, il est nécessaire de calculer le mois complet à partir de la date de début jusqu’au jour précédent dans le mois suivant ou du début à la fin du mois.

Ex: du 1/1/2018 au 31/1/2018 est un mois complet
Ex2: du 01/05/2018 au 2/2/2018 est un mois complet

Donc, sur cette base, voici ma solution:

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

Usage:

 Tuple Period = CalcPeriod(FromDate, ToDate); 

Note: dans mon cas, il était nécessaire de calculer les jours restants après les mois complets, donc si ce n’est pas votre cas, vous pouvez ignorer le résultat des jours ou même modifier la méthode return de tuple à integer.

 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); } 

Cette solution est pour le calcul de location / abonnement, où la différence ne signifie pas être la soustraction, elle est censée être la scope dans ces deux dates.

Il y a 3 cas: même année, année précédente et autres années.

Si le jour du mois n’a pas d’importance …

 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; } } 

J’ai écrit une fonction pour y parvenir, car les autres méthodes ne fonctionnaient pas pour moi.

 public ssortingng 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 ssortingng.Format("{0}-{1}-{2}", y.ToSsortingng(), m.ToSsortingng(), startDate.Day.ToSsortingng()); } 

Ma compréhension de la différence totale de mois entre 2 dates a une partie intégrale et une partie fractionnaire (la date est importante).

La partie intégrale est la différence de mois entiers.

La fraction, pour moi, est la différence du% du jour (par rapport aux jours entiers du mois) entre le début et la fin du mois.

 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; } } 

Avec cette extension, voici les résultats:

 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 

There are not a lot of clear answers on this because you are always assuming things.

This solution calculates between two dates the months between assuming you want to save the day of month for comparison, (meaning that the day of the month is considered in the calculation)

Example, if you have a date of 30 Jan 2012, 29 Feb 2012 will not be a month but 01 March 2013 will.

It’s been tested pretty thoroughly, probably will clean it up later as we use it, but here:

 private static int TotalMonthDifference(DateTime dtThis, DateTime dtOther) { int intReturn = 0; bool sameMonth = false; if (dtOther.Date < dtThis.Date) //used for an error catch in program, returns -1 intReturn--; int dayOfMonth = dtThis.Day; //captures the month of day for when it adds a month and doesn't have that many days int daysinMonth = 0; //used to caputre how many days are in the month while (dtOther.Date > dtThis.Date) //while Other date is still under the other { dtThis = dtThis.AddMonths(1); //as we loop, we just keep adding a month for testing daysinMonth = DateTime.DaysInMonth(dtThis.Year, dtThis.Month); //grabs the days in the current tested month if (dtThis.Day != dayOfMonth) //Example 30 Jan 2013 will go to 28 Feb when a month is added, so when it goes to march it will be 28th and not 30th { if (daysinMonth < dayOfMonth) // uses day in month max if can't set back to day of month dtThis.AddDays(daysinMonth - dtThis.Day); else dtThis.AddDays(dayOfMonth - dtThis.Day); } if (((dtOther.Year == dtThis.Year) && (dtOther.Month == dtThis.Month))) //If the loop puts it in the same month and year { if (dtOther.Day >= dayOfMonth) //check to see if it is the same day or later to add one to month intReturn++; sameMonth = true; //sets this to cancel out of the normal counting of month } if ((!sameMonth)&&(dtOther.Date > dtThis.Date))//so as long as it didn't reach the same month (or if i started in the same month, one month ahead, add a month) intReturn++; } return intReturn; //return month } 

To be able to calculate the difference between 2 dates in months is a perfectly logical thing to do, and is needed in many business applications. The several coders here who have provided comments such as – what’s the difference in months between “May 1,2010” and “June 16,2010, what’s the difference in months between 31 December 2010 and 1 Jan 2011? — have failed to understand the very basics of business applications.

Here is the answer to the above 2 comments – The number of months between 1-may-2010 and 16-jun-2010 is 1 month, the number of months between 31-dec-2010 and 1-jan-2011 is 0. It would be very foolish to calculate them as 1.5 months and 1 second, as the coders above have suggested.

People who have worked on credit card, mortgage processing, tax processing, rent processing, monthly interest calculations and a vast variety of other business solutions would agree.

Problem is that such a function is not included in C# or VB.NET for that matter. Datediff only takes into account years or the month component, so is actually useless.

Here are some real-life examples of where you need to and correctly can calculate months:

You lived in a short-term rental from 18-feb to 23-aug. How many months did you stay there? The answer is a simple – 6 months

You have a bank acount where interest is calculated and paid at the end of every month. You deposit money on 10-jun and take it out 29-oct (same year). How many months do you get interest for? Very simple answer- 4 months (again the extra days do not matter)

In business applications, most of the time, when you need to calculate months, it is because you need to know ‘full’ months based on how humans calculate time; not based on some abstract/irrelevant thoughts.

Expanded Kirks struct with ToSsortingng(format) and Duration(long ms)

  public struct DateTimeSpan { private readonly int years; private readonly int months; private readonly int days; private readonly int hours; private readonly int minutes; private readonly int seconds; private readonly int milliseconds; public DateTimeSpan(int years, int months, int days, int hours, int minutes, int seconds, int milliseconds) { this.years = years; this.months = months; this.days = days; this.hours = hours; this.minutes = minutes; this.seconds = seconds; this.milliseconds = 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; } } enum Phase { Years, Months, Days, Done } public ssortingng ToSsortingng(ssortingng format) { format = format.Replace("YYYY", Years.ToSsortingng()); format = format.Replace("MM", Months.ToSsortingng()); format = format.Replace("DD", Days.ToSsortingng()); format = format.Replace("hh", Hours.ToSsortingng()); format = format.Replace("mm", Minutes.ToSsortingng()); format = format.Replace("ss", Seconds.ToSsortingng()); format = format.Replace("ms", Milliseconds.ToSsortingng()); return format; } public static DateTimeSpan Duration(long ms) { DateTime dt = new DateTime(); return CompareDates(dt, dt.AddMilliseconds(ms)); } 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(); 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); } 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; } } 
  var dt1 = (DateTime.Now.Year * 12) + DateTime.Now.Month; var dt2 = (DateTime.Now.AddMonths(-13).Year * 12) + DateTime.Now.AddMonths(-13).Month; Console.WriteLine(dt1); Console.WriteLine(dt2); Console.WriteLine((dt1 - dt2)); 

Here’s how we approach this:

 public static int MonthDiff(DateTime date1, DateTime date2) { if (date1.Month < date2.Month) { return (date2.Year - date1.Year) * 12 + date2.Month - date1.Month; } else { return (date2.Year - date1.Year - 1) * 12 + date2.Month - date1.Month + 12; } } 
 int nMonths = 0; if (FDate.ToDateTime().Year == TDate.ToDateTime().Year) nMonths = TDate.ToDateTime().Month - FDate.ToDateTime().Month; else nMonths = (12 - FDate.Month) + TDate.Month;