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

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

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

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

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

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

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

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

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


当前回答

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

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

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

其他回答

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

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

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

仅举一个例子来证明,处理时间是描述的巨大混乱,你永远不会自满。在本页的几个地方,闰秒被忽略了。

几年前,Android操作系统使用GPS卫星获取UTC时间参考,但忽略了GPS卫星不使用闰秒的事实。没有人注意到,直到除夕夜出现了混乱,苹果手机用户和安卓手机用户相隔约15秒进行倒计时。

我想它已经被修复了,但你永远不知道这些“小细节”什么时候会回来困扰你。

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();
?>

如果您的设计能够适应,请避免同时转换本地时间!

我知道对一些人来说,这可能听起来很疯狂,但想想用户体验:用户处理接近的相对日期(今天、昨天、下周一)比绝对日期(2010.09.17,星期五-9月17日)的速度要快。当你仔细考虑时,时区(和DST)的准确度越接近现在()就越重要,所以如果你可以用+/-1或2周的相对格式表示日期/日期时间,其余的日期可以是UTC,这对95%的用户来说并不重要。

通过这种方式,您可以以UTC存储所有日期,并以UTC进行相对比较,只需向用户显示超出相对日期阈值的UTC日期。

这也适用于用户输入(但通常以更有限的方式)。从只有{昨天、今天、明天、下周一、下周四}的下拉列表中进行选择,对于用户来说,比日期选择器更简单、更容易。日期选择器是表单填充中最令人痛苦的部分。当然,这并不适用于所有情况,但您可以看到,它只需要一点巧妙的设计就可以使其非常强大。

在处理数据库(特别是MySQL,但这适用于大多数数据库)时,我发现很难存储UTC。

默认情况下,数据库通常使用服务器日期时间(即CURRENT_TIMESTAMP)。您可能无法更改服务器时区。即使您能够更改时区,您也可能有第三方代码希望服务器时区是本地的。

我发现,只需在数据库中存储服务器日期时间,然后让数据库在SQL语句中将存储的日期时间转换回UTC(即UNIX_TIMESTAMP())就更容易了。之后,您可以在代码中使用日期时间作为UTC。

如果您100%控制服务器和所有代码,那么最好将服务器时区更改为UTC。