我希望将这个问题及其答案作为处理夏令时的最终指南,特别是处理实际转换时。
如果你有什么要补充的,请做
许多系统都依赖于保持准确的时间,问题是由于夏时制而导致的时间变化——向前或向后移动时钟。
例如,一个订单接受系统中的业务规则取决于订单的时间——如果时钟发生变化,规则可能就不那么清晰了。应如何保持订单的时间?当然,有无数的场景——这只是一个例证。
你是如何处理日光节约问题的?您的解决方案包含哪些假设?(在此处查找上下文)
同样重要,如果不是更重要的话:
你尝试了什么但没有奏效?为什么不起作用?
我会对编程、操作系统、数据持久性和其他相关方面感兴趣。
一般的答案很好,但我也希望看到细节,特别是如果它们只在一个平台上提供的话。
对于在服务器上运行的应用程序(包括网站和其他后端服务),应用程序应忽略服务器的时区设置。
常见的建议是将服务器的时区设置为UTC。这确实是一个很好的最佳实践,但对于不遵循其他最佳实践的应用程序来说,这是一个创可贴。例如,服务可能使用本地时间戳而不是基于UTC的时间戳写入日志文件,从而在夏时制回退转换期间产生歧义。将服务器的时区设置为UTC将修复该应用程序。然而,真正的解决办法是应用程序首先使用UTC进行日志记录。
服务器端代码(包括网站)不应期望服务器的本地时区是任何特定的。
在某些语言中,本地时区很容易进入应用程序代码。例如,.NET中的DateTime.ToUniversalTime方法将从本地时区转换为UTC,DateTime.Now属性返回本地时区中的当前时间。此外,JavaScript中的Date构造函数使用计算机的本地时区。像这样的例子还有很多。练习防御性编程很重要,避免任何使用计算机本地时区设置的代码。
使用本地时区保留客户端代码,如桌面应用程序、移动应用程序和客户端JavaScript。
我不知道我能为上面的答案补充什么,但我有几点:
时间类型
您应该考虑四种不同的时间:
事件时间:例如,国际体育赛事发生的时间,或加冕/死亡等。这取决于事件的时区,而不是观众的时区。电视时间:例如,一个特定的电视节目在世界各地的当地时间晚上9点播出。当考虑在你的网站上发布(比如美国偶像)结果时,这一点很重要相对时间:例如:这个问题将在21小时内结束。这很容易显示重复播放时间:例如:每周一晚上9点播放电视节目,即使夏令时改变。
还有历史/备用时间。这些都很烦人,因为它们可能无法映射回标准时间。例如:朱利安日期,根据土星的阴历,克林贡日历。
在UTC中存储开始/结束时间戳效果良好。对于1,您需要与事件一起存储事件时区名称+偏移量。对于2,您需要为每个区域存储一个本地时间标识符,并为每个观众存储一个当地时区名称+偏移量(如果您遇到困难,可以从IP中导出)。对于3,以UTC秒存储,不需要时区。4是1或2的特殊情况,这取决于它是全局事件还是本地事件,但您还需要存储在时间戳创建的,以便您可以判断在创建此事件之前或之后是否更改了时区定义。如果需要显示历史数据,这是必要的。
存储时间
始终以UTC存储时间转换为显示的本地时间(本地时间由查看数据的用户定义)存储时区时,需要名称、时间戳和偏移量。这是必需的,因为政府有时会更改时区的含义(例如:美国政府更改了夏令时日期),而您的应用程序需要优雅地处理事情。。。例如:DST规则更改前后LOST剧集显示的确切时间戳。
偏移和名称
上述示例如下:
足球世界杯决赛发生在南非(UTC+2-SAST)2010年7月11日19:00 UTC。
有了这些信息,即使南非时区定义发生变化,我们也可以从历史上确定2010年WCS决赛的确切时间,并能够在观众查询数据库时以当地时区向他们显示。
系统时间
您还需要保持操作系统、数据库和应用程序tzdata文件彼此同步,并与世界其他地方同步,并在升级时进行广泛测试。你所依赖的第三方应用程序没有正确处理TZ更改,这并非闻所未闻。
确保硬件时钟设置为UTC,如果您在世界各地运行服务器,请确保其操作系统也配置为使用UTC。当您需要从多个时区的服务器复制每小时轮换一次的apache日志文件时,这一点变得很明显。仅当所有文件都以相同的时区命名时,才能按文件名对它们进行排序。这也意味着,当你从一个盒子到另一个盒子进行ssh时,你不必在脑子里计算日期,也不需要比较时间戳。
此外,在所有盒子上运行ntpd。
客户
永远不要相信从客户端计算机获得的时间戳是有效的。例如,Date:HTTP标头或javascript Date.getTime()调用。当这些值用作不透明标识符时,或者当在同一客户端上的单个会话中进行日期计算时,它们都很好,但不要试图将这些值与服务器上的值进行交叉引用。您的客户机不运行NTP,并且可能不一定有用于BIOS时钟的工作电池。
琐事
最后,政府有时会做出非常奇怪的事情:
荷兰的标准时间是正好19分32.13秒在1909-05-01年法律规定的UTC之前通过1937-06-30。此时区不能使用HH:MM格式。
好的,我想我完了。
跨越“计算机时间”和“人类时间”的界限是一场噩梦。主要原因是,时区和夏令时的规则没有一种标准。各国可以随时自由更改时区和夏令时规则,他们也可以这样做。
一些国家,例如以色列、巴西,每年都会决定何时实行夏令时,因此无法提前知道夏令时何时生效。其他人对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个)。