我正在使用第三方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
。
See 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。
答案 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
答案 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