You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Windows上运行的.NET应用中使用IANA时区数据库

.NET跨平台统一使用IANA时区数据库的解决方案

问题说明

以下C#代码在不同操作系统上运行输出不一致:

using System.Globalization; 

var zone = TimeZoneInfo.FindSystemTimeZoneById("Iran Standard Time");
var date = new DateTimeOffset( // 1367年Farvardin月1日
    year: 1988, 
    month: 3, 
    day: 21, 0, 0, 0, TimeSpan.FromHours(4.5));
var offset = zone.GetUtcOffset(date);

Console.WriteLine(offset);
// Windows输出: 4:30
// Ubuntu输出: 3:30

差异根源是.NET默认依赖操作系统提供的时区数据库:Windows使用自有时区库,Linux使用IANA时区数据库(TZDB)。需求是让应用跨平台统一使用IANA时区数据库,且不转换时区标识符、不引入NodaTime等第三方库。

实现方案(.NET 6及以上版本)

从.NET 6开始,官方提供了原生支持统一使用TZDB的方式,无需额外大型依赖:

1. 强制运行时使用TZDB

有两种方式配置运行时优先使用IANA时区数据库:

  • 环境变量配置:启动应用前设置环境变量 TZDB_DEFAULT=1,运行时会自动切换为TZDB模式。
  • 代码配置:在应用入口(如Program.cs最开头)添加以下代码:
// 禁用NLS时区,强制使用TZDB
AppContext.SetSwitch("System.TimeZoneInfo.UseNls", false);
// 可选:指定本地时区的IANA ID,替代系统默认本地时区
// AppContext.SetSwitch("System.TimeZoneInfo.LocalId", "Asia/Tehran");

2. 使用IANA时区标识符

切换到TZDB模式后,需要直接使用IANA时区ID(如Asia/Tehran)而非Windows时区ID(如Iran Standard Time),修改后的代码跨平台输出一致:

using System;

var zone = TimeZoneInfo.FindSystemTimeZoneById("Asia/Tehran");
var date = new DateTimeOffset(1988, 3, 21, 0, 0, 0, TimeSpan.FromHours(4.5));
var offset = zone.GetUtcOffset(date);

Console.WriteLine(offset); // 所有平台统一输出: 3:30

3. 确保时区数据为最新版本

如果需要使用最新的IANA时区规则(避免操作系统时区数据过时),可以安装官方NuGet包System.TimeZoneInfo.Tzdb:

dotnet add package System.TimeZoneInfo.Tzdb

安装后,运行时会自动使用包内的最新TZDB数据,无需额外配置。


内容的提问来源于stack exchange,提问作者Shahryar Saljoughi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 21:23:20