为什么Date.prototype.toString()和Date.prototype.toLocaleString()会返回表示时间点不一致的字符串?

时间:2014-09-25 23:41:26

标签: javascript google-chrome date timezone v8

var d = new Date();

// returns correct value "Fri Sep 26 2014 01:16:31 GMT+0300 (E. Europe Daylight Time)"
d.toString();

// returns incorrect value one hour behind "9/26/2014 12:16:31 AM"
d.toLocaleString();

似乎toLocaleString()没有将DST考虑在这个测试用例中。

如何按日期计算当地时间(例如,Chrome是否自行应用DST规则或通过操作系统)以及算法在toString()和toLocaleString()之间的差异如何/为何?

这是一个错误还是预期的行为?

在Chrome / 37.0.2062.120上测试,位置塞浦路斯尼科西亚(http://www.timeanddate.com/time/zone/cyprus/nicosia

1 个答案:

答案 0 :(得分:4)

在预感中,我尝试将我的Windows时区更改为:

TZ Key / ID:  "E. Europe Standard Time" 
Display name: "(UTC+02:00) E. Europe"

重新启动Chrome后,我就可以获得您展示的相同内容:

Screenshot

仔细研究一下本地化属性:

Screenshot

因此,似乎Chrome无法理解时区。这是因为Chrome使用了ICU,它使用CLDR mappings用于Windows时区。该特定时区现在被视为“无法映射” - 因为没有与此Windows区域匹配的IANA时区标识符。

请注意,此区域已使用映射到Asia/Nicosia,但在CLDR的最新版本中已更改,如CLDR #6973

中所述

出现差异的原因是toLocaleString函数使用ECMAScript Internationalization API,而toString则不然。先验取决于ICU和CLDR,而后者只是要求操作系统提供时区字符串。

修复方法是让用户将时区切换到正确的设置。塞浦路斯应该是:

TZ Key / ID:  "GTB Standard Time" 
Display name: "(UTC+02:00) Athens, Bucharest"

查看Windows时区控制面板中的选项时: tz settings

确保在更改时区后完全关闭所有Chrome窗口,因为Chrome在重新启动之前无法正确初始化时区。

现在,评论中的issue I mentioned earlier仍然存在问题,因为Intl.DateTimeFormat().resolvedOptions().timeZone现在返回Europe/Kiev,它应该返回Asia/NicosiaEurope/Bucharest。但至少在大多数情况下,返回toLocaleString的正确值是足够好的。

相关问题