web-dev-qa-db-ja.com

WindowsとIANAのタイムゾーンを変換する方法は?

タイムゾーンタグwiki で説明されているように、タイムゾーンには2つの異なるスタイルがあります。

  • Windowsおよび.Net TimeZoneInfoクラスで使用するためにMicrosoftが提供するものは、Eastern Standard Timeなどの値で識別されます。

  • TZDBでIANAによって提供されるものは、America/New_Yorkなどの値によって識別されます。

多くのインターネットベースのAPIはIANAタイムゾーンを使用しますが、多くの理由により、これをWindowsタイムゾーンIDに変換する必要がある場合があります。

これを.Netでどのように実現できますか?

132

WindowsとIANAのタイムゾーン識別子間の変換のためのデータの主要なソースは、 nicode CLDR プロジェクトの一部として配布されるwindowsZones.xmlファイルです。

ただし、、CLDRは年に2回だけリリースされます。これは、Windows更新の定期的なリズム、およびIANAタイムゾーンデータベースの不規則な更新とともに、CLDRデータを直接使用するだけで複雑になります。タイムゾーンの変更自体は世界のさまざまな政府の気まぐれで行われ、すべての変更がそれぞれの発効日の前にこれらのリリースサイクルに入るように十分な通知で行われるわけではないことに注意してください。

CLDRで厳密にカバーされていない他のエッジケースを処理する必要があり、新しいケースが時々ポップアップします。そのため、ソリューションの複雑さを TimeZoneConverter マイクロライブラリにカプセル化しました。これはNugetからインストールできます。

このライブラリの使用は簡単です。変換の例を次に示します。

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"

さらに多くの例があります プロジェクトサイト上

IANAタイムゾーンは単一のWindowsタイムゾーンにマッピングできますが、逆は当てはまらないことを認識することが重要です。 1つのWindowsタイムゾーンが複数のIANAタイムゾーンにマッピングされる場合があります。これは上記の例で見ることができます。Eastern Standard TimeAmerica/New_YorkAmerica/Torontoの両方にマッピングされています。 TimeZoneConverterは、国コードを具体的に指定し、その国の別のゾーンに一致する場合を除き、CLDRが"001"(「ゴールデンゾーン」と呼ばれる)でマークしたものを配信します。

注:この回答は長年にわたって進化しているため、以下のコメントは現在のリビジョンに適用される場合と適用されない場合があります。詳細については、編集履歴を確認してください。ありがとう。

170

私はこれが古い質問であることを知っていますが、検索時に見つけた最も関連性の高い投稿であるため、ここで共有するユースケースがありました。 Docker Linuxコンテナを使用して.NET Coreアプリを開発していましたが、Windowsサーバーでの展開用です。したがって、Windowsタイムゾーン名をサポートするために必要なのは、Docker Linuxコンテナのみです。次の操作を行うことで、アプリケーションコードを変更せずにこれを機能させることができました。

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"

次に、私の.NETコードでは、次のコードは変更なしで機能しました。TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time")

2
EverPresent