26
votes

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>
2
What OS are you on, and what is your computer's time zone setting?Matt Johnson-Pint
This is shocking, but I have confirmed this on Windows 8 with Chrome 27 and Eastern Time (US)Matt Johnson-Pint
I have also just confirmed on all US time zones, in Chrome and Firefox (latest) on Windows 7 and 8, in Safari, Chrome and Firefox on Mac. This is pretty troubling... Does anyone know the root cause? Did a TZDB update get messed up?Matt Johnson-Pint
@David - the item you linked is unrelated. This is a true bug in FF and Chrome.Matt Johnson-Pint

2 Answers

33
votes

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.

4
votes

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