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);
}
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();
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;
}
}
int months = (laterDate.Year - currentDate.Year) * 12 + laterDate.Month - currentDate.Month;
/// <summary>
/// Calculates the difference in full months between the current System.DateTime object and a later date.
/// </summary>
/// <param name="currentDate">The date of birth.</param>
/// <param name="laterDate">The date on which to calculate the age.</param>
/// <returns>Difference in months to a later day. 0 is returned as minimum.</returns>
public static int Months(this DateTime currentDate, DateTime laterDate)
{
int months;
months = (laterDate.Year - currentDate.Year) * 12 + laterDate.Month - currentDate.Month;
if (months > 0)
{
if (laterDate.Date < currentDate.Date.AddMonths(months))
{
// The last month is not a full month.
// Reduce the month count by one.
months--;
}
}
else
{
months = 0;
}
return months;
}
This is an extension method to DateTime. Of course, you can remove static and this to use it as is. /// <summary>
/// Calculates the difference in decimal months between the current System.DateTime object and a later date.
/// </summary>
/// <param name="currentDate">The date of birth.</param>
/// <param name="laterDate">The date on which to calculate the age.</param>
/// <returns>Difference in decimal months to a later day. 0 is returned as minimum.</returns>
public static double TotalMonths(DateTime currentDate, DateTime laterDate)
{
double months = 0;
double firstPart = 0;
double lastPart = 0;
months = (laterDate.Year - currentDate.Year) * 12 + laterDate.Month - currentDate.Month;
if (months > 0)
{
firstPart = (double)currentDate.Day / DateTime.DaysInMonth(currentDate.Year, currentDate.Month);
lastPart = (double)laterDate.Day / DateTime.DaysInMonth(laterDate.Year, laterDate.Month);
}
else
{
months = 0;
}
return months - firstPart + lastPart;
}
Of course, this can be turned into an extension of DateTime should you prefer so.
Open in new window
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.
Open in new window