C# 時區轉換教學 (Windows & Linux)

我們可以使用 TimeZoneInfo.FindSystemTimeZoneById 取得時區資訊,再將時間做轉換:
    
TimeZoneInfo timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Taipei Standard Time");

DateTime utcTime = DateTime.UtcNow;
Console.WriteLine($"UTC Time: {utcTime}");

DateTime localTime = TimeZoneInfo.ConvertTimeFromUtc(utcTime, timeZoneInfo);
Console.WriteLine($"Local Time: {localTime}");
    

範例輸出:
    
UTC Time: 2023/04/08 下午 12:22:55
Local Time: 2023/04/08 下午 08:22:55
    

查看所有時區列表:
    
ReadOnlyCollection<TimeZoneInfo> timeZoneInfos = TimeZoneInfo.GetSystemTimeZones();
foreach (var info in timeZoneInfos)
{
    Console.WriteLine(info.Id);
}
    

Linux 和 Windows 用來表示時區的 ID 不同

這裡列出來的時區 id 是使用 Windows ID ,也就是在 Windows 上使用的、用來確認時區的 ID。以台北標準時間為例是 "Taipei Standard Time",而不是平時在 Linux 上看到的 TZDB ID (tz database time) 的 "Asia/Taipei"。

最近嘗試將 .NET 3.1 的專案部屬到 Linux 上時發現錯誤,就是因為 Linux 認不得 Windows 的時區 ID,在仔細查看了 Github Issues 後發現在 .NET 6 以前(不包含 .NET 6) 都只能透過第三方套件來解決,不然就是需要手動判斷部屬的作業系統來使用不同的 id。

而在 .NET 6 之後 TimeZoneInfo.FindSystemTimeZoneById 終於可以直接使用 Windows ID 或是 TZDB ID 來處理時區了! 範例程式碼:
    
TimeZoneInfo timeZoneInfo1 = TimeZoneInfo.FindSystemTimeZoneById("Taipei Standard Time");
TimeZoneInfo timeZoneInfo2 = TimeZoneInfo.FindSystemTimeZoneById("Asia/Taipei");

DateTime utcTime = DateTime.UtcNow;
Console.WriteLine($"UTC Time: {utcTime}");
DateTime localTime1 = TimeZoneInfo.ConvertTimeFromUtc(utcTime, timeZoneInfo1);
Console.WriteLine($"Local Time1: {localTime1}");
DateTime localTime2 = TimeZoneInfo.ConvertTimeFromUtc(utcTime, timeZoneInfo2);
Console.WriteLine($"Local Time2: {localTime2}");
    

範例輸出:
    
UTC Time: 2023/04/08 下午 12:22:55
Local Time1: 2023/04/08 下午 08:22:55
Local Time2: 2023/04/08 下午 08:22:55
    

話說 Alpine Docker images 從 3.0 版本開始不再包含 tzdata ,有用到時區的需要自行增加

參考資料:
Github.Issues - TimeZoneInfo should have consistent Ids across Windows and Linux #14929
Github.Pull request - Support Time Zone IANA Ids and Windows Ids in all platforms #49412
Github - mattjohnsonpint/TimeZoneConverter
StackOverflow - TimeZoneInfo in .NET Core when hosting on unix (nginx)

留言