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

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

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

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

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

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

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

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

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


当前回答

我在两种类型的系统上找到了这一点,“轮班计划系统(例如工厂工人)”和“依赖天然气的管理系统”…

23小时和25小时的工作日是一个很难应付的问题,8小时的轮班需要7小时或9小时。问题是,你会发现每个客户,甚至客户的部门都有他们在这些特殊情况下创建的不同规则(通常没有记录)。

有些问题最好不要问客户,直到他们为您的“现成”软件支付了费用。很少有客户在购买软件时会提前考虑这类问题。

我认为在任何情况下,您都应该使用UTC记录时间,并在存储日期/时间之前转换为当地时间。然而,即使知道一个给定的时间是在哪,也很难使用夏令时和时区。

其他回答

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

商业规则应始终适用于民事诉讼时间(除非法律另有规定)。请注意,公民时间是一团糟,但这是人们使用的时间,所以这才是最重要的。

在内部,将时间戳保持在从大纪元开始的民用时间秒中。纪元并不特别重要(我喜欢Unix纪元),但它确实比其他纪元更容易。假装闰秒不存在,除非你正在做一些真正需要它们的事情(例如,卫星跟踪)。时间戳和显示时间之间的映射是应用DST规则的唯一点;规则经常变化(在全球范围内,一年几次;指责政客),所以你应该确保你没有硬编码地图。奥尔森的TZ数据库是无价的。

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

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

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

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

永远不要只依赖像这样的构造函数

 new DateTime(int year, int month, int day, int hour, int minute, TimeZone timezone)

当某个日期时间由于DST而不存在时,它们可以抛出异常。相反,构建自己的方法来创建这样的日期。在它们中,捕捉由于DST而发生的任何异常,并使用转换偏移调整所需的时间。根据时区,夏令时可能会在不同的日期和时间(甚至巴西的午夜)发生。

对于在服务器上运行的应用程序(包括网站和其他后端服务),应用程序应忽略服务器的时区设置。

常见的建议是将服务器的时区设置为UTC。这确实是一个很好的最佳实践,但对于不遵循其他最佳实践的应用程序来说,这是一个创可贴。例如,服务可能使用本地时间戳而不是基于UTC的时间戳写入日志文件,从而在夏时制回退转换期间产生歧义。将服务器的时区设置为UTC将修复该应用程序。然而,真正的解决办法是应用程序首先使用UTC进行日志记录。

服务器端代码(包括网站)不应期望服务器的本地时区是任何特定的。

在某些语言中,本地时区很容易进入应用程序代码。例如,.NET中的DateTime.ToUniversalTime方法将从本地时区转换为UTC,DateTime.Now属性返回本地时区中的当前时间。此外,JavaScript中的Date构造函数使用计算机的本地时区。像这样的例子还有很多。练习防御性编程很重要,避免任何使用计算机本地时区设置的代码。

使用本地时区保留客户端代码,如桌面应用程序、移动应用程序和客户端JavaScript。