夏令时和时区最佳实践

我希望使这个问题及其答案成为处理夏时制(尤其是处理实际变更)的权威指南。 如果您要添加任何内容,请执行 许多系统都依赖于保持准确的时间,问题在于夏时制导致的时间变化-向前或向后移动时钟
摘要由CSDN通过智能技术生成

我希望使这个问题及其答案成为处理夏时制(尤其是处理实际变更)的权威指南。

如果您要添加任何内容,请执行

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

例如,一个在接订单系统中有取决于订单时间的业务规则-如果时钟改变,则规则可能不太清楚。 订购时间应如何保留? 当然,有无数种情况-这只是一种说明。

  • 您如何处理夏令时问题?
  • 解决方案中包含哪些假设? (在此处查找上下文)

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

  • 您尝试了什么却不起作用?
  • 为什么不起作用?

我会对编程,操作系统,数据持久性以及该问题的其他相关方面感兴趣。

一般的答案很好,但是我也想看看细节,特别是如果它们仅在一个平台上可用。


#1楼

永远不要只依赖像

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

当由于DST导致某个日期时间不存在时,它们可以引发异常。 相反,应构建自己的方法来创建此类日期。 在它们中,捕获由于DST发生的所有异常,并需要用转换偏移量调整时间。 DST可能会在不同的日期和不同的时间(对于巴西甚至在午夜)发生。


#2楼

对于网络而言,规则并不那么复杂...

  • 服务器端,使用UTC
  • 客户端,使用Olson
    • 原因:UTC偏移不是夏令时安全的(例如,纽约是一年中的EST(UTC-5小时),一年中其余时间是EDT(UTC-4小时))。
    • 对于客户端时区确定,您有两个选择:

剩下的只是使用服务器端日期时间库的UTC /本地转换。 好去...


#3楼

对于那些在.NET上苦苦挣扎的人,请参阅使用DateTimeOffset和/或TimeZoneInfo是否值得一试。

如果您想使用IANA / Olson时区 ,或者发现内置类型不足以满足您的需求,请查看Noda Time ,它为.NET提供了更智能的日期和时间API。


#4楼

PHP的DateTimeZone::listAbbreviations()输出

此PHP方法返回一个包含一些“主要”时区(例如CEST)的关联数组,这些时区本身包含更特定的“地理”时区(例如欧洲/阿姆斯特丹)。

如果您正在使用这些时区及其偏移量/ DST信息,那么实现以下内容非常重要:

似乎每个时区的所有不同偏移量/ DST配置 (包括历史配置)都包括在内!

例如,在此函数的输出中可以找到六次欧洲/阿姆斯特丹。 直到1937年为止的阿姆斯特丹时间都有两次出现(偏移1172/4772); 其中两个(1200/4800)用于1937年至1940年之间的时间; 和两个(3600/4800)是自1940年以来使用的时间。

因此, 您不能依赖此函数当前正确/正在使用的偏移/ DST信息

如果您想知道某个时区的当前偏移/ DST,则必须执行以下操作:

<?php
$now = new DateTime(null, new DateTimeZone('Europe/Amsterdam'));
echo $now->getOffset();
?>

#5楼

业务规则应始终在民事时间生效 (除非法律另有规定)。 请注意,民事时间是一团糟,但这是人们所使用的,所以这很重要。

在内部,将时间戳记保持为距民用时间秒数之类的时间。 纪元并不重要(我更喜欢Unix纪元 ),但确实比其他事情容易。 假装leap秒根本就不存在,除非您正在做某些真正需要leap秒的事情(例如,卫星跟踪)。 时间戳和显示时间之间的映射是应该应用DST规则的唯一点; 规则经常更改(在全球范围内,每年几次;指责政客),因此您应确保不对映射进行硬编码。 奥尔森的TZ数据库非常宝贵。


#6楼

答案和其他数据摘要:(请添加您的答案)

做:

  • 每当您指的是确切的时间时,请按照不受夏令时影响的统一标准坚持时间。 (GMT和UTC在这方面是等效的,但最好使用术语UTC。请注意,UTC也称为ZuluZ time。)
  • 如果相反,您选择使用本地时间值来保留时间,则包括该特定时间与UTC的本地时间偏移量(此偏移量可能会在全年中发生变化),以便以后可以明确地解释时间戳。
  • 在某些情况下,你可能需要同时存储UTC时间和等效本地时间。 通常,这是通过两个单独的字段完成的,但是某些平台支持可以将两个字段都存储在一个字段中的datetimeoffset类型。
  • 将时间戳记存储为数值时,请使用Unix时间 -这是自1970-01-01T00:00:00Z以来的秒数(不包括leap秒)。 如果需要更高的精度,请改用毫秒。 此值应始终基于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)
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值