2

Given a DateTime object (last purchase) can I compare against DateTime.Now to return a new DateTime object that contains, years, months, days, hours and seconds?

I can compare dates and return the number of years however, I need all details down to the second.

Any help or examples would be appreciated

sam
  • 21
  • 1
  • The problem with returning a DateTime from a comparison of two dates is that a DateTime represents a specific date. So, even if you could do something like that, what you'd end up with is something like 'May 5 2011 - Jan 1 2011 = Feb 24 2011' or some such. Which is nonsensical. – AllenG May 07 '11 at 20:19

7 Answers7

2

You don't want to have a new DateTime object. What you want to have is a TimeSpan. And that's what you get if you subtract DateTime instances:

TimeSpan difference = DateTime.Now - yourDate
Achim
  • 15,415
  • 15
  • 80
  • 144
  • this won't provide years and months – sam May 07 '11 at 19:57
  • 2
    That is correct, but that is because months and years needs to be anchored. What you're looking for is a period of time, one that goes from one date to another, but still the concept of "months" will be fuzzy. For instance, if the period of time between 1st of January and 1st of March is 3 months, is the same length of time 3 months if you count from 1st of June (hint: the days doesn't line up.) – Lasse V. Karlsen May 07 '11 at 21:01
  • Sometimes, things are not entirely logical and that's where problems arise. Looking at someones age, one can say "I'm 25 years, 3 months and 6 days old". It's a fact, that this scientifically won't mean much. But most humans will understand this a lot better than saying that you are over 9200 days old. So the question is, does Sam want to provide a scientifically correct value or something humanly readable? – Jacco May 08 '11 at 11:28
  • In a general framework I only expect the "entirely logical" solutions. If he wants a custom logic which makes sense in his use case, he has to implement it. Either as an extension method for TimeSpan or for DateTime. – Achim May 08 '11 at 12:51
1

No, you can't, because a DateTime represents an absolute point in time, not a span of time. The correct object to use for the difference is TimeSpan. It has properties for all the relevant time units. You can get one by just subtracting two DateTimes:

TimeSpan ts = DateTime.Now - purchaseDate;
Matti Virkkunen
  • 63,558
  • 9
  • 127
  • 159
  • I need an object that will contain years, months etc. I dont believe a TimeSpan offers this? – sam May 07 '11 at 19:48
  • @sam: How long is one month? How about one year? – Matti Virkkunen May 07 '11 at 19:50
  • varies on the month not to mention leap years? – sam May 07 '11 at 19:51
  • @sam: So how is one supposed to calculate the number of months between two days then? – Matti Virkkunen May 07 '11 at 19:51
  • do you mean months between two dates? – sam May 07 '11 at 19:53
  • @sam: ...yes, that's what I mean. You need to be exact about these things when working with a computer. – Matti Virkkunen May 07 '11 at 19:54
  • i am surprised there is not an object that can do this accurately. I need to report the number of years, months, days, hours, minutes and sconds that have passed since a given date. – sam May 07 '11 at 19:57
  • @sam: That's because there is no such thing as "the number of months between two dates". You can get a decent approximation by using 30 days for a month and 365 days for a year, but it will drift as the difference grows. A `TimeSpan` gets you all the way to days, and you can use maths to figure out the rest from there. – Matti Virkkunen May 07 '11 at 19:59
  • 1
    @sam - you will be able to get exactly what you are after, of course - it will just involve some coding on your part. there's no object in the framework that gives you what you need – Paul Nearney May 07 '11 at 20:03
  • thanks Paul, that is what i was looking for, do you know if anyone has done this before? I'm sure it would have been needed for a variety of applications. – sam May 07 '11 at 20:07
  • @sam: It's two simple calculations. I bet most people would have something like that memorized. – Matti Virkkunen May 07 '11 at 20:07
  • using your above calculation it is not accurate – sam May 07 '11 at 20:08
  • exact number of years, days, months, hours, minutes, seconds passed – sam May 07 '11 at 20:11
  • @sam: Fine, since you don't seem to be able to define it, at least give me an example. What's the "exact difference" between, say, the 29th of February 2004 and the 28th of February 2005? – Matti Virkkunen May 07 '11 at 20:13
  • @sam - Lee's answer below looks promising – Paul Nearney May 07 '11 at 20:15
0

You can use the TimeSpan to compare two dates. Have a look at

DateTime date1 = new DateTime(2010, 1, 1, 8, 0, 15);
DateTime date2 = new DateTime(2010, 8, 18, 13, 30, 30);
// Calculate the interval between the two dates.
TimeSpan interval = date2 - date1;

Years and months have to be calculated through custom coding as month is a variable unit of measure but since TimeSpan tell you the days you can calculate months and years yourself.

Have a look at this post.

Have a look at this forum.

Hope this help.

Community
  • 1
  • 1
FIre Panda
  • 6,537
  • 2
  • 25
  • 38
  • this won't provide years and months – sam May 07 '11 at 19:57
  • 1
    Years and months you have to calculate through custom coding as month is a variable unit of measure but since TimeSpan tell you the days you can calculate months and years yourself. – FIre Panda May 07 '11 at 20:10
0

TimeSpan is the correct way to handle this, however, if you don't want to do the conversion of months/years yourself, you can always use some recursive method to subtract years until you get to the correct year, months until you get to the correct month, days until you get to the correct day, etc. It would suck and be ugly, though.

Also, you'd need a custom object that would hold the data for you.

A rough cut would be something like

DateTime original = [Whatever]
DateTime compare = [Whatever]
DateTimeDiff difference = GetDifference(original, compare)

GetDifference(DateTime original, DateTime compare)
{
  DateTimeDiff difference = new DateTimeDifference
  while(!original.Equals(compare) && original.Year >= compare.Year)
  {
     original.AddYears(-1);
     difference.Years++;
  }
  <snip...  //more code to do the same thing for months, days, hours, etc.)
}

Like I said, it would suck and be ugly, but you could do it.

AllenG
  • 8,112
  • 29
  • 40
0

This library includes the class DateDiff with support of Year and Months:

// ----------------------------------------------------------------------
public void DateDiffSample()
{
  DateTime date1 = new DateTime( 2009, 11, 8, 7, 13, 59 );
  Console.WriteLine( "Date1: {0}", date1 );
  // > Date1: 08.11.2009 07:13:59
  DateTime date2 = new DateTime( 2011, 3, 20, 19, 55, 28 );
  Console.WriteLine( "Date2: {0}", date2 );
  // > Date2: 20.03.2011 19:55:28

  DateDiff dateDiff = new DateDiff( date1, date2 );

  // differences
  Console.WriteLine( "DateDiff.Years: {0}", dateDiff.Years );
  // > DateDiff.Years: 1
  Console.WriteLine( "DateDiff.Quarters: {0}", dateDiff.Quarters );
  // > DateDiff.Quarters: 5
  Console.WriteLine( "DateDiff.Months: {0}", dateDiff.Months );
  // > DateDiff.Months: 16
  Console.WriteLine( "DateDiff.Weeks: {0}", dateDiff.Weeks );
  // > DateDiff.Weeks: 70
  Console.WriteLine( "DateDiff.Days: {0}", dateDiff.Days );
  // > DateDiff.Days: 497
  Console.WriteLine( "DateDiff.Weekdays: {0}", dateDiff.Weekdays );
  // > DateDiff.Weekdays: 71
  Console.WriteLine( "DateDiff.Hours: {0}", dateDiff.Hours );
  // > DateDiff.Hours: 11940
  Console.WriteLine( "DateDiff.Minutes: {0}", dateDiff.Minutes );
  // > DateDiff.Minutes: 716441
  Console.WriteLine( "DateDiff.Seconds: {0}", dateDiff.Seconds );
  // > DateDiff.Seconds: 42986489
} // DateDiffSample
  • @Lee: Many thanks :) The Microsoft library Microsoft.VisualBasic includes a DateDiff class, which unfortunately is useless. [link](http://msdn.microsoft.com/en-us/library/ms127413.aspx). See also [link](http://valcsgal.blogspot.com/2005/01/datediff-in-c.html) –  May 09 '11 at 13:47
  • Yeah - I had originally thought the DateDiff function would do the trick but after looking into it more I realised it's pretty pants. – Lee Gunn May 09 '11 at 13:53
0

If you want years and months you have to write your own code. It's actually tricky to write this code with an output which is 100% correct due to the different leapyear issues.

Here are a couple of tricky special cases (Note 2012 is a leap year, 2011 isn't):

  1. Between February 28th 2010 and February 28th 2011 - it is 1y, 0m, 0d
  2. Between February 28th 2011 and February 28th 2012 - it is 1y, 11m, 28d
  3. Between February 28th 2011 and February 29th 2012 - it is 1y, 0m, 0d
  4. Between February 29th 2012 and February 28th 2013 - it is 1y, 0m, 0d
  5. Between February 10th 2011 and March 9th 2011 - it is 0y, 0m, 27d
  6. Between February 10th 2012 and March 9th 2012 - it is 0y, 0m, 28d

I think you need to implement something like AllenG's algorithm with a few modifications

  1. You need to start with the earliest datetime (datetime1). Make sure that it is earliest.
  2. Loop until datetime1.AddYears(1) compares as greater than or equal to your latest datetime (datetime2). Make sure to compare the entire datetimes and not just the year property of starttime and endttime.

    • Increment a year counter on each iteration.
    • actually add a year to your datetime1 copy.
  3. Start with the datetime1 copy (to which you have added years in step 2)

  4. Loop until datetime1.AddMonths(1) compares as greater than or equal to your latest datetime (datetime2). Again: Make sure you compare the entire datetimes and not just the month component.
    • Increment a month counter on each iteration.
    • actually add a month to your datetime1 copy.
  5. etc. etc

This algorithm ensures that you are calculating your years, months, days, hours, minutes and seconds differences using the right excerpt of the underlying calendar.

Simen S
  • 3,210
  • 18
  • 24
-1

I think you need to combine the TimeSpan and some custom calculations. This, because you would like the years and months, which have a variable length. In addition you also want the number of hours, minutes and seconds. I think this approach would serve your needs:

var date1 = new DateTime(2010, 1, 1, 8, 0, 15);
var date2 = new DateTime(2007, 8, 18, 13, 30, 30);

var differenceYears = date1.Year - date2.Year;
var tempDate = date2.AddYears(differenceYears);
var differenceMonths = date1.Month - tempDate.Month;
if (differenceMonths < 0)
{
    differenceMonths += 12;
    differenceYears--;
}
tempDate = date2.AddYears(differenceYears).AddMonths(differenceMonths);
var additionalTimeSpan = date1 - tempDate;
var differenceDays = additionalTimeSpan.Days;
var differenceHours = additionalTimeSpan.Hours;
var differenceMinutes = additionalTimeSpan.Minutes;
var differenceSeconds = additionalTimeSpan.Seconds;
Jacco
  • 3,251
  • 1
  • 19
  • 29
  • -1 I don't think this logic will work. Your `tempdate` will frequently end up being subsequent to the end date (in the wrong year). Even though you handle negative month differences, your code will fail in special cases involving leap years. – Simen S May 07 '11 at 20:45
  • Okay, point taken. I agree this code is not bullet proof, which I did not notice myself. Thank you for your comment. But do you agree that the way of thinking is the way to go, or can't this be done? – Jacco May 07 '11 at 20:51