Linux-Windows 时区映射?

14

Windows中的所有时区都以这样的方式显示:

(GMT+10:00) 堪培拉,墨尔本,悉尼

GMT和偏移量以及地点。相反,Linux将每个时区作为目录映射在/usr/share/zoneinfo/[大陆]/[地点]。

我需要将每个Windows时区映射到Linux时区,以用于我的应用程序。

(GMT+05:30) Chennai, Kolkata, Mumbai, New Delhi => Asia/Calcutta

现在问题出现在国际日期变更线(IDL)西侧,它位于俄罗斯和美国之间。在Windows中,它标记为(GMT-12:00) International Date Line West,而从各种来源得知,在Linux中它是Etc/GMT+12。

(GMT-12:00) International Date Line West => Etc/GMT+12

同样

(GMT+12:00) Coordinated Universal Time+12 => Etc/GMT-12
(GMT-02:00) Coordinated Universal Time-02 => Etc/GMT+2
(GMT-11:00) Coordinated Universal Time-11 => Etc/GMT+11 

这让我感到困惑,因为我的应用程序与UTC时间戳及其UTC偏移密切相关。因此,这种映射方式让我感到困惑并且影响了我的应用程序。

有人能解释一下为什么同一个地方的偏移量会有正负12小时之间的反向变化吗?

提前感谢您的回答 :)


你有可以分享的映射吗?我正在我的项目中做类似的事情。或者有一些自动映射的方法吗? - F. Kam
由于旧链接已经失效,请使用新的Zone → Tzid - Sathish Guru V
3个回答

35

Unicode.org托管了CLDR的一部分映射。 您可以在此处获取最新版本。该页面还链接了数据的XML版本。

您可以在此处找到从XML数据生成映射的示例代码(使用Python)

时间区域的必要抱怨:

请注意,Windows 中实现时区支持的人真是吸食了毒品。我可不是开玩笑。看看时区名称。为什么中欧时间被称为“罗曼斯标准时间”?罗曼斯?是因为它包括巴黎吗?或者说是因为它与“浪漫”有关?罗马标准时间可能有些道理,因为它包括罗马,但是“浪漫”!?

此外,在注册表中,时区没有按其ID组织。不,他们疯狂地按照其显示名称进行组织!由于该名称是本地化的,这意味着每个时区都会在不同的Windows翻译中位于不同的键下!!!因此,要找到正确的时区,您必须查看所有时区,以查看哪个具有正确的ID。

我在这里也有示例代码(使用Python)。请参阅get_win_timezone()函数。

我想知道是否同一个人设计了这个,还决定 POSIX 应该颠倒时区符号,以便-8小时表示加 8 小时。无论如何,我肯定他们一起吸食了某些非法物质。


感谢Lennart和NullToken :) - Sathish Guru V
1
请注意,截至2013年1月25日,unicode.org上的时区数据已经过时至少7年。到目前为止,我发现它缺少了Asia/Kolkata(从Asia/Calcutta改名而来)、America/Indiana/Indianapolis和America/Kentucky/Louisville。这对于将Windows时区映射到Linux仍然可以使用,但在修复之前,我不会将此数据用于任何更多的事情。 - geofflee
@geofflee:很不幸,我不知道他们甚至有时区数据,如果他们不更新,我也不知道为什么要这样做。无论如何,我只用它来进行时区名称映射。 - Lennart Regebro
1
请注意,有一些比较不常见的时区在Windows和Linux之间无法映射,例如Windows的Mid-Atlantic Standard Time以及带有30分钟和45分钟UTC偏移量的Linux时区。请参阅Unicode CLDR页面上的“其他考虑事项”部分:http://cldr.unicode.org/development/development-process/design-proposals/extended-windows-olson-zid-mapping。 - geofflee
1
@geofflee - 我不确定你从哪里得到了CLDR过时的想法。它一直在维护更新。您可以在此处查看版本历史记录(http://cldr.unicode.org/index/downloads)。我更新了此答案,以指向最新发布的永久链接。关于您提到的缺失区域的一个注意事项 - TZDB维护别名(“链接”),以便这些别名仍然正确解析。 CLDR不一定会更改链接,因为它们旨在与旧TZDB版本最大兼容性。 - Matt Johnson-Pint
@matt-johnson,是的,你说得对;当时我不知道有别名。我想任何使用CLDR数据都需要检查别名。 - geofflee

3
如果所有文件的标志都反了,那么你看到的文件就是正向映射偏移量,而你可能更熟悉的是反向映射偏移量。
Windows通常使用机器的本地时区作为内部时间,因此需要时区文件来将其转换回UTC。Linux通常使用UTC作为机器的内部时间,因此需要时区文件来将其转换为本地时间。
由于两台机器的偏移量描述的是时间的互补但相反的方向,因此可以推断出时区文件是互相逆相关的。换句话说,如果你从一个集合中取出一组区域文件,则另一组将是负数。

2
“Etc”目录中的定义是按照POSIX风格编写的,因此它们与您预期的相反。我不是POSIX的专家,但据我了解,基本思想是通过本地名称和相对于GMT的偏移量的组合来表示时区。以中欧(中欧时间/CET)为例:
Europe/Berlin (w/o daylight savings)  equals  GMT+01:00  equals  CET-1

在Etc目录中,GMT-1实际上描述了一个虚构的时区叫做“GMT”,比(真正的)GMT快一小时。
据我所知,这些文件只是为了让你创建(符号)链接,因此如果你位于欧洲中部某个地方,你可以创建到GMT-1的链接并将其命名为CET-1
我能给你的最好建议就是完全忽略Etc目录,并使用一些从Windows时区名称到Unix时区文件夹/文件的映射表。Windows时区信息不仅提供与GMT的偏移量,还知道夏令时(何时开始或结束)。时区数据库中的文件夹/文件也是如此,但Etc目录中的文件则仅提供静态的GMT偏移量。
时区数据库中的时区列表可以在维基百科中找到。

根据您的建议,我找到了真正的原因并得出了解决方案:)谢谢Patrick :) - Sathish Guru V

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接