When looking at the valueOf value of a date object at the beggining of a year i expected to always receive zero seconds. The following code shows that until 1917 there was an offset of 54 seconds or 40 seconds in chrome. in IE i receive 0 seconds for all years.
Is there a reason for this? it seems to only happen in the last chrome version
for(var i=0; i<2020;i++)
if(!new Date(i,0,1).valueOf().toString().match("00000$"))
console.log({
y:i,
s: new Date(i,0,1).valueOf().toString().match(/(\d{2})\d{3}$/)[1]})
When looking at the valueOf value of a date object at the beggining of a year i expected to always receive zero seconds. The following code shows that until 1917 there was an offset of 54 seconds or 40 seconds in chrome. in IE i receive 0 seconds for all years.
Is there a reason for this? it seems to only happen in the last chrome version
for(var i=0; i<2020;i++)
if(!new Date(i,0,1).valueOf().toString().match("00000$"))
console.log({
y:i,
s: new Date(i,0,1).valueOf().toString().match(/(\d{2})\d{3}$/)[1]})
Share
Improve this question
asked Jun 14, 2018 at 12:07
DanielDaniel
2,3813 gold badges27 silver badges35 bronze badges
10
|
Show 5 more comments
2 Answers
Reset to default 17 +100This is Not a BUG..
As @Krzysztof pointed out Chrome has implemented a new spec for timezone offset calculation following the merge of Make LocalTZA take 't' and 'isUTC' and drop DSTA(t) to Ecma 262. So now the time-zone conversion does not work by just backward interval of seconds, it is calculated as what local time was being observed in a specific region.
Explanation:
I am from a wonderful little country called Bangladesh of South-Asia which follows BST(Bangladesh Standard Time +0600 GMT), which was not always exactly 6 hours ahead of GMT. As JavaScript date
takes in local time when I print the start time of this year in GMT I get:
new Date(2018, 0, 1).toUTCString()
// "Sun, 31 Dec 2017 18:00:00 GMT"
In 2009 one hour day-light saving was observed in Bangladesh from 19 June to 31 December. So if I print the first day of December 2009 I get:
new Date(2009, 11, 1).toUTCString()
// "Mon, 30 Nov 2009 17:00:00 GMT"
You can see the day-light saving is now reflected in the date now, which is not visible in my nodeJS
console. There was also changes in local time in 1941-1942 as shown below and can be seen on timeanddate.com:
All of the changes are reflected in Chrome now:
new Date(1941, 6, 1).toUTCString()
// "Mon, 30 Jun 1941 18:06:40 GMT"
new Date(1941, 11, 1).toUTCString()
// "Sun, 30 Nov 1941 17:30:00 GMT"
new Date(1942, 7, 1).toUTCString()
// "Fri, 31 Jul 1942 18:30:00 GMT"
new Date(1942, 11, 1).toUTCString()
// "Mon, 30 Nov 1942 17:30:00 GMT"
So now if I pick any date before 1941 keeping in mind my local time is 6 hours ahead I see an offset of 6 minutes 40 seconds. It will vary depending on the time-zone for the back dates due to the recent update of Chrome, or specifically saying the update of ECMAScript(JavaScript).
This may not be 100% the solution of the problem, but one can get the "jitter" introduced by chrome by casting it to UTC and back, then compensate with a new new Date(oldDate.getTime() + jitter)
.
// Compensates for google chrome 67+ issue with very old dates.
// We should skip this test if any other browser.
$getJitter: function (d) {
var utcDate = new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate(), d.getUTCHours(), d.getUTCMinutes(), d.getUTCMilliseconds())),
jitter = 0;
// As we're setting UTC date, the non-UTC year could be
// shifted one ahead or behind, so set the utc full
// year to ensure compliance.
utcDate.setUTCFullYear(d.getUTCFullYear());
if (d.getFullYear() != utcDate.getFullYear() ||
d.getMonth() != utcDate.getMonth() ||
d.getDate() != utcDate.getDate() ||
d.getHours() != utcDate.getHours() ||
d.getMinutes() != utcDate.getMinutes() ||
d.getMilliseconds() != utcDate.getMilliseconds()) {
// infers the "jitter" introduced during the conversion to compensate in the
// actual value of ticks
jitter = d.getTime() - utcDate.getTime()
}
return jitter;
}
This "jitter" pretty much depends on the time zone. For Brazil I'm getting a 28 seconds noise (so it gets back to like, 12:00:00 AM > 23:59:32 PM the previous day.
For Brazil the issue happens down to 1913. This coincides with the time we got our daylight saving times and time zone to -3:00 from -3:06, according to the time changes over years at https://www.timeanddate.com/time/zone/brazil/sao-paulo.
With the above code you can explore the broken dates with this loop:
for (var i=1900; i < 2020; i++) {
for (var j=0; j < 12; j++) {
var dt = new Date(i, j, 1);
var jitter = System.DateTime.$getJitter(dt);
if (jitter != 0) {
console.log("broken: " + i + ", " + j + ", jitter: " + (jitter/1000) + "s: " + dt.toString());
}
}
}
new Date(1915, 0, 1, 0, 0, 0).toUTCString()
results in"Thu, 31 Dec 1914 22:36:00 GMT"
(Chrome 67.0.3396.87). Thats really strange, and I think it's a bug. Did You report that? – Krzysztof Grzybek Commented Jun 14, 2018 at 15:30new Date(1915, 0, 1, 0, 0, 0).toUTCString()
returns"Fri, 01 Jan 1915 00:00:00 GMT"
– Eliott Robson Commented Jun 20, 2018 at 7:24new Date(1915, 0, 1, 0, 0, 0)
gives output "Fri Jan 01 1915 00:00:00 GMT+0124" and difference is indeed 1h 24min. AlsogetTimezoneOffset
returns -84 (1h 24min) – barbsan Commented Jun 20, 2018 at 10:00