夏令时和时区最佳做法
我希望将这个问题及其答案作为处理夏令时的权威性指南,特别是处理实际变更的过程。
如果你有任何补充,请做
许多系统都依赖于保持准确的时间,问题在于由于夏令时而改变时间 - 向前或向后移动时钟。
例如,一个订单服务系统中的业务规则取决于订单的时间 - 如果时钟发生变化,规则可能不那么清晰。 订单的时间应该如何持续? 当然有无数的情景 - 这只是一个例证。
同样重要的是,如果不是如此:
我会对编程,操作系统,数据持久性和其他相关问题感兴趣。
一般的答案很好,但我也希望看到详细信息,特别是如果他们只在一个平台上可用。
答案和其他数据摘要:(请加上你的)
做:
datetimeoffset
类型。 1970-01-01T00:00:00Z
以来的整秒数(不包括闰秒)。 如果您需要更高的精度,请改用毫秒。 此值应始终基于UTC,无需任何时区调整。 DateTimeOffset
通常是比DateTime
更好的选择。 DateTime
和DateTimeZone
类提供的本地时区转换。 使用DateTimeZone::listAbbreviations()
时要小心 - 请参阅答案。 要使PHP保持最新的Olson数据,请定期安装timezonedb PECL包; 见答案。 >=
, <
)。 别:
America/New_York
与“时区偏移”(例如-05:00
混淆。 他们是两个不同的东西。 查看时区标记wiki。 Date
对象在较早的Web浏览器中执行日期和时间计算,因为ECMAScript 5.1及更低版本有可能错误地使用夏令时的设计缺陷。 (这在ECMAScript 6/2015中得到了修复)。 测试:
参考:
timezone
标签wiki页面 dst
timezone
其他:
我不确定我可以在上面的答案中添加什么,但是这里有几点来自我:
时代的类型
有四个不同的时间你应该考虑:
还有历史/替代时间。 这些都很烦人,因为它们可能无法映射回标准时间。 例如:朱利安日期,根据土星农历,克林贡日历的日期。
以UTC存储开始/结束时间戳效果很好。 对于1,您需要一个与事件一起存储的事件时区名称+偏移量。 对于2,您需要存储每个区域的本地时间标识符以及为每个查看器存储的本地时区名称+偏移量(如果您处于紧缩状态,可以从IP中获得此值)。 对于3,以UTC秒存储并且不需要时区。 4是1或2的特殊情况,具体取决于它是全局事件还是本地事件,但您还需要存储创建的时间戳,以便您可以确定在创建此事件之前或之后是否更改了时区定义。 如果您需要显示历史数据,这是必需的。
储存时间
偏移和名称
以上的例子是:
足球世界杯决赛比赛于2010年7月11日19:00 UTC在南非(UTC + 2 - SAST)举行。
有了这些信息,即使南非时区定义发生变化,我们也可以历史性地确定2010年WCS总决赛的确切时间, 并且能够在查询数据库时将其显示给当地时区的观众。
系统时间
您还需要保持操作系统,数据库和应用程序tzdata文件彼此同步,并与世界其他地方保持同步,并在升级时进行广泛测试。 您所依赖的第三方应用程序没有正确处理TZ更改并不是闻所未闻。
确保硬件时钟设置为UTC,如果您在世界各地运行服务器,请确保其操作系统配置为使用UTC。 当您需要从多个时区中的服务器复制按小时轮播的apache日志文件时,这一点变得明显。 按文件名对它们进行排序仅适用于所有文件都使用相同时区命名的情况。 这也意味着,当你从一个盒子到另一个盒子并且需要比较时间戳时,你不必在脑中进行日期数学计算。
另外,在所有盒子上运行ntpd。
客户端
永远不要相信您从客户端计算机获得的时间戳有效。 例如,Date:HTTP标头,或者一个javascript Date.getTime()
调用。 当用作不透明标识符时,或者在同一客户端的单个会话期间进行日期数学计算时,这些都没有问题,但不要尝试将这些值与服务器上的某些值进行交叉引用。 您的客户不运行NTP,并且可能不需要为他们的BIOS时钟准备好工作电池。
琐事
最后,政府有时会做很奇怪的事情:
荷兰标准时间从1909年5月1日至1937年6月30日,法定时间为19分钟32.13秒。 使用HH:MM格式无法准确表示此时区。
好吧,我想我已经完成了。
这是一个重要且令人惊讶的难题。 事实是,持续时间没有完全令人满意的标准。 例如,SQL标准和ISO格式(ISO 8601)显然是不够的。
从概念的角度来看,通常会处理两种类型的时间日期数据,并且便于区分它们(上述标准没有):“ 实际时间 ”和“ 公民时间 ”。
“物理”时间瞬间是物理学处理的连续通用时间轴上的一个点(当然,忽略相对性)。 例如,如果您可以忽略闰秒,则可以对此概念进行充分编码 - 以UTC保存。
“民间”时间是遵循民事规范的日期时间规范:此处的时间点由一组日期时间字段(Y,M,D,H,MM,S,FS)加上TZ(时区规范) (实际上也是“日历”,但让我们假设我们将讨论限制于公历)。 时区和日历共同允许(原则上)从一个表示映射到另一个表示。 但是,公民和物理时间刻度是根本不同类型的大小,应该保持它们在概念上的分离和不同的处理(类比:字节和字符串阵列)。
这个问题令人困惑,因为我们可以互换地谈论这些类型的事件,并且因为民间时代受到政治变化的影响。 问题(以及区分这些概念的需要)对未来的事件更为明显。 例子(来自我在这里的讨论。
约翰在他的日历中记录了2019-Jul-27, 10:30:00
TZ = Chile/Santiago
日期时间的一些事件提示(它抵消了GMT-4,因此它对应于UTC 2019-Jul-27 14:30:00
)。 但是在未来的某一天,该国决定将TZ的偏移量改为GMT-5。
现在,当一天到来...应该提醒触发
A) 2019-Jul-27 10:30:00 Chile/Santiago
= UTC time 2019-Jul-27 15:30:00
?
要么
B) 2019-Jul-27 9:30:00 Chile/Santiago
= UTC time 2019-Jul-27 14:30:00
?
没有正确的答案,除非人们知道约翰在讲日历时的概念意思“请在2019-Jul-27, 10:30:00 TZ=Chile/Santiago
给我2019-Jul-27, 10:30:00 TZ=Chile/Santiago
”。
他的意思是“公民日期时间”(“当我的城市的时钟告诉10:30”)? 在这种情况下,A)是正确的答案。
还是他的意思是“物理时间瞬间”,即我们宇宙连续时间线中的一个点,比如说“下一次日食发生时”。 在这种情况下,答案B)是正确的。
一些日期/时间API可以正确区分这个区别:其中包括Jodatime,它是下一个(第三个!)Java DateTime API(JSR 310)的基础。
链接地址: http://www.djcxy.com/p/767.html上一篇: Daylight saving time and time zone best practices
下一篇: How to insert an item into an array at a specific index?