为什么 C# 检测不到 1970/1/1 在 BST 下?

Why doesn't C# detect that 1970/1/1 was under BST?

我正在与第 3 方 API 合作,returns 时间值作为 DateTime 值填充在 1970 年 1 月 1 日作为日期部分。所以对于凌晨 5 点,它将 return 类似于 1969-12-31T21:03:00.000-08:00

问题是,如果用户在伦敦时间,C# 无法为 1970-01-01 应用 BST 调整。 例如,UTC 中的 1970-01-01 5AM 在伦敦应为 1970-01-01 6AMSee conversion

但是,C# 似乎不应用此转换:

var utcTime = new DateTime(1970, 1, 1, 5, 0, 0, DateTimeKind.Utc);
var britishZone = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time");
var ukTime = TimeZoneInfo.ConvertTime(utcTime, britishZone);
Console.WriteLine(ukTime);

以上代码仍会打印 5AM。

但是,如果我将其设置为 BST 生效的较新日期,例如 2016 年 10 月 1 日,则相同的代码可以正确打印早上 6 点。

  1. 为什么会这样?
  2. 我该如何解决这个问题?我们的应用程序需要跨任何时区工作(即硬编码时区不是一个选项 - 我们基本上使用 Windows 本地时区)。

我认为代码运行正常。 BSt 从 3 月的最后一个星期日开始,直到 10 月的最后一个星期日,时钟向前移动一个小时。即UTC+1。由于您正在查看 1 月的日期,因此伦敦时间将与 UTC.that 相同,即 utc+0 查看维基百科了解时区详细信息 https://en.m.wikipedia.org/wiki/British_Summer_Time

当您在 Windows 上使用 TimeZoneInfo class 来处理系统时区(在本例中为 "GMT Standard Time")时,您正在请求时区数据来自 Windows 操作系统,存储在注册表中:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones

Windows 根本没有将历史数据带回那么远。对于 "GMT Standard Time",这是在 GMT 和 BST 之间交替的伦敦时区,它只知道一组规则 - 当前有效的规则。在此之前它一无所知(它最后一次更改是在 1996 年)。

请注意,根据 Microsoft 的 DST/TZ Support Policy,保证只记录 2010 年以后的更改。 Windows 历史上有几项较早的更改(例如美国 2007 年 DST 更改等),它们确实有效,但从全球角度来看,您可能无法在 2010 年之前获得最佳结果。

为此,您需要 the IANA TZ Database, and in .NET, one of the best ways to do that is with the Noda Time 库的完整实现。

您的代码,音译为野田时间:

var utcTime = Instant.FromUtc(1970, 1, 1, 5, 0, 0);
var britishZone = DateTimeZoneProviders.Tzdb["Europe/London"];
var ukTime = utcTime.InZone(britishZone);
Console.WriteLine(ukTime.ToDateTimeUnspecified()); // just for equivalent output

// Prints:  1/1/1970 6:00:00 AM

另请注意,如果您在 Linux 或 OSX 上使用 运行 .NET Core,那么时区确实是 IANA 时区,因此您的原始代码将仅通过使用 IANA 标识符

var britishZone = TimeZoneInfo.FindSystemTimeZoneById("Europe/London");

另见 the timezone tag wiki

您是否考虑过为有问题的历史时期创建自定义时区调整?

https://msdn.microsoft.com/en-us/library/bb397784(v=vs.110).aspx

可用于以下情况:

The time zone does not have accurate information about time zone adjustments for a particular historic period.