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



我正在使用一个第三方API,该API返回一天中的时间,因为DateTime值在1970年1月1日作为日期部分填充。因此,在凌晨5点,它将返回1969-12-31T21:03:00.000-08:00

之类的东西

问题是,如果用户在伦敦时间,C#未能对1970-01-01进行BST调整。例如,UTC中的1970-01-01 5AM应为伦敦的1970-01-01 6AM。请参阅转换

但是,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日,相同的代码可以正常打印6am。

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

当您使用Windows上的TimeZoneInfo类用于系统时区(在这种情况下为"GMT Standard Time")时,您是在Windows操作系统中要求时区数据,该数据存储在注册表:

HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindows NTCurrentVersionTime Zones

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

请注意,根据Microsoft的DST/TZ支持策略,只有从2010年开始的更改将被记录下来。历史上有几个较旧的变化在Windows中(例如美国2007年DST变更等)确实有效,但是从全球角度来看,您可能不会在2010年之前与日期获得最佳结果。

为此,您需要全面实施IANA TZ数据库,在.NET中,最好的方法之一就是使用Noda Time库。

您的代码,译为NODA时间:

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");

另请参见时区标签Wiki。

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

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

可以在以下情况下使用:

时区没有有关特定历史时期时区调整的准确信息。

我认为代码正常工作。BST从3月的最后一个星期日开始,直到10月的上周日,时钟向前移动了一个小时。那是UTC 1。由于您正在1月份的日期,伦敦时间将与UTC相同。检查Wikipedia是否详细信息https://en.m.wikipedia.org/wiki/british_summer_time

相关内容

  • 没有找到相关文章

最新更新