将 UTC 时间转换为实际有效的当地国家时间

RRM*_*RRM 1 .net c# timezone datetime

如果我有一些 UTC 时间,我如何在 C# 中获取波兰相应的当地时间?还是在法国?还是在厄瓜多尔?(我理解这对于像俄罗斯这样多次使用的大国来说没有意义)

在大多数现有示例中,人们使用TimeZoneInfo对象:

var zone = TimeZoneInfo.FindSystemTimeZoneById("SE Asia Standard Time");
Run Code Online (Sandbox Code Playgroud)

问题是这还不够。许多国家/地区都有“夏令时”或“夏令时”之类的时间,它们根据一年中的日期甚至确切的时间(在时间更改的当天)使用与 UTC 不同的时间偏移。

例如,我只知道目标时间是芝加哥,而不是知道我是否需要Central Daylight Time或选项。Central Standard Time我希望能够有一个字符串,让平台为我决定这两个偏移量中哪一个现在是正确的。

是否有任何 C# 内置函数可以处理此问题,或者我是否需要根据所选国家/地区的法律自行处理夏令时开始和结束的所有计算?

Mat*_*int 5

如果我有一些 UTC 时间,我如何在 C# 中获取波兰相应的当地时间?还是在法国?还是在厄瓜多尔?

在 Windows 上:

var poland = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(DateTimeOffset.UtcNow, "Central European Standard Time");
var france = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(DateTimeOffset.UtcNow, "Romance Standard Time");
var ecuador1 = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(DateTimeOffset.UtcNow, "SA Pacific Standard Time"); // (Mainland)
var ecuador2 = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(DateTimeOffset.UtcNow, "Central America Standard Time"); // (Galapagos Is.)
Run Code Online (Sandbox Code Playgroud)

在 Linux、OSX 和其他 .NET Core 平台上:

var poland = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(DateTimeOffset.UtcNow, "Europe/Warsaw");
var france = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(DateTimeOffset.UtcNow, "Europe/Paris");
var ecuador1 = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(DateTimeOffset.UtcNow, "America/Guayaquil"); // (Mainland)
var ecuador2 = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(DateTimeOffset.UtcNow, "Pacific/Galapagos"); // (Galapagos Is.)
Run Code Online (Sandbox Code Playgroud)

(请注意,厄瓜多尔有两个时区,一个为大陆时区,一个为加拉帕戈斯群岛。)

CLDRwindowsZones.xml文件是确定要使用哪个 Windows ID 的一个很好的参考,它是 Windows 和 IANA 时区标识符之间转换的真实来源。

(我理解这对于像俄罗斯这样多次使用的大国来说没有意义)

事实上,俄罗斯有许多不同的时区标识符。人们必须知道他们对俄罗斯的哪一部分感兴趣。

在大多数现有示例中,人们使用TimeZoneInfo对象:

var zone = TimeZoneInfo.FindSystemTimeZoneById("SE Asia Standard Time");
Run Code Online (Sandbox Code Playgroud)

问题是这还不够。许多国家/地区都有“夏令时”或“夏令时”之类的时间,它们根据一年中的日期甚至确切的时间(在时间更改的当天)使用与 UTC 不同的时间偏移。

例如,我不想知道我是否需要Central Daylight TimeorCentral Standard Time选项,而是希望能够选择 America/Chicago并让它为我处理该选项。

不,那不是问题。您可能对要求感到困惑,因为标识符名称中包含“标准”一词。尽管如此,一个TimeZoneInfo对象代表了整个时区,包括标准时间和夏令时。

为了澄清,该TimeZoneInfo.FindSystemTimeZoneById方法采用一个标识符。生成的对象的Id属性将包含该标识符。

  • "America/Chicago"是 IANA 时区标识符。
  • "Central Standard Time"既是 Windows 时区标识符,又是同一区域的英文本地化“标准名称”(在 Windows 上)。
  • "Central Daylight Time"是该区域的英文本地化“日光名称”(在 Windows 上)。它不是有效的时区标识符。

是否有任何 C# 内置函数可以处理此问题,或者我是否需要根据所选国家/地区的法律自行处理夏令时开始和结束的所有计算?

所有内置计算都可以处理此问题。仅传递有效的标识符,框架将确定与 UTC 的正确偏移量,无论标准时间或夏令时是否有效。

这是一个演示这些概念的工作示例

TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time"); // Use "America/Chicago" on non-Windows systems

Console.WriteLine("Id:             " + tzi.Id);
Console.WriteLine("DisplayName:    " + tzi.DisplayName);
Console.WriteLine("StandardName:   " + tzi.StandardName);
Console.WriteLine("DaylightName:   " + tzi.DaylightName);
Console.WriteLine();

DateTime winterDate = new DateTime(2020, 1, 1);
DateTime summerDate = new DateTime(2020, 7, 1);

TimeSpan winterOffset = tzi.GetUtcOffset(winterDate);
TimeSpan summerOffset = tzi.GetUtcOffset(summerDate);

bool winterIsDst = tzi.IsDaylightSavingTime(winterDate);
bool summerIsDst = tzi.IsDaylightSavingTime(summerDate);

Console.WriteLine("Winter Offset:  " + winterOffset + "  IsDST:  " + winterIsDst);
Console.WriteLine("Summer Offset:  " + summerOffset + "  IsDST:  " + summerIsDst);
Run Code Online (Sandbox Code Playgroud)

输出:

Id:             Central Standard Time
DisplayName:    (UTC-06:00) Central Time (US & Canada)
StandardName:   Central Standard Time
DaylightName:   Central Daylight Time

Winter Offset:  -06:00:00  IsDST:  False
Summer Offset:  -05:00:00  IsDST:  True
Run Code Online (Sandbox Code Playgroud)

最后,如果您希望能够在任何操作系统上使用任一组标识符,可以通过两种不同的方式来处理:

  • TimeZoneInfo您可以使用我的TimeZoneConverter库检索。例如:

    // Either of these will work on any platform:
    TimeZoneInfo tzi = TZConvert.GetTimeZoneInfo("America/Chicago");
    TimeZoneInfo tzi = TZConvert.GetTimeZoneInfo("Central Standard Time");
    
    Run Code Online (Sandbox Code Playgroud)
  • 您可以使用Noda Time代替TimeZoneInfo,后者适用ZonedDateTimeProviders于 Bcl (Windows) 和 Tzdb (IANA) 标识符。

    // This will work on any platform:
    DateTimeZone dtz = DateTimeZoneProviders.Tzdb["America/Chicago"];
    
    // This will work with Windows on .NET Framework only
    DateTimeZone dtz = DateTimeZoneProviders.Bcl["Central Standard Time"];
    
    Run Code Online (Sandbox Code Playgroud)

您可能还想在 Stack Overflow 上阅读时区标签 wiki 。特别是标题为“时区数据库”的部分。