Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaScript Time Zone is wrong for past Daylight Saving Time transition rules

In 2007, the days that we switch to daylight savings time changed. Any date that falls within the extend range of DST prior to that change is reporting an incorrect timezone offset in Chrome and Firefox. It's like Firefox and Chrome don't pay attention to the fact that DST used to have different days.

If you run the following script it will report an offset of 240 minutes. That's incorrect, it should report 300 minutes. IE10 does this correctly. Does anyone know of a fix?

alert(new Date('11/04/2004').getTimezoneOffset());

UPDATE:

Here's an interesting piece of code I just hacked together (see below). It's really surprising how far off most of the dates are in every browser but IE. Compare the begin and end dates to this: http://www.timeanddate.com/worldclock/timezone.html?n=77&syear=2000

I ended up just replacing Date's prototype for getTimezoneOffset with my own that calculates it based on a hard-coded table. That works for us because we only do business in the U.S. It's about the worst possible solution I can imagine though...

<!DOCTYPE html>
<html>
    <head>
        <title>Moment Test</title>
        <script src="http://cdnjs.cloudflare.com/ajax/libs/moment.js/2.0.0/moment.min.js"></script>
        <script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
        <script>
var lastOffset = null;
var $tbody = null;
var endDate = new Date('01/01/2021');

function addDate(d) {
    if($tbody === null)
        $tbody = $('#dates');

    var offset = d.getTimezoneOffset();
    var s = '';
    if(lastOffset != offset) {
        if(lastOffset != null)
            s = '<tr style="background-color: red;">';
        lastOffset = offset;
    }
    else {
        s = '<tr>';
    }
    var m = new moment(d);
    s += '<td>' + m.format('YYYY-MM-DD') + '</td><td>' + m.format('YYYY-MM-DDTHH:mm:ssZ') + '</td><td>' + m.format('YYYY-MM-DDTHH:mm:ss') + '</td><td>' + offset + '</td></tr>';
    $tbody.append($(s));
    d.setDate(d.getDate() + 1);

    if(d < endDate)
        window.setTimeout(function(){addDate(d)}, 0);
}

        </script>
    </head>
    <body>
        <button onclick="addDate(new Date('01/01/1980'));">Fill Table</button>
        <table border="1">
            <thead><tr><th>Date</th><th>Date 2</th><th>Date 3</th><th>TZ Offset</th></tr></thead>
            <tbody id='dates'></tbody>
        </table>
    </body>
</html>
like image 282
Brian Avatar asked Jun 05 '13 17:06

Brian


People also ask

How do you fix daylight savings time not observed by this time zone?

In Control Panel, select Clock, Language, and Region. Select Change the time zone. In the Time Zone area of the Date and Time dialog box, select Change time zone. In the Time zone list, select a time zone that does not observe daylight saving time and has the same UTC offset as your current time zone.

Does Javascript date handle Daylight Savings?

The answer is Yes. If we are considering New York, USA, then during Daylight Saving, the offset is -4, whereas it would otherwise be -5.

Does Daylight Savings mess with time zones?

From a chronobiological perspective, chronic effects are very likely because, throughout the months of DST, body and social clocks are likely set to different time zones in most people, as we explained above.

Does UTC adjust for Daylight Savings?

The switch to daylight saving time does not affect UTC. It refers to time on the zero or Greenwich meridian, which is not adjusted to reflect changes either to or from Daylight Saving Time.


2 Answers

It's actually specified behavior to use the current DST rules, and to ignore the ones in place at the particular date/time being examined. See ES5 15.9.1.8:

"The implementation of ECMAScript should not try to determine whether the exact time was subject to daylight saving time, but just whether daylight saving time would have been in effect if the current daylight saving time algorithm had been used at the time. This avoids complications such as taking into account the years that the locale observed daylight saving time year round."

The rules are: apply the current DST rules, to whatever time was specified. This results in arrant nonsense behavior, but it's what ECMAScript requires.

It's possible -- likely, even -- that this behavior will change in a future version of ECMAScript, to require actual DST rules at all points in time be used. This wasn't required initially because of the burden of shipping tzdata that it imposes on implementers. The language has become important enough, however, that probably everyone will just have to suck it up in the long run. But the change could be years away for all I know, so don't hold your breath on it.

like image 134
Jeff Walden Avatar answered Oct 16 '22 10:10

Jeff Walden


I have confirmed that this is a true bug in JavaScript.

  • Tested with common US time zones that follow daylight saving time
    • Eastern, Central, Mountain, Pacific
  • Tested in Chrome, Firefox, Safari and failed (latest versions)
  • Tested in IE 6, 7, 8, 9 and failed.
  • Tested in IE 10 and passed (not affected).
  • Tested on Windows 7, 8 and Mac OSX.

This is pretty troubling. Does anyone know the root cause?

I thought it might be a WebKit bug, but Firefox uses Gecko.

I checked various issue lists and couldn't find this particular problem anywhere. Perhaps I missed something. I'm not sure where to file a bug report, since it affects multiple places.

Perhaps it is a core JavaScript bug? I really find it hard to believe that something this basic has been overlooked by a unit test.

I thought perhaps it was just affecting Windows systems, due to the OS having Windows timezones instead of TZDB, but that doesn't appear to be the case since it happens on Mac as well.

We all know JavaScript dates are screwy, but I thought we could at least depend on this. You don't even have to look at the offset, or involve parsing. Just check the value of:

new Date(2004,10,4)  // recall, js months are 0-11, so this is Nov. 4 2004.

In 2004 in the United States, daylight saving time ended on October 31 at at 2:00 AM, when the clocks rolled back to 1:00 AM. So by Nov 4th, they should certainly all be on standard time, but they're not! For example, in Chrome dev tools on the console, with clock set to US Eastern time zone:

> new Date(2004,10,7,0,0)
  Sun Nov 07 2004 00:00:00 GMT-0400 (Eastern Daylight Time)

> new Date(2004,10,7,1,0)
  Sun Nov 07 2004 01:00:00 GMT-0500 (Eastern Standard Time)

It's putting the transition date on Nov 7th. That's the following the "First Sunday in November" rule that is presently in effect, but in 2004 the rule should have been the old one of "Last Sunday in October".

UPDATE 1

It does not appear limited to the browser. It also fails in Node.js

Node.js Screenshot

And just to prove that IE is fine, here is the output from IE10:

IE10 Screenshot

Interesting that IE and Firefox resolve the 1:00 ambiguity as Daylight Time while Chrome resolves it as Standard Time, but that is a separate issue. It does pick the correct transition date.

UPDATE 2

It's worth mentioning that in the latest Firefox 21, this issue does happen, but it presents itself differently because it's compounded by another issue that switches daylight for standard names, even though the correct offset is used. In otherwords, on Firefox, the output is like this:

Firefox Screenshot

like image 4
Matt Johnson-Pint Avatar answered Oct 16 '22 11:10

Matt Johnson-Pint