👻

.NET CoreでWindowsとLinuxでTimeZoneのIDが異なる

2023/12/18に公開

問題

TimeZoneInfo.FindSystemTimeZoneById(String) メソッド でタイムゾーンを取得する際にLinuxで実行するとエラーになる。

テスト用のサンプルコード

// UTC時間を取得
var utcNow = DateTime.UtcNow;
// JSTのタイムゾーンを取得
var jstTimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Tokyo Standard Time");
// UTCからJSTに変更
var jstNow = TimeZoneInfo.ConvertTimeFromUtc(utcNow, jstTimeZoneInfo);

Console.WriteLine("utcNow : " + utcNow.ToString());
Console.WriteLine("jstNow : " + jstNow.ToString());

Windowsで実行

utcNow : 12/02/2023 14:10:06
jstNow : 12/02/2023 23:10:06

Linuxで実行

System.TimeZoneNotFoundException: The time zone ID 'Tokyo Standard Time' was not found on the local computer.

原因

プラットフォームでタイムゾーンのID値が異なる。

Cross-platform Time Zones with .NET Coreの記事によると下記のようにプラットフォームで指定する値が異なるとの事。

Windows

https://learn.microsoft.com/en-us/windows-hardware/manufacture/desktop/default-time-zones?view=windows-11

Linux

https://www.iana.org/time-zones

解決方法

記事によると下記のライブラリを利用する事で指定の差異を吸収できる。
Linuxではtzdataのライブラリがインストールされている必要がある。

https://github.com/mattjohnsonpint/TimeZoneConverter

自身の利用シーンでは、UTCとJSTの変換くらいだったので、JSTのタイムゾーンを取得する下記のコードにしました。
プラットフォームによっては一度で取得できずコストが増えるので、ライブラリを使うのがベストプラクティスかもしれません。

public static class Utils
{
    /// <summary>
    /// JSTのタイムゾーン情報を取得
    /// </summary>
    public static TimeZoneInfo TZ_JST = GetTimeZone("Asia/Tokyo", "Tokyo Standard Time");

    public static TimeZoneInfo GetTimeZone(params string[] names)
    {
        foreach (var name in names)
        {
            try { return TimeZoneInfo.FindSystemTimeZoneById(name); }
            catch (TimeZoneNotFoundException) { }
        }
        throw new TimeZoneNotFoundException();
    }
}

Discussion