我希望将这个问题及其答案作为处理夏令时的最终指南,特别是处理实际转换时。

如果你有什么要补充的,请做

许多系统都依赖于保持准确的时间,问题是由于夏时制而导致的时间变化——向前或向后移动时钟。

例如,一个订单接受系统中的业务规则取决于订单的时间——如果时钟发生变化,规则可能就不那么清晰了。应如何保持订单的时间?当然,有无数的场景——这只是一个例证。

你是如何处理日光节约问题的?您的解决方案包含哪些假设?(在此处查找上下文)

同样重要,如果不是更重要的话:

你尝试了什么但没有奏效?为什么不起作用?

我会对编程、操作系统、数据持久性和其他相关方面感兴趣。

一般的答案很好,但我也希望看到细节,特别是如果它们只在一个平台上提供的话。


当前回答

还有一件事,确保服务器应用了最新的夏令时补丁。

去年,我们遇到了这样一种情况,北美用户在三周内的时间里,即使我们使用的是基于UTC的系统,我们的时间也总是比以前少一个小时。

最后证明是服务器。他们只需要应用最新的修补程序(Windows Server 2003)。

其他回答

将服务器设置为UTC,并确保所有服务器都配置为ntp或同等版本。

UTC避免了夏令时问题,服务器不同步可能会导致不可预测的结果,需要一段时间才能进行诊断。

虽然我没有尝试过,但我认为时区调整的方法很有说服力,如下所示:

以UTC格式存储所有内容。创建具有三列的表TZOffsets:RegionClassId、StartDateTime和OffsetMinutes(int,以分钟为单位)。

在表中,存储本地时间更改的日期和时间列表,以及更改的程度。表中区域的数量和日期的数量取决于您需要支持的日期范围和世界范围。将其视为“历史”日期,尽管日期应包括未来,但实际的限制。

当您需要计算任何UTC时间的本地时间时,只需执行以下操作:

SELECT DATEADD('m', SUM(OffsetMinutes), @inputdatetime) AS LocalDateTime
FROM   TZOffsets
WHERE  StartDateTime <= @inputdatetime
       AND RegionClassId = @RegionClassId;

您可能希望在应用程序中缓存此表,并使用LINQ或其他类似方法进行查询,而不是访问数据库。

这些数据可以从公共域tz数据库中提取出来。

这种方法的优点和脚注:

代码中没有规则,您可以很容易地调整新区域或日期范围的偏移量。您不必支持每个日期或地区范围,您可以根据需要添加它们。地区不必直接对应于地缘政治边界,为了避免重复行(例如,美国大多数州都以相同的方式处理DST),您可以在另一个表中设置广泛的RegionClass条目,以链接到更传统的州、国家等列表。对于像美国这样的情况,DST的开始和结束日期在过去几年中发生了变化,这很容易处理。由于StartDateTime字段也可以存储时间,因此2:00 AM标准转换时间很容易处理。并非世界上任何地方都使用1小时夏令时。这很容易处理这些情况。数据表是跨平台的,可以是一个单独的开源项目,可以被几乎使用任何数据库平台或编程语言的开发人员使用。这可以用于与时区无关的偏移。例如,为调整地球自转而不时发生的1秒调整、对公历的历史调整等。由于这是在一个数据库表中,标准报表查询等可以利用数据,而无需遍历业务逻辑代码。如果您愿意,它还可以处理时区偏移,甚至可以考虑将一个地区分配给另一个时区的特殊历史情况。您所需要的只是一个初始日期,该日期为每个区域分配一个时区偏移量,并具有最小的开始日期。这将要求为每个时区创建至少一个区域,但允许您提出一些有趣的问题,例如:“1989年2月2日凌晨5:00,亚利桑那州尤马市和华盛顿州西雅图市之间的当地时间差是多少?”(只需从另一个SUM()中减去一个)。

现在,这种方法或任何其他方法的唯一缺点是,从本地时间到GMT的转换并不完美,因为任何与时钟有负偏移的DST变化都会重复给定的本地时间。恐怕没有简单的方法来处理这个问题,这也是存储当地时间首先是坏消息的原因之一。

我最近在一个web应用程序中遇到了一个问题,在Ajax帖子中,返回到服务器端代码的日期时间与提供的日期时间不同。

这很可能与我在客户端上的JavaScript代码有关,该代码建立了以字符串形式发送回客户端的日期,因为JavaScript正在调整时区和夏时制,在某些浏览器中,何时应用夏时制的计算似乎与其他浏览器不同。

最后,我选择完全删除客户端上的日期和时间计算,并在一个整数键上返回到服务器,然后在服务器上转换为日期时间,以实现一致的转换。

我从中学习到:除非绝对必须,否则不要在web应用程序中使用JavaScript日期和时间计算。

永远不要在没有UTC偏移(或时区参考)的情况下存储本地时间-如何不这样做的示例包括C¹中的FAT32和结构tm了解时区是一组UTC偏移(例如,冬季+0100,夏季+0200)切换发生的时间规则(可能会随着时间的推移而改变:例如,在20世纪90年代,欧盟将切换统一为3月和10月的最后一个星期日,标准时间02:00/夏令时03:00;之前成员国之间有所不同)。


¹struct tm的一些实现确实存储UTC偏移量,但这并未将其纳入标准。

通常,在存储的时间戳中包含本地时间偏移量(包括DST偏移量):如果您以后想在原始时区(和DST设置)中显示时间戳,仅使用UTC是不够的。

请记住,偏移量并不总是整数小时(例如,印度标准时间为UTC+05:30)。

例如,合适的格式是元组(unix时间,以分钟为单位的偏移量)或ISO 8601。