我们将数据库中的所有时间都保存为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字段中产生了错误的结果,当我开始深入研究它时,我意识到,如果从使用.net 4.0编译的客户端应用程序调用上述相同的代码表单SQL2008(使用.net 3.5编译),则会产生不同的结果。2015年智利时区全年观测到夏令时时,3.5中的结果不正确,4.0中的结果正确。
我可以假设,这可能是专门为.net 3.5制作的一个缺失的修补程序,目前正在缺失。但是,如果有人以前遇到过这个或类似的问题,我会非常感谢一些额外的意见。
首先要做的几件事:
-
当你指的是
Id
时,不要使用StandardName
。虽然它们在某些情况下可能匹配,但这并不能保证。特别要考虑的是,StandardName
(以及DaylightName
和DisplayName
)是基于操作系统的主语言进行本地化的。它们在日本电脑上的外观与在英国电脑上的截然不同。 -
UTC的
Id
只是"UTC"
,所以如果您愿意,可以对其进行硬编码。或者,使用TimeZoneInfo.Utc.Id
,或者最好切换到TimeZoneInfo.ConvertTimeFromUtc
方法。 -
这里的try/catch将屏蔽任何真正的异常,例如传递的
timeZoneId
无效时的TimeZoneNotFoundException
。
现在,关于版本之间的差异,您正在经历的行为是KB3012229中描述的行为。虽然这篇文章提到了俄罗斯时区,但它也适用于智利最近的时区变化。之所以会出现这种情况,是因为TimeZoneInfo.AdjustmentRule
类最初的设计没有考虑到UTC的基准偏移量也可能逐年变化。这是在.NET 4.6中通过添加内部属性BaseUtcOffsetDelta
修复的,您可以在此处的参考源中看到。
如果您在计算机上安装了.NET 4.6或更高版本,那么任何使用.NET 4运行时的应用程序(即任何以.NET 4.0或更高版为目标的应用程序)都将具有正确的实现并正常工作。(这在.NET Core中也得到了修复。)
在我自己的机器上测试后,它似乎也在.NET3.5中得到了修复,但我不确定是哪一个特定的更新解决了这个问题。确保你已经安装了所有更新,问题应该(可能)会消失。
这里有更多关于这个的信息。