为啥有这么多 IANA 时区名称?

Posted

技术标签:

【中文标题】为啥有这么多 IANA 时区名称?【英文标题】:Why So Many IANA Time Zones Names?为什么有这么多 IANA 时区名称? 【发布时间】:2019-06-24 20:49:02 【问题描述】:

如果您指定该时区的IANA 给定名称,javascript 允许您查看另一个时区的时间。例如:

new Date().toLocaleString("en-US", timeZone: "America/Chicago");

您可以在下面看到 IANA 在每个通用时区提供多个名称:

America/New_York    Eastern (most areas)
America/Detroit Eastern - MI (most areas)
America/Kentucky/Louisville Eastern - KY (Louisville area)
America/Kentucky/Monticello Eastern - KY (Wayne)
America/Indiana/Indianapolis    Eastern - IN (most areas)
America/Indiana/Vincennes   Eastern - IN (Da, Du, K, Mn)
America/Indiana/Winamac Eastern - IN (Pulaski)
America/Indiana/Marengo Eastern - IN (Crawford)
America/Indiana/Petersburg  Eastern - IN (Pike)
America/Indiana/Vevay   Eastern - IN (Switzerland)
America/Chicago Central (most areas)
America/Indiana/Tell_City   Central - IN (Perry)
America/Indiana/Knox    Central - IN (Starke)
America/Menominee   Central - MI (Wisconsin border)
America/North_Dakota/Center Central - ND (Oliver)
America/North_Dakota/New_Salem  Central - ND (Morton rural)
America/North_Dakota/Beulah Central - ND (Mercer)
America/Denver  Mountain (most areas)
America/Boise   Mountain - ID (south); OR (east)
America/Phoenix MST - Arizona (except Navajo)
America/Los_Angeles Pacific
America/Anchorage   Alaska (most areas)
America/Juneau  Alaska - Juneau area
America/Sitka   Alaska - Sitka area
America/Metlakatla  Alaska - Annette Island
America/Yakutat Alaska - Yakutat
America/Nome    Alaska (west)
America/Adak    Aleutian Islands
Pacific/Honolulu    Hawaii

为什么需要这样做?

例如,America/DetroitAmerica/New_York(通常)都在东部时区。为什么这两个位置不共享一个 IANA 时区名称?

一年中纽约的时间是否与底特律的时间不同?

如果不是,那么为什么允许时区名称多于实际差异数?

【问题讨论】:

“数据库中的每个主要条目都代表一组自 1970 年以来一致同意的民用时钟的时区。时区通常由大陆或海洋标识,然后由该地区最大的城市包含时钟..." 来源:IANA -> Sources for time zone and daylight saving time data 这些时区之间可能存在历史差异和/或仍然存在差异。 DST 和/或将来可能再次存在差异。我不确定这完全是否方便。 @marekful - 名称仅指偏移量,而是指偏移量、转换日期/时间和缩写的完整集一个特定地区的文明时代已经过去。此外,不一定要选择最近的城市,而是必须知道哪个城市与同一当地时间一致。考虑一个靠近地缘政治边界的城市可能与更远的内陆城市的时间一致,而不是边界对面的城市。 @LonnieBest - 不,你不能安全地假设。您必须将每个条目视为唯一的实体。如果您想知道它们何时对齐以及何时不同,那么您要么必须举例说明来源,要么编写代码来寻找差异。还有像timeanddate.com 这样的网站可以帮助您更轻松地挖掘细节。 它甚至不是轻微为了方便。人们经常问为什么他们最喜欢的城市没有自己的区域,答案是它不会包含与(不是用户最喜欢的城市)不同的数据。 【参考方案1】:

我会用你的例子:

例如,America/Detroit 和 America/New_York 都在东部时区。为什么这两个位置不共享一个时区名称?

在 TZDB 中,the Zone entry for America/New_York 如下所示:

# Zone  NAME              GMTOFF    RULES   FORMAT   [UNTIL]
Zone    America/New_York  -4:56:02  -       LMT      1883 Nov 18 12:03:58
                          -5:00     US      E%sT     1920
                          -5:00     NYC     E%sT     1942
                          -5:00     US      E%sT     1946
                          -5:00     NYC     E%sT     1967
                          -5:00     US      E%sT

虽然the Zone entry for America/Detroit 看起来像这样:

# Zone  NAME              GMTOFF    RULES   FORMAT   [UNTIL]
Zone    America/Detroit   -5:32:11  -       LMT      1905
                          -6:00     -       CST      1915 May 15  2:00
                          -5:00     -       EST      1942
                          -5:00     US      E%sT     1946
                          -5:00     Detroit E%sT     1973
                          -5:00     US      E%sT     1975
                          -5:00     -       EST      1975 Apr 27  2:00
                          -5:00     US      E%sT

要完全理解这一点,还需要USNYCDetroitRule 条目(我不会在此处复制/粘贴,但您可以点击链接)。

如您所见,底特律与纽约有所不同,最后一次是在 1975 年底特律开始夏令时的时间略晚于大多数东部时区(此处显示的是 4 月 27 日与 2 月 23 日given by Rule US) .

然而,从那以后,它们一直是一样的。 The TZDB rules 要求对自 1970 年以来达成一致的区域使用唯一的区域,而这些区域在 1973 年和 1975 年存在偏差,因此它们需要唯一的区域标识符。

可以像这样在 JavaScript 中看到这种差异:

var d = new Date("1975-03-01T00:00:00.000Z"); // Midnight UTC on March 1st
d.toLocaleString("en-US", timeZone: "America/New_York")  //=> "2/28/1975, 8:00:00 PM"
d.toLocaleString("en-US", timeZone: "America/Detroit")   //=> "2/28/1975, 7:00:00 PM"

当然,如果在您的应用程序中,您从不处理追溯到那么远的日期,那么您可以只使用America/New_York 代表美国东部时区,并省略America/Detroit (和其他一些人)-但这完全是您的决定。

您可能也有兴趣阅读 tzdb 本身中的 Theory 文件,它更详细地解释了时区数据库的概念和原理。

【讨论】:

旁注:我发现几个官方时区在 Chromium 71 中缺少支持,我报告了它here。

以上是关于为啥有这么多 IANA 时区名称?的主要内容,如果未能解决你的问题,请参考以下文章

为啥这个 SPARQL 查询缺少这么多结果?

IANA

如何在 ICU4J 中获得“当前”IANA 时区缩写?

为啥服务器上sqlserver会占那么多内存?

从“没有时区的时间”和时区名称中获取“有时区的时间”

如何从时区名称中获取时区偏移量