JavaScript时区对于过去的夏令时转换规则是错误的

在2007年,我们转换为夏令时的日子改变了。 任何落在DST扩展范围之内的date都会在Chrome和Firefox中报告不正确的时区偏移量。 这就像Firefox和Chrome不注意DST曾经有过不同的日子。

如果运行以下脚本,它将报告240分钟的偏移量。 这是不正确的,它应该报告300分钟。 IE10正确地做到了这一点。 有谁知道一个修复?

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

更新:

这里有一段我​​刚刚入侵的代码(见下文)。 真正令人惊讶的是,除了IE以外,每个浏览器的大部分date还有多远。 比较开始date和结束date: http : //www.timeanddate.com/worldclock/timezone.html?n=77&syear=2000

我最终只是用我自己的getTimezoneOffsetreplaceDate的原型,根据硬编码表计算它。 这对我们是有效的,因为我们只在美国做生意。这是我可以想象的最糟糕的解决scheme,尽pipe…

 <!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> 

它实际上是指定的行为,使用当前的DST规则,并忽略在特定的date/时间正在审查的地方。 参见ES5 15.9.1.8 :

“ECMAScript的实现不应该试图确定确切的时间是否受到夏令时的影响,而只是在当前使用夏令时时间algorithm的情况下,夏令时是否有效。同时考虑到当地观察夏令时一年的时间。“

规则是:将当前的DST规则应用到指定的任何时间。 这导致了无谓的行为,但这是ECMAScript要求的。

在未来的ECMAScript版本中,这种行为可能会发生变化,要求在所有时间点使用实际的DST规则。 这并不是最初要求的,因为运输tzdata给实施者带来的负担。 语言已经变得足够重要,但是,从长远来看,大概每个人都可能不得不把它吸引过来。 但是,我所知道的变化可能还有几年的时间,所以不要屏住呼吸。

我已经确认这是JavaScript中的一个真正的错误。

  • testing与美国夏时制后的普通时区
    • 东部,中部,山区,太平洋
  • 在Chrome,Firefox,Safari中testing失败(最新版本)
  • 在IE 6,7,8,9testing失败。
  • 在IE 10中testing通过(不受影响)。
  • 在Windows 7,8和Mac OSX上testing。

这很麻烦。 有谁知道的根本原因?

我认为这可能是一个WebKit的错误,但火狐使用壁虎。

我检查了各种问题列表,无法find任何地方这个特定的问题。 也许我错过了什么。 我不确定在哪里提交错误报告,因为它影响到多个地方。

也许这是一个核心的JavaScript错误? 我真的很难相信这个基本的东西被unit testing忽略了。

我以为也许它只是影响Windows系统,由于操作系统有Windows时区而不是TZDB,但似乎并不是这种情况,因为它也发生在Mac上。

我们都知道JavaScript的date是棘手的,但我认为我们至less可以依靠这个。 你甚至不必看偏移量,或者涉及parsing。 只要检查的价值:

 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日过渡。 这是目前有效的“十一月的第一个星期天”规则,但在2004年,这个规则应该是“十月最后一个星期天”的旧规则。

更新1

它并不局限于浏览器。 它也在Node.js中失败

Node.js截图

只是为了certificateIE是好的,这里是IE10的输出:

IE10截图

有趣的是,IE浏览器和Firefox解决一时歧义作为日光时间,而Chromeparsing为标准时间,但这是一个单独的问题。 它确实select了正确的过渡date。

更新2

值得一提的是,在最新的Firefox 21中,这个问题确实发生了,但是它的performance方式却有所不同,因为即使使用了正确的偏移量,它也会改变标准名称的日光。 换句话说,在Firefox上,输出是这样的:

Firefox截图