Reputation: 1071
I need to be able to subtract 2 dates and get back the years and months between the 2.
Does anyone know of any easy ways to do this?
I have looked at the TimeSpan returned when subtracting dates but there is no 'NumberOfYears' etc option!
EDIT:
I have found the following article
http://www.codeproject.com/KB/datetime/TimePeriod.aspx?msg=4078849#xx4078849xx
it is awesome!
Upvotes: 0
Views: 415
Reputation: 18810
You could take off the ticks since the start of time (well not the start of time, but 01/01/0001) :
// Assuming date 1 is the later date
DateTime newDate = new DateTime(myDate1.Ticks - myDate2.Ticks);
// NOTE : you might need to take 1 off each property, as they start at 1
string.Format("{0} Years, {1} Months, {2} Days", newDate.Year, newDate.Month, newDate.Day);
or
You could create a module that will do your workings for you that will loop counting the number of years between the dates until either the years are equal or the year is one less in the case that the earlier month is greater. Then you can loop until the months are equal without forgetting to drop from 12 to 1.
int yearCount = 0;
int monthCount = 0;
int earliestYear = 0;
int earliestMonth = 0;
int latestYear = 0;
int latestMonth = 0;
// Get the earlier date, assuming that you haven't calculated which date is the latter already.
if (myDate1 > myDate2)
{
earliestYear = myDate2.Year;
earliestMonth = myDate2.Month;
}
else
{
latestYear = myDate1.Year;
latestMonth = myDate1.Month;
}
// Get the years between (remember not to include a year where the earlier dates month is greater than the latter. E.g. 09/2011 -> 01/2013 will only be 1 year, not 2!
while(earliestYear < latestYear && (earliestMonth <= latestMonth || earliestYear < (latestYear - 1)))
{
yearCount++;
earliestYear++;
}
// Finally get the months between, moving back to january after december.
while (earliestMonth != latestMonth)
{
monthCount++;
if (earliestMonth == 12)
{
earliestMonth = 1;
}
else
{
earliestMonth++;
}
}
string.Format("{0} years and {1} months", yearCount, monthCount);
This is untested code written on the fly to give you a rough idea.
This also assumes that you would represent there being 1 month between two dates such as 29/02/1988 and 01/03/1988 (British Date Time Format)
or
You could try using a timespan to complete the task, there is no way to get the years without a bit of manual code although I'm sure you can figure that part out :-) (e.g. something like days / 365.25
)
TimeSpan timebetween = myDate1 - myDate2;
Upvotes: 3
Reputation: 6591
You can create a DateTime with the diff in ticks.
DateTime tmp = new DateTime(date1.Ticks - date2.Ticks);
Console.WriteLine(tmp.Year - 1);
Console.WriteLine(tmp.Month - 1);
Console.WriteLine(tmp.Day - 1);
You have to subtract 1 from everything since 1/1/1 is first possible date, not 0/0/0
Upvotes: 0
Reputation: 1071
The best solution I have found is this code projects article:
http://www.codeproject.com/KB/datetime/TimePeriod.aspx?msg=4078849#xx4078849xx
Upvotes: 0
Reputation: 6451
Why not create an extension method on DateTime
which returns a Tuple<int, int>
or a custom class to serve your needs? Especially as TimeSpan
will not serve your need nicely, as you'd have to calculate from days to months and years (and take the length of every month into account.)
public static Tuple<int, int> GetYearsAndMonthsDifference(this DateTime dt1, DateTime dt2)
{
DateTime laterDate;
DateTime earlierDate;
if (dt1 > dt2)
{
earlierDate = dt2;
laterDate = dt1;
}
else
{
earlierDate = dt1;
laterDate = dt2;
}
int months = 0;
while(earlierDate.Month != laterDate.Month || earlierDate.Year != laterDate.Year)
{
months++;
earlierDate = earlierDate.AddMonths(1);
}
return Tuple.Create<int, int>(months / 12, months % 12);
}
Usage:
var dt1 = DateTime.Now;
var dt2 = new DateTime(2010, 1, 1);
var difference = dt1.GetYearsAndMonthsDifference(dt2);
Console.WriteLine(string.Format("Years: {0}", difference.Item1));
Console.WriteLine(string.Format("Months: {0}", difference.Item2));
N.B: If you do not like Item1
, Item2
then you could always create a custom structure / class with better and return this, instead of a Tuple<int, int>
.
Upvotes: 0
Reputation: 5195
Have a look here:
How to display difference between two dates as 00Y 00M
and here:
http://www.codeproject.com/KB/datetime/DateDurationCalculation1.aspx
Upvotes: 1