两个date之间的月差

如何计算C#中两个date之间的差异?

在C#中是否有相当于VB的DateDiff()方法。 我需要在相隔几年的两个date之间find几个月的差异。 该文件说,我可以使用TimeSpan

 TimeSpan ts = date1 - date2; 

但是这给了我几天的数据。 我不想把这个数字除以30,因为不是每个月都是30天,而且因为两个操作数的数值是相互分开的,恐怕除以30会给我一个错误的价值。

有什么build议么?

假设月份的date是不相关的(即2011.1.1与2010.12.31之间的差异为1),date1> date2给出正值,date2> date1为负值

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

或者,假设您希望两个date之间的“平均月份”数量大致相同,那么除了非常大的date差异之外,以下内容都适用。

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

请注意,如果您要使用后一种解决scheme,那么您的unit testing应该说明应用程序devise的最宽date范围,并相应地validation计算结果。


更新(感谢加里 )

如果使用“平均月份”的方法,用于“每年平均天数”的稍微更准确的数字是365.2425 。

这是一个全面的解决scheme,返回一个类似于TimeSpanDateTimeSpan ,除了它包含除时间组件之外的所有date组件。

用法:

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

输出:

年份:1
几个月:5
天:27
营业时间:1
分钟:36
秒:50
毫秒:0

为了方便起见,我将逻辑放入了DateTimeSpan结构中,但是您可以将方法CompareDates移动到您认为合适的地方。 另外请注意,哪个date在另一个之前是没有关系的。

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

如果你想要整整一个月的确切数字,总是正数(2000-01-15,2000-02-14返回0),考虑一个整月是到了下一个月的同一天(类似年龄计算)

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

编辑原因:在某些情况下,旧代码不正确:

 new { From = new DateTime(1900, 8, 31), To = new DateTime(1901, 8, 30), Result = 11 }, 

我用来testing函数的testing用例:

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

我通过MSDN在VB.NET中检查了这个方法的用法,似乎它有很多用法。 在C#中没有这样的内置方法。 (即使这不是一个好主意),你可以在C#中调用VB。

  1. Microsoft.VisualBasic.dll添加到您的项目作为参考
  2. 在代码中使用Microsoft.VisualBasic.DateAndTime.DateDiff

你可以做

 if ( date1.AddMonths(x) > date2 ) 

不pipedate如何,在几个月内(包括开始和结束)

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

我只是需要一些简单的东西,例如就业date,只有月/年进入,所以希望不同年份和月份工作。这就是我使用的,在这里只为有用

  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小提琴

您可以使用.NET时间库的DateDiff类:

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

使用野田时间 :

 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 

(示例源)

 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 

这是从我自己的图书馆,将返回两个date之间的月份的差异。

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

你可以有一个这样的function。

例如从2012/12/27到2012/12/29变成3天。 同样,从2012/12/15到2013/01/15变成2个月,因为到2013/01/14为止,是1个月。 从15日开始第二个月

如果您不想在计算中包含这两个date,则可以在第二个条件中删除“=”。 即2012/12/15至2013/01/15为1个月。

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

这为我所需要的工作。 在我的情况下,这个月的一天并不重要,因为它总是恰好是这个月的最后一天。

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

您可以使用以下扩展名: 代码

 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 } 

执行!

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

这里有一个更简洁的解决scheme,只使用VB.Net DateDiff进行年,月,日。 你也可以在C#中加载DateDiff库。

date1必须<= 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); 

这是我的贡献,以获得我认为是准确的几个月的差异:

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

用法:

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

您可以创build另一个称为DiffYears的方法,并在while循环中应用与上面相同的逻辑和AddYears而不是AddMonths。

为了能够计算出两个月份之间的差异,这是完全合乎逻辑的事情,并且在许多商业应用中都是需要的。 这里的几位编码人员提供了如下评论:“2010年5月1日”和“2010年6月16日”之间的月差,2010年12月31日至2011年1月1日的月份差异是多less?商业应用程序的基础知识。

以上是对上述2条意见的回答 – 2010年1月1日至2010年6月16日之间的月数为1个月,2010年12月31日至2011年1月1日之间的月数为0。按照上面的编码者的build议,将其计算为1.5个月和1秒是非常愚蠢的。

从事信用卡,抵押贷款处理,税务处理,租金处理,每月利息计算以及各种其他业务解决scheme的人都会同意。

问题是这样的函数不包含在C#或VB.NET中。 Datediff只考虑年份或月份组件,所以实际上是无用的。

这里有一些真实的例子,你需要和正确地计算月份:

你住在短短的18至23月的租金。 你在那里呆了几个月? 答案很简单 – 6个月

你有银行帐户,每月月底计息利息。 你把钱存在10-jun,拿出29-oct(同年)。 你有多less个月的兴趣? 非常简单的答案 – 4个月(再次多余的日子并不重要)

在商业应用程序中,大多数情况下,当你需要计算几个月的时候,这是因为你需要知道“完整的”月份,基于人类如何计算时间; 不是基于一些抽象/不相关的想法。

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

这个解决scheme是租赁/订阅计算,差异不意味着是减法,它的意思是在这两个date内的跨度。

有3起,分别是同年,上年和其他年份。

如果一个月中的某一天不重要…

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

扩展Kirks结构ToString(格式)和持续时间(长毫秒)

  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 string ToString(string format) { format = format.Replace("YYYY", Years.ToString()); format = format.Replace("MM", Months.ToString()); format = format.Replace("DD", Days.ToString()); format = format.Replace("hh", Hours.ToString()); format = format.Replace("mm", Minutes.ToString()); format = format.Replace("ss", Seconds.ToString()); format = format.Replace("ms", Milliseconds.ToString()); 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; } } 

这里没有很多明确的答案,因为你总是在做假设。

这个解决scheme计算两个date之间的月份,假设你想保存一个月的date进行比较,(这意味着在计算中考虑了一个月份的date)

例如,如果您的date为2012年1月30日,则2012年2月29日将不是一个月,但2013年3月1日将是。

它已经被彻底地testing过了,可能会在我们使用它之后清理它,但是在这里:

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

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

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; 

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 

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

Here is my solution that works (at least for me). It's probably not the fastest though because it uses the cool DateTime's AddMonth feature:

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

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

LINQ Solution,

 DateTime ToDate = DateTime.Today; DateTime FromDate = ToDate.Date.AddYears(-1).AddDays(1); int monthCount = Enumerable.Range(0, 1 + ToDate.Subtract(FromDate).Days) .Select(x => FromDate.AddDays(x)) .ToList<DateTime>() .GroupBy(z => new { z.Year, z.Month }) .Count();