为了账号安全,请及时绑定邮箱和手机立即绑定

过去的夏令时过渡规则,JavaScript时区错误

/ 猿问

过去的夏令时过渡规则,JavaScript时区错误

牛魔王的故事 2019-11-18 18:27:05

在2007年,我们改用夏时制的日子发生了变化。在此更改之前,属于DST扩展范围的任何日期都将报告Chrome和Firefox中不正确的时区偏移。就像Firefox和Chrome不用注意DST过去的日子不同。


如果运行以下脚本,它将报告偏移量为240分钟。这是不正确的,它应该报告300分钟。IE10可以正确执行此操作。有人知道解决办法吗?


alert(new Date('11/04/2004').getTimezoneOffset());

更新:


这是我刚刚一起学习的一段有趣的代码(请参见下文)。令人惊讶的是,除了IE之外,每种日期在大多数浏览器中的距离还有多远。比较开始日期和结束日期与此:http : //www.timeanddate.com/worldclock/timezone.html?n=77&syear=2000


我最终只是用我自己的Date原型将getTimezoneOffset替换为Date的原型,该原型根据硬编码表进行计算。这对我们有用,因为我们仅在美国开展业务,但这是我能想到的最糟糕的解决方案...


<!DOCTYPE html>

<html>

    <head>

        <title>Moment Test</title>

        <script src="http://cdnjs.cloudflare.com/ajax/libs/moment.js/2.0.0/moment.min.js"></script>

        <script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>

        <script>

var lastOffset = null;

var $tbody = null;

var endDate = new Date('01/01/2021');


function addDate(d) {

    if($tbody === null)

        $tbody = $('#dates');


    var offset = d.getTimezoneOffset();

    var s = '';

    if(lastOffset != offset) {

        if(lastOffset != null)

            s = '<tr style="background-color: red;">';

        lastOffset = offset;

    }

    else {

        s = '<tr>';

    }

    var m = new moment(d);

    s += '<td>' + m.format('YYYY-MM-DD') + '</td><td>' + m.format('YYYY-MM-DDTHH:mm:ssZ') + '</td><td>' + m.format('YYYY-MM-DDTHH:mm:ss') + '</td><td>' + offset + '</td></tr>';

    $tbody.append($(s));

    d.setDate(d.getDate() + 1);


    if(d < endDate)

        window.setTimeout(function(){addDate(d)}, 0);

}


        </script>

    </head>

    <body>

        <button onclick="addDate(new Date('01/01/1980'));">Fill Table</button>

        <table border="1">

            <thead><tr><th>Date</th><th>Date 2</th><th>Date 3</th><th>TZ Offset</th></tr></thead>

            <tbody id='dates'></tbody>

        </table>

    </body>

</html>


查看完整描述

2 回答

?
慕莱坞7535251

实际上是指定行为,以使用当前的DST规则,而忽略在检查的特定日期/时间到位的规则。参见ES5 15.9.1.8:


“ ECMAScript的实现不应尝试确定确切的时间是否受夏时制的约束,而应确定如果当时使用了当前的夏时制算法,则夏时制是否会生效。这避免了诸如此类的复杂性。考虑到该语言环境全年观察夏令时的情况。”


规则是:将当前DST规则应用于指定的任何时间。这会导致胡言乱语,但这正是ECMAScript所要求的。


在将来的ECMAScript版本中,这种行为甚至可能会改变,要求在所有时间点都使用实际的DST规则。最初并不需要这样做,因为它会给实现者带来发送tzdata的负担。语言已经变得足够重要,但是从长远来看,也许每个人都必须掌握它。但是就我所知,这种变化可能还需要数年,所以不要屏住呼吸。


查看完整回答
反对 回复 2019-11-18
?
繁星淼淼

我已经确认这是JavaScript中的错误。


在遵循夏时制的美国常见时区进行测试

东部,中部,山脉,太平洋

已在Chrome,Firefox,Safari中测试,并且失败(最新版本)

在IE 6、7、8、9中进行了测试,但失败了。

在IE 10中测试并通过(不受影响)。

在Windows 7、8和Mac OSX上进行了测试。

这很麻烦。有人知道根本原因吗?


我以为可能是WebKit错误,但是Firefox使用Gecko。


我检查了各种问题列表,在任何地方都找不到此特定问题。也许我错过了一些东西。我不确定在哪里提交错误报告,因为它会影响多个地方。


也许这是JavaScript的核心错误?我真的很难相信这个基本的东西已经被单元测试所忽略了。


我认为这可能只是影响Windows系统,因为该操作系统具有Windows时区而不是TZDB,但是事实并非如此,因为它也发生在Mac上。


我们都知道JavaScript日期是很麻烦的,但是我认为我们至少可以依靠它。您甚至不必查看偏移量,也不必进行解析。只需检查以下值:


new Date(2004,10,4)  // recall, js months are 0-11, so this is Nov. 4 2004.

在2004年的美国,夏令时于10月31日的凌晨2:00结束,而时钟又回到了凌晨1:00。因此,到11月4日,他们肯定都应该在标准时间上,但事实并非如此!例如,在控制台上的Chrome开发者工具中,时钟设置为美国东部时区:


> new Date(2004,10,7,0,0)

  Sun Nov 07 2004 00:00:00 GMT-0400 (Eastern Daylight Time)


> new Date(2004,10,7,1,0)

  Sun Nov 07 2004 01:00:00 GMT-0500 (Eastern Standard Time)

过渡日期定在11月7日。这是继目前生效的“ 11月的第一个星期日”规则之后的,但是在2004年,该规则应该是“ 10月的最后一个星期日”的旧规则。


更新1


它似乎限于浏览器。 它还在Node.js中失败

只是为了证明IE很好,这是IE10的输出:

有趣的是,IE和Firefox将1:00歧义解决为“夏令时”,而Chrome将其解决为标准时间,但这是一个单独的问题。它确实选择了正确的过渡日期。


更新2


值得一提的是,在最新的Firefox 21中,确实发生了此问题,但其呈现方式却有所不同,因为即使使用了正确的偏移量,另一个问题却又切换了标准名称的白天设置。换句话说,在Firefox上,输出如下:


查看完整回答
反对 回复 2019-11-18

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信