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

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

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

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

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

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

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

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

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


当前回答

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

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

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

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

其他回答

您需要了解Olson-tz数据库,可从ftp://elsie.nci.nih.gov/pub http://iana.org/time-zones/.它每年更新多次,以应对世界各地不同国家在冬季和夏季(标准时间和夏令时)之间切换的时间(以及是否切换)的最后时刻变化。2009年,最后一次发布是2009年;2010年为2010n;2011年为2011n;2012年5月底,发布时间为2012c。注意,在两个独立的存档(tzcode20xxy.tar.gz和tzdata20xxy.tar.gz)中有一组代码来管理数据和实际时区数据本身。代码和数据都在公共域中。

这是时区名称的来源,如America/Los_Angeles(和同义词,如US/Pacific)。

如果你需要跟踪不同的区域,那么你需要奥尔森数据库。正如其他人所建议的,您还希望以固定格式(UTC通常是所选的格式)存储数据,并记录生成数据的时区。您可能需要区分时间与UTC的偏移量和时区名称;这会在以后产生影响。此外,知道当前是2010-03-28T23:47:00-07:00(美国/太平洋)可能会或可能不会帮助您解释值2010-11-15T12:30-这可能是在PST(太平洋标准时间)而不是PDT(太平洋夏令时)中指定的。

标准的C库接口对这类东西没有太大的帮助。


奥尔森的数据发生了变化,部分原因是A·D·奥尔森很快就要退休了,另一部分原因是对维护者的版权侵权诉讼(现已驳回)。时区数据库现在由互联网号码分配机构IANA负责管理,并且在首页有一个“时区数据库”链接。讨论邮件列表现在是tz@iana.org; 公告列表是tz-announce@iana.org.

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

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

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

如果您碰巧维护的数据库系统在DST活动的情况下运行,请仔细检查它们是否需要在秋季过渡期间关闭。Mandy DBS(或其他系统)不喜欢在同一时间点(本地)两次通过,这正是当你在秋天将时钟拨回时发生的情况。SAP采用了一种(IMHO真的很好)变通方法解决了这一问题——他们没有让时钟倒转,而是让内部时钟以正常速度的一半运行两个小时。。。

PHP的DateTimeZone::listAbstrations()输出

此PHP方法返回一个包含一些“主要”时区(如CEST)的关联数组,这些时区本身包含更具体的“地理”时区(例如欧洲/阿姆斯特丹)。

如果您使用这些时区及其偏移/DST信息,请务必了解以下信息:

似乎每个时区的所有不同偏移量/DST配置(包括历史配置)都包含在内!

例如,欧洲/阿姆斯特丹可以在该函数的输出中找到六次。两次出现(偏移量1172/4772)是1937年之前使用的阿姆斯特丹时间;两个(1200/4800)用于1937年至1940年间使用的时间;两个(3600/4800)是1940年以来使用的时间。

因此,您不能依赖此函数返回的当前正确/正在使用的偏移量/DST信息!

如果您想知道某个时区的当前偏移量/DST,您必须执行以下操作:

<?php
$now = new DateTime(null, new DateTimeZone('Europe/Amsterdam'));
echo $now->getOffset();
?>

汤姆·斯科特(Tom Scott)在《计算机爱好者》频道的YouTube上关于时区的视频也对这一话题进行了精彩有趣的描述。示例包括:

萨摩亚(太平洋中的一个岛屿)将其时区提前24小时,以便于与澳大利亚和新西兰的贸易,西岸有两个人口在不同的时区,18世纪从儒略历到格里高利历的变化日历(发生在20世纪的俄罗斯)。