代码之家  ›  专栏  ›  技术社区  ›  Daniel

chrome中js日期对象中奇怪的秒偏移量

  •  17
  • Daniel  · 技术社区  · 8 年前

    当我看一个日期对象在一年的行乞时的价值时,我希望总是得到零秒。 下面的代码显示,直到1917年,chrome的偏移量为54秒或40秒。在IE中,我每年都会获得0秒。

    这是有原因的吗?这似乎只发生在最后一个Chrome版本中

       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]})
    
    2 回复  |  直到 8 年前
        1
  •  13
  •   Munim Munna    8 年前

    这是 不是虫子

    正如@krzysztof指出的那样,chrome已经 implemented a new spec for timezone offset calculation 合并之后 Make LocalTZA take 't' and 'isUTC' and drop DSTA(t) 至ECMA 262。因此,现在时区转换不只是以秒的向后间隔工作,它被计算为 在一个特定地区观察到的当地时间 .

    说明:

    我来自一个叫 孟加拉国 属于 南亚 接下来 BST (孟加拉国标准时间+0600 GMT),并不总是比GMT早6小时。 date 当我用GMT打印今年的开始时间时,获取本地时间:

    new Date(2018, 0, 1).toUTCString()
    // "Sun, 31 Dec 2017 18:00:00 GMT"
    

    2009 one hour day-light saving 于6月19日至12月31日在孟加拉国观察到。所以如果我打印2009年12月的第一天,我会得到:

    new Date(2009, 11, 1).toUTCString()
    // "Mon, 30 Nov 2009 17:00:00 GMT"
    

    你可以看到白天的节光现在反映在现在的日期,这在我的 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
  •  5
  •   Fabrício Murta    8 年前

    这可能不是100%解决问题的办法,但是可以通过将chrome的“抖动”投射到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:06到-3:00的时间,根据多年来的时间变化 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());
      }
     }
    }