смещение секундных секунд в объекте даты js в хроме
Если посмотреть значение valueOf объекта даты в начале года, я ожидал, что всегда будет получать нулевые секунды. Следующий код показывает, что до 1917 года в хроме было смещение на 54 секунды или 40 секунд. в IE я получаю 0 секунд на все годы.
Для этого есть причина? это похоже только в последней версии хрома
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]})
Ответы
Ответ 1
Это не ошибка.
Поскольку @Krzysztof отметил, что Chrome внедрил новую спецификацию для расчета смещения часового пояса после слияния Make LocalTZA, возьмите 't' и 'isUTC' и поместите DSTA (t) в Ecma 262. Итак, теперь изменение часового пояса не работает только обратный интервал секунд, он рассчитывается как то, что локальное время наблюдается в определенном регионе.
Объяснение:
Я из прекрасной маленькой страны, названной Бангладеш Южной Азии, которая следует за BST (стандартное время Бангладеш +0600 GMT), что не всегда было ровно на 6 часов раньше GMT. Поскольку date
JavaScript принимается по местному времени, когда я печатаю время начала этого года в GMT, я получаю:
new Date(2018, 0, 1).toUTCString()
// "Sun, 31 Dec 2017 18:00:00 GMT"
В 2009 году в Бангладеш с 19 июня по 31 декабря наблюдалось одночасовое экономия времени. Поэтому, если я печатаю первый день декабря 2009 года, я получаю:
new Date(2009, 11, 1).toUTCString()
// "Mon, 30 Nov 2009 17:00:00 GMT"
Вы можете видеть, что дневная подсветка теперь отражается в nodeJS
дате, которая не видна в моей консоли nodeJS
. Были также изменения в местное время в 1941-1942 годах, как показано ниже, и можно увидеть на timeanddate.com:
Все изменения теперь отражены в Chrome:
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"
Итак, теперь, если я выбираю любую дату до 1941 года, имея в виду, что мое местное время на 6 часов вперед, я вижу смещение 6 минут 40 секунд. Он будет меняться в зависимости от часового пояса для последних дат из-за недавнего обновления Chrome или, в частности, для обновления ECMAScript (JavaScript).
Ответ 2
Это может быть не 100% решение проблемы, но можно получить "дрожание", введенное хром, отбросив его на UTC и обратно, а затем компенсировать новую 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;
}
Этот "дрожание" в значительной степени зависит от часового пояса. Для Бразилии я получаю 28-секундный шум (так он возвращается, как, 12:00:00 AM> 23:59:32 PM в предыдущий день.
Для Бразилии проблема происходит до 1913 года. Это совпадает с тем, как мы получили наши летнее время и часовой пояс на -3: 00 из -3: 06, в соответствии с изменением времени в течение лет на https://www. timeanddate.com/time/zone/brazil/sao-paulo.
С помощью приведенного выше кода вы можете исследовать разбитые даты с помощью этого цикла:
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());
}
}
}