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

时间:2016-11-28 03:05:42

标签: c# datetime timezone dst timezone-offset

我正在使用第三方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 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日,则相同的代码可以正常打印6AM。

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

3 个答案:

答案 0 :(得分:3)

当您使用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 Support Policy,只保证记录从2010年开始的更改。历史上一直存在于Windows中的一些旧版本(例如美国2007年DST更改等)确实有效,但从全球角度来看,您可能无法在2010年之前获得最佳结果。

为此,您需要the IANA TZ Database的完整实现,而在.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

另见the timezone tag wiki

答案 1 :(得分:1)

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

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

可以在以下情况下使用:

  

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

答案 2 :(得分:0)

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