为什么C#没有检测到1970/1/1是否属于BST?

我正在使用第三方API,它返回时间值作为DateTime值填充1970年1月1日作为日期部分。 因此,对于1969-12-31T21:03:00.000-08:00 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. 我该如何解决这个问题? 我们的应用程序需要跨任何TimeZone工作(即硬编码时区不是一个选项 – 我们基本上使用Windows本地时区)。

当您使用TimeZoneInfo类处理系统时区(在本例中为"GMT Standard Time" )时,您要求从Windows操作系统获取时区数据,该操作系统存储在注册表中:

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

Windows目前还没有提供历史数据。 对于"GMT Standard Time" ,这是伦敦在GMT和BST之间交替的时区,它只知道一组规则 – 当前有效的规则。 它之前不知道任何事情(1996年最后一次改变)。

请注意,根据Microsoft的DST / TZ支持政策 ,只保证记录从2010年开始的更改。 历史上一直存在于Windows中的一些较旧的更改(例如美国2007 DST更改和其他更改)确实有效,但从全球角度来看,您可能无法在2010年之前获得最佳结果。

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

您的代码,音译为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 

另请参阅timezone标记wiki 。

您是否考虑过针对相关历史时段创建自定义时区调整?

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

可用于以下情况:

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

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