JavaScript的国际API提供了在Chrome
不同的结果,我使用的JavaScript国际API来检测浏览器的用户的时区:JavaScript的国际API提供了在Chrome
Intl.DateTimeFormat().resolvedOptions().timeZone
虽然这个API,我不知道如何处理接下来的事情。在我的Windows 10的机器,该时区设置为US Eastern Standard Time
:
C:\> tzutil /g
US Eastern Standard Time
在Firefox与"America/Indiana/Indianapolis"
封边上面的JavaScript代码的结果,而Chrome浏览器只返回"America/Indianapolis"
。
为什么这会产生不同的浏览器不同的结果?是Chrome bug吗?还是应该在处理服务器之前以某种方式转换时区?
在Ubuntu(这是我的服务器操作系统),如果我列出了可用的时区与timedatectl list-timezones
,有"America/Indiana/Indianapolis"
,但没有"America/Indianapolis"
。由于这个问题,我无法接受来自客户端的Chrome的"America/Indianapolis"
,因为我从timedatectl list-timezones
的输出中获取“可用时区列表”。我应该在这里适用哪些行为?
任何帮助表示赞赏。谢谢!
Chrome与许多其他Chrome浏览器一样,通过ICU获取其时区信息,该信息源自CLDR,部分源自IANA。
IANA和CLDR之间在规范化方面存在细微差异。
IANA对待优选形式的时区标识符作为典型的。如果首选表单发生更改,则会使新主表单(一个
Zone
条目)并将旧表单移动到别名(Link
条目)。CLDR处理第一个形式的时区标识符为规范。也就是说,它第一次出现在CLDR中,它永远被锁定。如果出现新表单,则会将其添加为
/common/bcp47/timezone.xml
文件中的别名。
以你的印第安纳波利斯的情况下:
-
IANA区入口(reference here)
Zone America/Indiana/Indianapolis ...
-
IANA链接条目(reference here)
Link America/Indiana/Indianapolis America/Indianapolis
-
在CLDR中,主要区域首先列在“别名”属性中,后跟别的别名。 (reference here)
<type name="usind" description="Indianapolis, United States" alias="America/Indianapolis America/Fort_Wayne America/Indiana/Indianapolis US/East-Indiana"/>
同样的事情可以用Asia/Calcutta
与Asia/Kolkata
和其他几个例子可以找到。
此外,请注意,Windows时区映射也源自CLDR,文件为/common/supplemental/windowsZones.xml
。你会注意到US Eastern Standard Time
映射到America/Indianapolis
。 因此,浏览器之间的差异很大程度上取决于遵循哪些规范化规则。
最后,使用哪个别名并不重要。他们指向相同的数据。
另外值得指出的是,只有在您关心historical time changes in Indiana时才应选择该特定Windows区域。如果您刚刚在美国东部时区,则应将系统设置为"Eastern Standard Time"
,而不是"US Eastern Standard Time"
。 (是的,这些ID是令人困惑的...)
非常感谢你对这样的扩展描述!一切都很有意义。事实上,我在我的Moment.js项目中使用moment-timezone(以及其他一些库)来解决这个问题,因为使用这些库会使处理时间翻倍,这是至关重要的(我的项目构建了多时区,基于日历数据的二维数据透视表)。因此,我决定使用集群启动工作人员,并将每个工作人员初始化到一个特定的时区,而不是在处理时区和替换时间区域并替换“Date”对象(NodeJS),这在NodeJS/V8中是可行的。 – ZitRo
很好的回答!我一直认为浏览器直接从SO读取这些信息。我并不感到惊讶,因为每个人都遵循不同的规则 - 我对此的了解越多,看起来就越困惑。 – 2017-08-24 21:11:02
@Hugo - 欢迎来到我的世界。 ;) –
zone.tab不完整。某些时区表示为符号链接:
$ find /usr/share/zoneinfo/America -name Indianapolis -exec file {} \;
/usr/share/zoneinfo/America/Indiana/Indianapolis: symbolic link to ../Indianapolis
/usr/share/zoneinfo/America/Indianapolis: timezone data, version 2, 7 gmt time flags, 7 std time flags, no leap seconds, 99 transition times, 7 abbreviation chars
谢谢乔希!那么获得所有可用时区列表的最佳方式是什么?通过'/ usr/share/zoneinfo'来查找?拥有这个列表的目的是为了能够在处理任何数据之前验证用户请求的时区(在我的例子中,产生一个新进程,进行计算等)。 – ZitRo
我不知道如何/为什么每个浏览器返回不同的结果(可能是他们从不同的来源和/或它可以是由于每个如何实现读Intl.DateTimeFormat
) 。但没关系,因为两者都是同一时区。
如果你检查this list,你会看到America/Indianapolis
链接到America/Indiana/Indianapolis
。格式为Region/City
的这些名称由IANA维护,它可能是我们有关时区信息的最佳来源之一。
IANA也保持了backward file映射的2名,与America/Indiana/Indianapolis
是最近的一个。
那么一个替代方案是让落后的文件的副本,并用它来映射您收到相应的新名字任何名义,也验证对您的服务器的时区列表。
谢谢!看起来我最终将通过添加来自[后退文件](https:// github)的别名。com/eggert/tz/blob/master/backward)添加到'timedatectl list-timezones'的结果中,这样可以创建一个(完整的?)可用时区列表。 – ZitRo
@ZitRo不客气!该清单将尽可能完整。时区是由政府和法律界定的,政界人士(他们喜欢改变他们)(https://www.timeanddate.com/news/time),无论出于何种原因(请参阅[git中的更改列表](https:/ /github.com/eggert/tz/commits/master)有一个想法)。当然,新的**时区比改变现有区域的规则更不常见,但是如果您想要有一个“完整”列表,则必须始终更新此文件。祝你好运! – 2017-08-24 18:33:10
实际上,两者是相同的 - 检查他们的名字在[本列表](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones)(一个是链接另一个)。也请查看[这里](https://github.com/eggert/tz/blob/master/backward) – 2017-08-24 17:40:45
https://unix.stackexchange.com/questions/35781/why-is-zone-tab-missing-so - 多个时区 –
@Hugo,谢谢。您链接的“后退”文件是否提供完整的“时区别名”列表?算法应该是什么?看起来像是我的LINK-NAME具有确切的时区名称,我需要在该表格中将其更改为TARGET。它是否正确?那么你能回答一个问题吗? – ZitRo