In measuring an interval, between two dates, and giving the result as a string in the form of "1Y 2M 3D", the natural assumption is to use the .NET TimeSpan class. But this assumption falls short because the TimeSpan measures only days, hours, minutes, and seconds and does not give any information about the number of, for example, elapsed months. Or years for that matter. That means you are left having to delve into the calendar to know how many days in a particular month and so on.
A helper method that can be used to solve the problem is...
private static String Interval(DateTime start, DateTime end)
{
if (end <= start)
{
throw new Exception("Invalid interval");
}
int days = 0;
int months = 0;
int years = 0;
DateTime temp = start;
while (start.AddYears(years) <= end)
{
++years;
}
--years;
temp = temp.AddYears(years);
while (temp.AddMonths(months) <= end)
{
++months;
}
--months;
temp = temp.AddMonths(months);
while (temp.AddDays(days) <= end)
{
++days;
}
--days;
StringBuilder result = new StringBuilder();
if (years > 0)
{
result.AppendFormat("{0}Y ", years);
}
if (months > 0)
{
result.AppendFormat("{0}M ", months);
}
if (days > 0)
{
result.AppendFormat("{0}D", days);
}
return result.ToString();
}
This method increments various counters between two dates using native .NET methods and avoids having to use the calendar.
It produces these results
Start 22 Oct 2013 End 28 Oct 2013 => 6D
Start 23 Aug 2013 End 28 Oct 2013 => 2M 5D
Start 1 Jan 2012 End 28 Oct 2013 => 1Y 9M 27D
And so on...
You can use the same technique to resolve the interval down to minutes and seconds. And you can introduce weeks into the method by adding another variable and looping on it.
while (temp.AddDays(weeks*7) <= end)
{
++weeks;
}
--weeks;
temp = temp.AddDays(weeks*7);
I'm sorry for the poor formatting, it seems the code formatter has gone south.
Triva: the legendary Jon Skeet took a crack at this same question, but then wrote that he didn't have time to complete the answer. How to get difference between two dates in Year/Month/Week/Day?