我们将所有时间都保留在UTC数据库中。根据客户端的位置,使用.net函数将UTC时间转换为本地时间
public static DateTime ConvertToLocalTime(DateTime utcTime, string timezoneId)
{
try
{
return TimeZoneInfo.ConvertTimeBySystemTimeZoneId(utcTime, TimeZoneInfo.Utc.StandardName, timezoneId);
}
catch
{
return new DateTime();
}
}
有一个问题报告说某些报告在DateTime字段中产生了错误的结果,当我开始更深入地查看它时,我意识到上面相同的代码称为表单SQL2008(使用.net 3.5编译)会产生不同的结果来自使用.net 4.0编译的客户端应用程序。结果在3.5中是不正确的,并且在2015年智利时区的4.0中正确,当时全年都观察到夏令时。
我可以假设这可能是为.net 3.5专门生成的缺少修补程序,目前缺少。但如果有人以前遇到过这个或类似的问题,我会很感激一些额外的投入。
答案 0 :(得分:1)
首先要做的几件事:
当您的意思是StandardName
时,请不要使用Id
。虽然在某些情况下它们可能匹配,但这并不能保证。特别是,请考虑StandardName
(以及DaylightName
和DisplayName
)是基于操作系统的主要语言进行本地化的。它们在日本PC上看起来与在英语PC上看起来完全不同。
UTC的Id
只是"UTC"
- 因此,如果您愿意,可以对其进行硬编码。或者,使用TimeZoneInfo.Utc.Id
,或者最好切换到TimeZoneInfo.ConvertTimeFromUtc
方法。
此处的try / catch将掩盖任何实际异常,例如TimeZoneNotFoundException
如果传递的timeZoneId
无效。
现在关于版本之间的差异,您遇到的行为是KB3012229中描述的行为。虽然文章提到俄罗斯时区,但它也适用于智利最近的时区变化。之所以出现这种情况,是因为TimeZoneInfo.AdjustmentRule
类的设计最初并未考虑到UTC的基本偏移量也会逐年变化。这在.NET 4.6中通过添加内部属性BaseUtcOffsetDelta
得到修复,you can see in the reference sources here。
如果您在计算机上安装了.NET 4.6或更高版本,那么使用.NET 4运行时的任何应用程序(即任何面向.NET 4.0或更高版本的应用程序)都将具有更正的实现并正常工作。 (这也在.NET Core中得到修复。)
从我自己的机器上测试,它似乎也在.NET 3.5中得到修复,但是我不确定哪个特定的更新解决了这个问题。确保你已经安装了所有更新,问题应该(可能)消失。