Apache – Weird flex date issue

apache-flexdatetime

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;
    }

Best Answer

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.