Closed Bug 1330307 Opened 7 years ago Closed 6 years ago

Intl.DateTimeFormat formats the date in the wrong timezone in some cases

Categories

(Core :: JavaScript: Internationalization API, defect, P3)

50 Branch
defect

Tracking

()

RESOLVED DUPLICATE of bug 1346211

People

(Reporter: levdmitriy, Unassigned)

References

Details

User Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36

Steps to reproduce:

1. Change system time zone to the Moscow (UTC +3:00). I also reproduce it with (UTC +4:00) Baku
2. Just open https://jsfiddle.net/9ygfq19n/

or run in the console:
var options = { hour: "numeric", minute: "numeric" };
var dateTimeFormat = new Intl.DateTimeFormat('en-US', options);
dateTimeFormat.format(new Date('2012/05/14 12:13:14'));


Actual results:

1:13 PM


Expected results:

12:13 PM

If you change system time zone to any other (I've tried (UTC +4) Tbilisi) - all OK
Component: Untriaged → JavaScript Engine
Product: Firefox → Core
Component: JavaScript Engine → JavaScript: Internationalization API
This is an issue with Windows' localtime_s function (which we use in js/src/vm/DateTime.cpp). Simple repro:
---
#include <ctime>
#include <iostream>

using namespace std;

static bool
ComputeLocalTime(time_t local, struct tm* ptm)
{
#if defined(_WIN32)
    return localtime_s(ptm, &local) == 0;
#else
    return localtime_r(&local, ptm);
#endif
}

int main() {
    struct tm tm{};
    if (!ComputeLocalTime(static_cast<time_t>(1336982400), &tm))
        return 0;
    cout << "hour: " << tm.tm_hour << endl;
    return 0;
}
---

This should print "hour: 12", but instead prints "hour: 11" on Windows (tested on Win10).
This seems to be a bug with daylight savings time (in 2012 which is used in comment 0, Russia used permanent DST).

Example:

var monthFormat = new Intl.DateTimeFormat("en-US", { month: "short" }).format;
var dateTimeFormat = new Intl.DateTimeFormat("en-US", { year: "numeric", month: "short", day: "numeric", hour: "numeric" }).format;
var output = "";
for (var month = 0; month < 12; month++)
{
  //output += new Date(0, month) + "\n";
  var date = new Date(0, month);
  output += date + " - " + dateTimeFormat(date) + "\n";
}
output

generates the following output on Windows (8.1):

/*
Mon Jan 01 1900 00:00:00 GMT+0100 - Jan 1, 1900, 12 AM
Thu Feb 01 1900 00:00:00 GMT+0100 - Feb 1, 1900, 12 AM
Thu Mar 01 1900 00:00:00 GMT+0100 - Mar 1, 1900, 12 AM
Sun Apr 01 1900 00:00:00 GMT+0200 - Mar 31, 1900, 11 PM
Tue May 01 1900 00:00:00 GMT+0200 - Apr 30, 1900, 11 PM
Fri Jun 01 1900 00:00:00 GMT+0200 - May 31, 1900, 11 PM
Sun Jul 01 1900 00:00:00 GMT+0200 - Jun 30, 1900, 11 PM
Wed Aug 01 1900 00:00:00 GMT+0200 - Jul 31, 1900, 11 PM
Sat Sep 01 1900 00:00:00 GMT+0200 - Aug 31, 1900, 11 PM
Mon Oct 01 1900 00:00:00 GMT+0200 - Sep 30, 1900, 11 PM
Thu Nov 01 1900 00:00:00 GMT+0100 - Nov 1, 1900, 12 AM
Sat Dec 01 1900 00:00:00 GMT+0100 - Dec 1, 1900, 12 AM

*/

On Linux, I and Mac user Wawuschel get:

/*
Mon Jan 01 1900 00:00:00 GMT+0100 (CET) - Jan 1, 1900, 12 AM
Thu Feb 01 1900 00:00:00 GMT+0100 (CET) - Feb 1, 1900, 12 AM
Thu Mar 01 1900 00:00:00 GMT+0100 (CET) - Mar 1, 1900, 12 AM
Sun Apr 01 1900 00:00:00 GMT+0100 (CET) - Apr 1, 1900, 12 AM
Tue May 01 1900 00:00:00 GMT+0100 (CET) - May 1, 1900, 12 AM
Fri Jun 01 1900 00:00:00 GMT+0100 (CET) - Jun 1, 1900, 12 AM
Sun Jul 01 1900 00:00:00 GMT+0100 (CET) - Jul 1, 1900, 12 AM
Wed Aug 01 1900 00:00:00 GMT+0100 (CET) - Aug 1, 1900, 12 AM
Sat Sep 01 1900 00:00:00 GMT+0100 (CET) - Sep 1, 1900, 12 AM
Mon Oct 01 1900 00:00:00 GMT+0100 (CET) - Oct 1, 1900, 12 AM
Thu Nov 01 1900 00:00:00 GMT+0100 (CET) - Nov 1, 1900, 12 AM
Sat Dec 01 1900 00:00:00 GMT+0100 (CET) - Dec 1, 1900, 12 AM

*/
Status: UNCONFIRMED → NEW
Ever confirmed: true
I got
Mon Jan 01 1900 00:00:00 GMT+0300 - Jan 1, 1900, 6 AM
Thu Feb 01 1900 00:00:00 GMT+0300 - Feb 1, 1900, 6 AM
Thu Mar 01 1900 00:00:00 GMT+0300 - Mar 1, 1900, 6 AM
Sun Apr 01 1900 00:00:00 GMT+0300 - Apr 1, 1900, 6 AM
Tue May 01 1900 00:00:00 GMT+0300 - May 1, 1900, 6 AM
Fri Jun 01 1900 00:00:00 GMT+0300 - Jun 1, 1900, 6 AM
Sun Jul 01 1900 00:00:00 GMT+0300 - Jul 1, 1900, 6 AM
Wed Aug 01 1900 00:00:00 GMT+0300 - Aug 1, 1900, 6 AM
Sat Sep 01 1900 00:00:00 GMT+0300 - Sep 1, 1900, 6 AM
Mon Oct 01 1900 00:00:00 GMT+0300 - Oct 1, 1900, 6 AM
Thu Nov 01 1900 00:00:00 GMT+0300 - Nov 1, 1900, 6 AM
Sat Dec 01 1900 00:00:00 GMT+0300 - Dec 1, 1900, 6 AM
on Win7.
Is the latest timezone update applied?

(In reply to Sebastian Hengst [:aryx][:archaeopteryx] (needinfo on intermittent or backout) from comment #2)
> Mon Jan 01 1900 00:00:00 GMT+0100 - Jan 1, 1900, 12 AM

Why GMT+0100? did you change the timezone before testing?
https://tc39.github.io/ecma402/#sec-tolocaltime
> If the calendar is "gregory", then the calculations must match the algorithms specified in ES2017, 20.3.1.

Hm, then this is definitely a bug of the Windows implementation.
(In reply to Masatoshi Kimura [:emk] from comment #3)
> Is the latest timezone update applied?
Yes (using Windows 8.1 and no updates offered).

> (In reply to Sebastian Hengst [:aryx][:archaeopteryx] (needinfo on
> intermittent or backout) from comment #2)
> > Mon Jan 01 1900 00:00:00 GMT+0100 - Jan 1, 1900, 12 AM
> 
> Why GMT+0100? did you change the timezone before testing?
I kept my local time because I stumbled upon this bug in bug 1331608.
Note, there's a related open spec question at https://github.com/tc39/ecma262/pull/778 . The logic of timezones that's referenced by local dates in the Date constructor doesn't handle historical timezone changes well. It is based on a single timezone offset from GMT, with only the DST offset being based on the current time. By contrast, ICU does handle the historical changes well. I think this is a factor in mismatches here generally. You'll find a similar mismatch in V8 and JSC, reproducible on Linux as well.
Blocks: 285663
Priority: -- → P3
Dup'ing forward to bug 1346211 which should have fixed this problem. Please reopen if the issue is still present. Thanks!
Status: NEW → RESOLVED
Closed: 6 years ago
Resolution: --- → DUPLICATE
You need to log in before you can comment on or make changes to this bug.