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

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

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

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

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

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

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

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

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


当前回答

跨越“计算机时间”和“人类时间”的界限是一场噩梦。主要原因是,时区和夏令时的规则没有一种标准。各国可以随时自由更改时区和夏令时规则,他们也可以这样做。

一些国家,例如以色列、巴西,每年都会决定何时实行夏令时,因此无法提前知道夏令时何时生效。其他人对DST何时生效有固定的规则。其他国家并不完全使用夏令时。

时区不必与格林尼治标准时间相差整整一小时。尼泊尔为+5.45。甚至还有+13的时区。这意味着:

SUN 23:00 in Howland Island (-12)
MON 11:00 GMT 
TUE 00:00 in Tonga (+13)

都是同一时间,但3天不同!

对于时区的缩写,以及它们在夏令时中的变化,也没有明确的标准,因此您最终会遇到这样的情况:

AST Arab Standard Time     UTC+03
AST Arabian Standard Time  UTC+04
AST Arabic Standard Time   UTC+03

最好的建议是尽可能远离当地时间,尽可能坚持UTC。仅在最后一刻转换为当地时间。

测试时,请确保您测试了西半球和东半球的国家,其中既有正在进行的夏令时,也有未使用夏令时的国家(共6个)。

其他回答

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

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

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

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

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

跨越“计算机时间”和“人类时间”的界限是一场噩梦。主要原因是,时区和夏令时的规则没有一种标准。各国可以随时自由更改时区和夏令时规则,他们也可以这样做。

一些国家,例如以色列、巴西,每年都会决定何时实行夏令时,因此无法提前知道夏令时何时生效。其他人对DST何时生效有固定的规则。其他国家并不完全使用夏令时。

时区不必与格林尼治标准时间相差整整一小时。尼泊尔为+5.45。甚至还有+13的时区。这意味着:

SUN 23:00 in Howland Island (-12)
MON 11:00 GMT 
TUE 00:00 in Tonga (+13)

都是同一时间,但3天不同!

对于时区的缩写,以及它们在夏令时中的变化,也没有明确的标准,因此您最终会遇到这样的情况:

AST Arab Standard Time     UTC+03
AST Arabian Standard Time  UTC+04
AST Arabic Standard Time   UTC+03

最好的建议是尽可能远离当地时间,尽可能坚持UTC。仅在最后一刻转换为当地时间。

测试时,请确保您测试了西半球和东半球的国家,其中既有正在进行的夏令时,也有未使用夏令时的国家(共6个)。

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

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

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

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

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


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

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

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