tags:

views:

544

answers:

2

Flex is driving me CRAZY and I think it's some weird gotcha with how it handles leap years and none leap years. So here's my example. I have the below dateDiff method that finds the number of days or milliseconds between two dates. If I run the following three statements I get some weird issues.

     dateDiff("date", new Date(2010, 0,1), new Date(2010, 0, 31));
 dateDiff("date", new Date(2010, 1,1), new Date(2010, 1, 28));
 dateDiff("date", new Date(2010, 2,1), new Date(2010, 2, 31));
 dateDiff("date", new Date(2010, 3,1), new Date(2010, 3, 30));

If you were to look at the date comparisons above you would expect to get 30, 27, 30, 29 as the number of days between the dates. There weird part is that I get 29 when comparing March 1 to March 31. Why is that? Is it something to do with February only having 28 days? If anyone has ANY input on this that would be greatly appreciated.

public static function dateDiff( datePart:String, startDate:Date, endDate:Date ):Number 
 {
  var _returnValue:Number = 0;

  switch (datePart) {
   case "milliseconds":
    _returnValue = endDate.time - startDate.time;
    break;
   case "date":
    // TODO: Need to figure out DST problem i.e. 23 hours at DST start, 25 at end.
    // Math.floor causes rounding down error with DST start at dayOfYear
    _returnValue = Math.floor(dateDiff("milliseconds", startDate, endDate)/(1000 * 60 * 60 * 24));
    break;
  }

  return _returnValue;
 }
A: 

You have part of the answer in your comment: 2010-Mar-01 0:00 until 2010-Mar-31 0:00 is thirty (!) days minus one hour (because Mar 14 is DST start in 2010). Since you floor the result of your division, you get 29.

Edit: This answer is of course based on the assumption that the time property of Date takes DST into account. This would explain your problem; I didn't check it, however.

balpha
+3  A: 

This is not a leap year problem, but rather a daylight savings time problem.

To correct the code to account for DST, you need to look at the timezoneOffset of both dates to determine if the date range is spanning a DST boundary.

var adjustment:Number = ( startDate.timezoneOffset - endDate.timezoneOffset ) * 60 * 1000;
_returnValue = endDate.time - startDate.time + adjustment;

This will get the difference between the two time zones (in minutes), convert that value to milliseconds, and then apply the timezone difference to the millisecond difference to "cancel out" the DST boundary.

Naturally, when both numbers are in the same time zone, the adjustment value becomes 0 and the time values are not adjusted.

darronschall
That's awesome!! Thank you very much for posting the code sample. That fixes my problem perfectly.
CodeMonkey