Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript timezone bug between Feb 9, 1942-Sept 30 1945 [duplicate]

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 216
Brian Avatar asked Jun 05 '13 17:06

Brian


People also ask

Do JavaScript dates have timezones?

JavaScript's internal representation uses the “universal” UTC time but by the time the date/time is displayed, it has probably been localized per the timezone settings on the user's computer. And, indeed, that's the way JavaScript is set up to work.

How do I get timezone offset?

The JavaScript getTimezoneOffset() method is used to find the timezone offset. It returns the timezone difference in minutes, between the UTC and the current local time. If the returned value is positive, local timezone is behind the UTC and if it is negative, the local timezone if ahead of UTC.

What timezone is JavaScript new date?

The JavaScript Date object tracks time in UTC internally, but most of its methods (except the ones with UTC in their name) return output in the local time of the visitor (the time zone the visitor's computer is in).

How do I get current timezone in typescript?

To get the current browser's time zone, you can use the getTimezoneOffset() method from the JavaScript Date object. The getTimezoneOffset() returns the time difference, in minutes, between UTC time and local 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 123
Jeff Walden Avatar answered Oct 05 '22 04: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 41
Matt Johnson-Pint Avatar answered Oct 05 '22 06:10

Matt Johnson-Pint