我希望将这个问题及其答案作为处理夏令时的最终指南,特别是处理实际转换时。
如果你有什么要补充的,请做
许多系统都依赖于保持准确的时间,问题是由于夏时制而导致的时间变化——向前或向后移动时钟。
例如,一个订单接受系统中的业务规则取决于订单的时间——如果时钟发生变化,规则可能就不那么清晰了。应如何保持订单的时间?当然,有无数的场景——这只是一个例证。
你是如何处理日光节约问题的?您的解决方案包含哪些假设?(在此处查找上下文)
同样重要,如果不是更重要的话:
你尝试了什么但没有奏效?为什么不起作用?
我会对编程、操作系统、数据持久性和其他相关方面感兴趣。
一般的答案很好,但我也希望看到细节,特别是如果它们只在一个平台上提供的话。
跨越“计算机时间”和“人类时间”的界限是一场噩梦。主要原因是,时区和夏令时的规则没有一种标准。各国可以随时自由更改时区和夏令时规则,他们也可以这样做。
一些国家,例如以色列、巴西,每年都会决定何时实行夏令时,因此无法提前知道夏令时何时生效。其他人对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个)。
答案和其他数据摘要:(请添加您的答案)
Do:
无论何时,只要你指的是一个确切的时刻,都要根据不受夏令时影响的统一标准坚持时间。(GMT和UTC在这方面相当,但最好使用UTC一词。请注意,UTC也被称为祖鲁时间或Z时间。)相反,如果您选择使用本地时间值保存一个(过去的)时间,请包括该特定时间与UTC的本地时间偏移量(该偏移量可能会在一年中发生变化),以便以后可以明确地解释时间戳。在某些情况下,您可能需要同时存储UTC时间和等效的本地时间。通常这是通过两个单独的字段来完成的,但有些平台支持datetimeoffset类型,可以将这两个字段存储在一个字段中。当将时间戳存储为数值时,请使用Unix时间-这是自1970-01-01T00:00:00Z以来的整秒数(不包括闰秒)。如果需要更高的精度,请改用毫秒。该值应始终基于UTC,不进行任何时区调整。如果以后可能需要修改时间戳,请包括原始时区ID,以便确定偏移量是否与记录的原始值发生了变化。在安排未来事件时,通常首选当地时间而不是UTC,因为偏移量通常会发生变化。请参阅答案和博客文章。存储整个日期(如生日和周年纪念日)时,不要转换为UTC或任何其他时区。如果可能,请存储不包含时间的仅日期数据类型。如果这种类型不可用,请确保在解释值时始终忽略一天中的时间。如果您不能保证一天中的时间会被忽略,请选择中午12:00,而不是午夜00:00作为当天更安全的代表时间。请记住,时区偏移并不总是整数小时(例如,印度标准时间为UTC+05:30,尼泊尔使用UTC+05:45)。如果使用Java,请将Java.time用于Java 8和更高版本。java.time的大部分功能在ThreeTen Backport库中被向后移植到java 6和7。进一步适用于ThreeTenABP库中的早期Android(<26)。这些项目正式取代了现在处于维护模式的久负盛名的Joda Time。Joda Time、ThreeTen Backport、ThreeTen-Extra、java.Time类和JSR 310由同一个人Stephen Colebourne领导。如果使用.NET,请考虑使用Noda Time。如果使用没有Noda Time的.NET,请考虑DateTimeOffset通常比DateTime更好。如果使用Perl,请使用DateTime。如果使用Python 3.9或更高版本,请使用内置的zoneinfo处理时区。否则,请使用dateutil或arrow。通常可以避免使用较旧的pytz库。如果使用JavaScript,请避免使用旧的moment.js或moment时区库,因为它们不再被主动维护。有关详细信息,请参阅Moment.js项目状态。相反,考虑Luxon、date fns、day.js或js joda。如果使用PHP>5.2,请使用DateTime和DateTimeZone类提供的本地时区转换。使用DateTimeZone::listAb缩略语()时要小心-请参阅答案。要使PHP保持最新的Olson数据,请定期安装timezonedb PECL包;见答案。如果使用C++,请确保使用正确实现IANA时区数据库的库。其中包括cctz、ICU和霍华德·希南特的“tz”图书馆。在C++20中,后者被采用到标准<chrono>库中。不要将Boost用于时区转换。尽管其API声称支持标准IANA(又称“zoneinfo”)标识符,但它将它们粗略地映射到POSIX风格的数据,而没有考虑每个区域可能发生的丰富变化历史。(此外,该文件已无法维护。)如果使用Rust,请使用chrono。大多数业务规则使用民用时间,而不是UTC或GMT。因此,在应用应用程序逻辑之前,计划将UTC时间戳转换为本地时区。请记住,时区和偏移不是固定的,可能会改变。例如,历史上,美国和英国使用相同的日期来“向前冲”和“向后冲”。然而,在2007年,美国改变了时钟的日期。这意味着一年中的48周,伦敦时间和纽约时间相差5小时,4周(春季3小时,秋季1小时)相差4小时。在涉及多个区域的任何计算中,请注意类似的项目。考虑时间类型(实际事件时间、广播时间、相对时间、历史时间、重现时间),您需要存储哪些元素(时间戳、时区偏移和时区名称)以进行正确检索-请参阅本答案中的“时间类型”。让您的操作系统、数据库和应用程序tzdata文件在它们与世界其他地方之间保持同步。在服务器上,将硬件时钟和操作系统时钟设置为UTC,而不是本地时区。无论前面的要点是什么,服务器端代码(包括网站)都不应该期望服务器的本地时区是任何特定的。见答案。更喜欢在应用程序代码中逐个处理时区,而不是通过配置文件设置或默认值进行全局处理。在所有服务器上使用NTP服务。如果使用FAT32,请记住时间戳存储在本地时间,而不是UTC。当处理重复发生的事件(例如每周电视节目)时,请记住,时间会随着夏令时的变化而变化,并且不同时区的时间也会不同。始终将日期时间值查询为下限包含,上限不包含(>=,<)。
不要:
不要将“时区”(如美国/纽约)与“时区偏移”(如-05:00)混淆。它们是两种不同的东西。请参见时区标签wiki。不要使用JavaScript的Date对象在较旧的web浏览器中执行日期和时间计算,因为ECMAScript 5.1及更低版本有一个设计缺陷,可能会错误地使用夏时制。(这在ECMAScript 6/2015中已修复)。永远不要相信客户的时钟。这很可能是不正确的。不要告诉人们“在任何地方都要使用UTC”。这一广泛的建议是对本文档前面描述的几种有效场景的短视。相反,对正在处理的数据使用适当的时间参考。(时间戳可以使用UTC,但未来时间调度和仅日期值不应使用。)
测试:
测试时,请确保您测试了西半球、东半球、北半球和南半球的国家(事实上,在全球每四分之一的地区,共有4个地区),无论是否正在进行夏令时测试(给出8个),以及一个不使用夏令时的国家(另外4个国家覆盖所有地区,共12个)。测试DST转换,即当您当前处于夏季时,选择冬季的时间值。测试边界情况,例如UTC+12时区,夏令时,使当地时间UTC+13在夏季,甚至UTC+13的地方在冬季测试所有第三方库和应用程序,确保它们正确处理时区数据。至少测试半小时时区。
参考:
堆栈溢出上的详细时区标记wiki页面Olson数据库,又名Tz_databaseIETF奥尔森数据库维护程序草案时区和夏令时的来源ISO格式(ISO 8601)UnicodeConsortium提供的Olson数据库与Windows时区ID之间的映射维基百科上的时区页面StackOverflow问题标记为dstStackOverflow问题标记了时区处理DST-Microsoft DateTime最佳实践维基百科上的网络时间协议
其他:
游说你的代表结束DST这一令人厌恶的行为。我们总是希望。。。地球标准时间大厅