C# 如何在 Windows 和 IANA 时区之间进行转换?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17348807/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 09:15:24  来源:igfitidea点击:

How to translate between Windows and IANA time zones?

c#.nettimezonenodatime

提问by Matt Johnson-Pint

As described in the timezone tag wiki, there are two different styles of time zones.

正如timezone tag wiki 中所述,有两种不同风格的时区。

  • Those provided by Microsoft for use with Windows and the .Net TimeZoneInfoclass (when running on Windows) are identified by a value such as "Eastern Standard Time".

  • Those provided by IANA in the TZDB, and used by the .NET TimeZoneInfoclass when running on Linux or OSX, are identified by a value such as "America/New_York".

  • Microsoft 提供的用于 Windows 和 .NetTimeZoneInfo类(在 Windows 上运行时)的那些由诸如"Eastern Standard Time".

  • 由 IANA 在 TZDB 中提供并TimeZoneInfo在 Linux 或 OSX 上运行时由 .NET类使用的那些由诸如"America/New_York".

Many Internet-based APIs use the IANA time zones, but for numerous reasons one might need to convert this to a Windows time zone id, or vice-versa.

许多基于 Internet 的 API 使用 IANA 时区,但出于多种原因,可能需要将其转换为 Windows 时区 ID,反之亦然。

How can this be accomplished in .Net?

这如何在 .Net 中实现?

采纳答案by Matt Johnson-Pint

The primary source of the data for conversion between Windows and IANA time zone identifiers is the windowsZones.xmlfile, distributed as part of the Unicode CLDRproject.

Windows 和 IANA 时区标识符之间转换数据的主要来源是该windowsZones.xml文件,作为Unicode CLDR项目的一部分分发。

However, CLDR is released only twice annually. This, along with the periodic cadence of Windows updates, and the irregular updates of the IANA time zone database, makes it complicated to just use the CLDR data directly. Keep in mind that time zone changes themselves are made at the whim of the world's various governments, and not all changes are made with sufficient notice to make it into these release cycles before their respective effective dates.

但是,CLDR 每年仅发布两次。这一点,再加上 Windows 更新的周期性节奏,以及 IANA 时区数据库的不定期更新,使得直接使用 CLDR 数据变得很复杂。请记住,时区更改本身是根据世界各国政府的心血来潮进行的,并非所有更改都是在发出足够通知的情况下进行的,以使其在各自的生效日期之前进入这些发布周期。

There are a few other edge cases that need to be handled that are not covered strictly by the CLDR, and new ones pop up from time to time. Therefore, I've encapsulated the complexity of the solution into the TimeZoneConvertermicro-library, which can be installed from Nuget.

还有一些其他边缘情况需要处理,但 CLDR 并未严格涵盖,并且不时会出现新的情况。因此,我将解决方案的复杂性封装到TimeZoneConverter微库中,可以从 Nuget 安装。

Using this library is simple. Here are some examples of conversion:

使用这个库很简单。以下是一些转换示例:

string tz = TZConvert.IanaToWindows("America/New_York");
// Result:  "Eastern Standard Time"

string tz = TZConvert.WindowsToIana("Eastern Standard Time");
// result:  "America/New_York"

string tz = TZConvert.WindowsToIana("Eastern Standard Time", "CA");
// result:  "America/Toronto"

There are more examples on the project site.

项目站点上有更多示例。

It's important to recognize that while an IANA time zone can be mapped to a single Windows time zone, the reverse is not true. A single Windows time zone might be mapped to more than one IANA time zone. This can be seen in the above examples, where Eastern Standard Timeis mapped to both America/New_York, and to America/Toronto. TimeZoneConverter will deliver the one that CLDR marks with "001", known as the "golden zone", unless you specifically provide a country code and there's a match for a different zone in that country.

重要的是要认识到,虽然 IANA 时区可以映射到单个 Windows 时区,但反之则不然。一个 Windows 时区可能映射到多个 IANA 时区。这可以在上面的示例中看到,其中Eastern Standard Time映射到America/New_YorkAmerica/Toronto。TimeZoneConverter 将提供 CLDR 标记的那个"001",称为“黄金区域”,除非您特别提供国家/地区代码并且该国家/地区的不同区域有匹配项。

Note: This answer has evolved over the years, so comments below may or may not apply to the current revision. Review the edit history for details. Thanks.

注意:这个答案多年来一直在发展,所以下面的评论可能适用于也可能不适用于当前的修订版。查看编辑历史以了解详细信息。谢谢。

回答by EverPresent

I know this is an old question, but I had a use case I though I would share here, since this is the most relevant post I found when searching. I was developing a .NET Core app using a docker linux container, but for deployment on a windows server. So I only needed my docker linux container to support the windows timezone names. I got this working without changing my application code by doing the following:

我知道这是一个老问题,但我有一个用例,尽管我会在这里分享,因为这是我在搜索时找到的最相关的帖子。我正在使用 docker linux 容器开发 .NET Core 应用程序,但用于在 Windows 服务器上进行部署。所以我只需要我的 docker linux 容器来支持 windows 时区名称。通过执行以下操作,我在不更改应用程序代码的情况下完成了这项工作:

cp /usr/share/zoneinfo/America/Chicago "/usr/share/zoneinfo/Central Standard Time"
cp /usr/share/zoneinfo/America/New_York "/usr/share/zoneinfo/Eastern Standard Time"
cp /usr/share/zoneinfo/America/Denver "/usr/share/zoneinfo/Mountain Standard Time"
cp /usr/share/zoneinfo/America/Los_Angeles "/usr/share/zoneinfo/Pacific Standard Time"

Then, in my .NET code, the following worked without any modification: TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time")

然后,在我的 .NET 代码中,以下内容无需任何修改即可运行: TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time")