смещение секундных секунд в объекте даты 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:

enter image description here

Все изменения теперь отражены в 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());
  }
 }
}