夏令时和时区最佳实践

Ode*_*ded 2021 timezone datetime utc datetimeoffset dst

我希望能够将这个问题及其答案作为处理夏令时的权威指南,特别是处理实际的变更问题.

如果您有任何要添加的内容,请执行此操作

许多系统依赖于保持准确的时间,问题在于由于夏令时改变时间 - 向前或向后移动时钟.

例如,在订单获取系统中有一个业务规则取决于订单的时间 - 如果时钟发生变化,规则可能不那么明确.如何保持订单的时间?当然有无数的场景 - 这只是一个说明性的场景.

  • 你是如何处理夏令时问题的?
  • 您的解决方案中有哪些假设?(在这里寻找背景)

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

  • 你尝试了哪些不起作用?
  • 为什么不起作用?

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

一般答案很好,但我也希望看到细节,特别是如果它们只在一个平台上可用.

Yuv*_*dam 911


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

做:

  • 无论何时提到确切的时刻,都要按照不受夏令时影响的统一标准来保持时间.(GMT和UTC在这方面是相同的,但最好使用术语UTC.请注意,UTC也称为ZuluZ时间.)
  • 相反,如果您选择使用本地时间值保留时间,请包括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及更高版本.
  • 如果使用.NET,请考虑使用Noda Time.
  • 如果在没有Noda Time的情况下使用.NET,请考虑这DateTimeOffset通常是比较好的选择DateTime.
  • 如果使用Perl,请使用DateTime.
  • 如果使用Python,请使用pytzdateutil.
  • 如果使用JavaScript,请将moment.jsmoment-timezone扩展名一起使用.
  • 如果使用PHP> 5.2,请使用由类DateTimeDateTimeZone类提供的本机时区转换.使用时要小心DateTimeZone::listAbbreviations()- 见答案.为了使PHP保持最新的Olson数据,请定期安装timezonedb PECL包; 看到答案.
  • 如果使用C++,请确保使用正确实现IANA时区数据库的库.这些包括cctz,ICUHoward Hinnant的"tz"库.
    • 不要将Boost用于时区转换.虽然它的API声称支持标准IANA(也称为"zoneinfo")标识符,但它粗略地将它们映射到POSIX样式的数据,而没有考虑每个区域可能具有的丰富的更改历史记录.(此外,该文件已不再用于维护.)
  • 如果使用Rust,请使用chrono.
  • 大多数业务规则使用民用时间,而不是UTC或GMT.因此,计划在应用应用程序逻辑之前将UTC时间戳转换为本地时区.
  • 请记住,时区和偏移不是固定的,可能会改变.例如,历史上美国和英国使用相同的日期来"前进"和"后退".然而,在2007年,美国改变了时钟变换的日期.这意味着一年中的48周,伦敦时间和纽约时间之间的差异是5小时和4周(春季3个,秋季1个),这是4个小时.在涉及多个区域的任何计算中都要注意这样的项目.
  • 考虑时间类型(实际事件时间,广播时间,相对时间,历史时间,重复时间)您需要存储哪些元素(时间戳,时区偏移和时区名称)以便正确检索 - 请参阅"时间类型" 这个答案.
  • 保持您的操作系统,数据库和应用程序tzdata文件在它们与世界其他地方之间保持同步.
  • 在服务器上,将硬件时钟和OS时钟设置为UTC而不是本地时区.
  • 不管前面的项目点,服务器端代码,包括网站,应该从来没有想到的服务器的本地时区是什么特别. 看到答案.
  • 首选在应用程序代码中逐个使用时区,而不是通过配置文件设置或默认值全局使用.
  • 在所有服务器上使用NTP服务.
  • 如果使用FAT32,请记住时间戳存储在本地时间,而不是UTC.
  • 在处理周期性事件(例如每周电视节目)时,请记住时间随着夏令时的变化而变化,并且在不同时区会有所不同.
  • 始终将日期时间值作为下限包含,上限独占(>=,<).

别:

  • 不要混淆"时区",例如America/New_York"时区偏移",例如-05:00.他们是两个不同的东西.查看时区标签wiki.
  • 不要使用JavaScript的Date对象在旧的Web浏览器中执行日期和时间计算,因为ECMAScript 5.1及更低版本的设计缺陷可能会错误地使用夏令时.(这已在ECMAScript 6/2015中修复).
  • 永远不要相信客户的时钟.这可能是不正确的.
  • 不要告诉人们"始终使用UTC".这种广泛的建议是本文前面所述的几种有效方案的短视.而是对您正在使用的数据使用适当的时间参考.(时间戳可以使用UTC,但未来的时间安排和仅限日期的值不应该.)

测试:

  • 测试时,请确保您在西部,东部,北部和测试国家南方半球(在地球的每个季度其实,这样4个区域)在建,既DST和不(给8),和一个国家,不不使用DST(另外4个覆盖所有区域,共计12个).
  • 测试DST的过渡,即当您在夏季时,从冬季选择时间值.
  • 使用DST测试边界情况,例如UTC + 12的时区,使夏季的当地时间为UTC + 13,冬季甚至为UTC + 13的地方
  • 测试所有第三方库和应用程序,并确保它们正确处理时区数据.
  • 至少测试半小时的时区.

参考:

其他:

  • 大厅让你的代表结束美国夏令时的憎恶.我们总能希望......
  • 地球标准时间的大厅

  • 使用GMT并没有真正解决问题,你仍然需要弄清楚*什么是正确的delta应用,这就是所有复杂性所在.在用于不同区域(具有不同夏令时切换时间表)的用户或显示历史/未来数据的系统中使用的系统中,增量可能很复杂. (31认同)
  • 是的,在Windows中存在这样的OS调用--SystemTimeToTzSpecificLocation.http://msdn.microsoft.com/en-us/library/ms724949(VS.85).aspx (22认同)
  • 请记住将未来日期(甚至是明天)转换为UTC*总是*丢失一些东西.例如,您使用了一些已知的偏移来进行转换,但由于日期是将来的,因此设置这些规则的组总是有可能更改这些规则.此外,几乎不可能将某些未来日期转换为UTC,因为直到那一年才知道夏令时(一些国家每年设定日期,而不是提前10年或基于任何设定规则). (16认同)
  • 如果所有应用程序需要做的是显示当前本地时间,那就是这样.但是,如果我们在澳大利亚有一台服务器需要在2006年4月2日在加拿大显示交易的日期/时间(这是加拿大夏令时切换规则发生变化的最后一年) - 你有OS调用吗?可以做DateTime("2006/04/02 14:35Z").ToLocalTime().WithDaylightSavingRules("Canada",2006)? (10认同)
  • @tchrist也许如果你坚持不懈就可以. (7认同)
  • 我希望它总是这么容易......有时,出于性能原因,您需要聚合(非规范化)特定日期发生的数据,并且聚合*必须*在当地时间,否则客户会开始调用并询问您的网络原因网站错了. (3认同)
  • "坚持"不是及物动词.一个人不能坚持任何事情. (3认同)
  • -1当谈到日期和时间时 - 从你的词汇中消除**总是**.通常,是的,但并非总是如此.有时,除了本地时间之外,存储任何东西都是非法的或违反策略的 - 在这种情况下,您可以存储本地时间+偏移量(例如"DateTimeOffset").其他时候,您可能真的想存储一个纯粹的本地日历时间,因为您的意思是"无论您身在何处都是本地人". (3认同)
  • @Me - 我想把你的报价归功于你,但我很难显示出"现在". (2认同)

blu*_*oon 312

我不确定我能在上面的答案中添加什么,但这里有几点我:

时代的类型

您应该考虑四种不同的时间:

  1. 活动时间:例如,国际体育赛事发生的时间,或加冕/死亡/等等.这取决于事件的时区而不是观众的时区.
  2. 电视时间:例如,特定电视节目在当地时间晚上9点广播.在考虑在您的网站上发布结果(比如说"美国偶像")时很重要
  3. 相对时间:例如:这个问题在21小时内有一个开放的赏金.这很容易显示
  4. 重复时间:例如:即使DST发生变化,电视节目也会在每个星期一晚上9点播出.

还有历史/交替时间.这些都很烦人,因为它们可能无法映射回标准时间.例如:朱利安日期,日期根据土星的农历,克林贡日历.

以UTC格式存储开始/结束时间戳效果很好.对于1,您需要与事件一起存储的事件时区名称+偏移量.对于2,您需要为每个区域存储本地时间标识符,并为每个查看器存储本地时区名称+偏移量(如果您处于紧缩状态,则可以从IP中获取此值).对于3,以UTC秒存储,不需要时区.4是1或2的特殊情况,具体取决于它是全局还是本地事件,但您还需要存储时间戳中创建的内容,以便您可以判断在创建此事件之前或之后是否更改了时区定义.如果您需要显示历史数据,这是必要的.

存放时间

  • 始终以UTC格式存储时间
  • 转换为显示的本地时间(本地由查看数据的用户定义)
  • 存储时区时,需要名称,时间戳和偏移量.这是必需的,因为政府有时会改变其时区的含义(例如:美国政府更改了DST日期),并且您的应用程序需要优雅地处理事情...例如:DST规则之前和之后LOST剧集的确切时间戳显示改变.

偏移和名称

以上的一个例子是:

足球世界杯决赛比赛于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-05-01到1937-06-30,荷兰的标准时间恰好是UTC的19分和32.13秒.使用HH:MM格式无法准确表示此时区.

好的,我想我已经完成了.

  • 为琐事+1.保持内容的有趣性使这项任务更加愉快,这可能会提高生产力:) (45认同)
  • 这个答案有一些很好的观点,我特别想指出这个部分"重复时间:例如:电视节目是在每个星期一晚上9点,即使DST改变"在数据库中以UTC存储时间然后转换显示有助于处理处理时区的许多棘手问题.然而,处理跨越DST障碍的"反复发生的事件"变得更加困难. (6认同)
  • 这个答案中有很多好东西,但有几个问题.1)许多时区缩写都不明确.[见这里](http://www.timeanddate.com/library/abbreviations/timezones/)2)不*总是*你想以UTC格式存储吗?大部分时间 - 是的,但背景很重要.在您的条款中,*电视时间*不会以UTC格式存储.此外,有时它的非法或反对政策不存储当地时间 - 这就像`DateTimeOffset`(或等价物)之类的东西派上用场.否则,好写. (4认同)
  • 荷兰的琐事看起来很合法.http://www.ietf.org/rfc/rfc3339.txt第5.8节.中途认为有人在拉我们的腿. (2认同)

leo*_*loy 87

这是一个重要且令人惊讶的棘手问题.事实是,没有完全令人满意的标准来坚持时间.例如,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.

他的意思是"民事约会时间"("我所在城市的时钟告诉10:30")?在这种情况下,A)是正确的答案.

或者他的意思是"物理瞬间的时间",这是我们宇宙连续时间线上的一个点,比如说,"当下一次日食发生时".在这种情况下,答案B)是正确的.

一些日期/时间API正确地获得了这一区别:其中包括Jodatime,它是下一个(第三个!)Java DateTime API(JSR 310)的基础.

  • 显然约翰想要A)因为人们在8:30去上班,无论目前的DST或时区是什么.如果他们进入DST,他们将在8:30去工作,当他们退出夏令时,他们将在8:30去上班.如果该国决定转移到另一个时区,他们将在8:30开始工作 (2认同)

ZXX*_*ZXX 57

明确关注点的架构分离 - 准确了解哪个层与用户交互,并且必须更改规范表示(UTC)的日期时间.非UTC日期时间是表示(遵循用户本地时区),UTC时间是模型(对于后端和中间层保持唯一).

另外,决定你的实际观众是什么,你不需要服务什么,以及你在哪里画线.不要触摸异国情调的日历,除非您实际上有重要的客户,然后考虑仅针对该区域的单独的面向用户的服务器.

如果您可以获取并维护用户的位置,请使用位置进行系统的日期时间转换(例如.NET文化或SQL表),但如果日期时间对您的用户至关重要,则为最终用户提供选择替代的方法.

如果涉及历史审计义务(比如确切知道2月前Jo在AZ支付账单的时间),那么请保留UTC和当地时间进行记录(您的转换表将在一段时间内发生变化).

为批量生成的数据定义时间参考时区 - 如文件,Web服务等.假设East Coast公司在CA中有数据中心 - 您需要询问并知道他们使用什么作为标准而不是假设其中一个.

不要信任嵌入在日期时间的文本表示中的时区偏移,并且不接受解析和遵循它们.而是始终要求必须明确定义时区和/或参考区域.您可以轻松地接收PST偏移的时间,但时间实际上是EST,因为这是客户端的参考时间,而记录只是在PST中的服务器上导出.


Jon*_*ler 39

您需要了解Olson tz数据库,该数据库可从ftp://elsie.nci.nih.gov/pub http://iana.org/time-zones/获得.它每年更新多次,以处理世界各地不同国家在冬季和夏季(标准和夏令时)之间切换的时间(以及是否)的最后时刻变化.2009年,最后一个版本是2009年; 在2010年,它是2010n; 在2011年,它是2011n; 截至2012年5月底,发布时间为2012c.请注意,有一组代码可以在两个单独的存档(tzcode20xxy.tar.gz和tzdata20xxy.tar.gz)中管理数据和实际时区数据本身.代码和数据都属于公共领域.

这是时区名称的来源,例如America/Los_Angeles(以及美国/太平洋等同义词).

如果您需要跟踪不同的区域,那么您需要Olson数据库.正如其他人所建议的那样,您还希望以固定格式存储数据 - 通常是选择的UTC - 以及生成数据的时区记录.您可能希望区分当时与UTC的偏移量和时区名称; 这可以在以后产生影响.此外,知道它目前是2010-03-28T23:47:00-07:00(美国/太平洋)可能会或可能不会帮助您解释2010-11-15T12:30的值 - 这可能是在PST中指定的(太平洋标准时间)而非PDT(太平洋夏令时).

标准的C库接口对这类东西并没有太大的帮助.


Olson的数据有所改变,部分原因是因为AD Olson将很快退休,部分原因是因为版权侵权的维护者有一项(现已被驳回的)法律诉讼.现在,时区数据库在IANA(互联网号码分配机构)的主持下进行管理,首页上有一个"时区数据库"链接.讨论邮件列表现在是tz@iana.org; 公告清单是tz-announce@iana.org.

  • Olson数据库也包含*历史*数据,这使得它对处理DST特别有用.例如,它知道对应于2000年3月31日在美国的UTC值不是DST,而是对应于2008年3月31日在美国的UTC值. (11认同)
  • Unicode Consortium维护Olson tome区域ID和Windows时区ID之间的映射:http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/windows_tzid.html (3认同)

oef*_*efe 25

通常,在存储的时间戳中包括本地时间偏移量(包括DST偏移量):如果稍后要在其原始时区(和DST设置)中显示时间戳,则仅使用UTC是不够的.

请记住,偏移量并不总是整数小时(例如印度标准时间是UTC + 05:30).

例如,合适的格式是元组(unix时间,以分钟为单位的偏移量)或ISO 8601.

  • 对于显示,偏移是完美的.如果要进行更改,则偏移量仍然不足.您还必须知道时区,因为新值可能需要不同的偏移量. (4认同)

Ric*_*ard 23

越过"计算机时间"和"人们时间"的界限是一场噩梦.主要的一点是,时区和夏令时的规则没有任何标准.各国可随时自由改变其时区和DST规则,而且确实如此.

一些国家,例如以色列,巴西,每年决定何时进行夏令时,因此不可能提前知道(如果)DST何时生效.其他人有关于DST何时生效的固定(ish)规则.其他国家不使用夏令时.

时区不一定与格林威治标准时间完全不同.尼泊尔是+5.45.甚至还有时区为+13.这意味着:

SUN 23:00 in Howland Island (-12)
MON 11:00 GMT 
TUE 00:00 in Tonga (+13)
Run Code Online (Sandbox Code Playgroud)

是同一时间,但3个不同的日子!

时区的缩写也没有明确的标准,以及它们在DST中如何变化,所以你最终得到这样的东西:

AST Arab Standard Time     UTC+03
AST Arabian Standard Time  UTC+04
AST Arabic Standard Time   UTC+03
Run Code Online (Sandbox Code Playgroud)

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

在进行测试时,请确保您测试西半球和东半球的国家/地区是否正在进行DST,以及未使用DST的国家/地区(总共6个).


she*_*iel 20

对于PHP:

PHP> 5.2中的DateTimeZone类已经基于其他人提到的Olson DB,因此如果您在PHP中而不是在DB中进行时区转换,则可以免除使用(难以理解的)Olson文件.

但是,PHP没有像Olson DB那样频繁更新,因此仅使用PHP时区转换可能会留下过时的DST信息,并影响数据的正确性.虽然预计这种情况不会频繁发生,但如果全球拥有大量用户,情况可能发生.

要解决上述问题,请使用timezonedb pecl包,其功能是更新PHP的时区数据.按照更新的频率安装此软件包.(我不确定这些软件包更新是否完全遵循Olson更新,但似乎更新的频率至少非常接近Olson更新.)


Mat*_*caj 18

如果您的设计可以容纳它,请避免本地时间转换!

我知道有些人可能听起来很疯狂但是考虑一下用户体验:用户处理的时间比相对日期(今天,昨天,下周一)快于绝对日期(2010.09.17,周一9月17日).当你考虑更多时,时区(和DST)的准确性越接近日期越近now(),所以如果你能用相对格式表达日期/日期时间+/- 1或2周,其余的日期可以是UTC,对95%的用户来说都不会太重要.

这样,您可以以UTC格式存储所有日期,并以UTC格式进行相对比较,只显示相对日期阈值之外的用户UTC日期.

这也可以应用于用户输入(但通常以更有限的方式).从只有{昨天,今天,明天,下周一,下周四}的下拉菜单中选择对于用户来说比日期选择器更简单,更容易.采摘日期是形式填充最痛苦的组成部分.当然,这对所有情况都不适用,但你可以看到它只需要一点巧妙的设计就可以使它变得非常强大.


ric*_*ent 15

虽然我没有尝试过,但我觉得引人注目的时区调整方法如下:

  1. 以UTC格式存储所有内容

  2. 创建一个TZOffsets包含三列的表:RegionClassId,StartDateTime和OffsetMinutes(int,以分钟为单位).

在该表中,存储日期和时间的列表时,当地的时间而改变,并且由多少.表中的区域数量和日期数量取决于您需要支持的日期和地区范围.可以把它想象成是"历史"日期,即使日期应该包括未来的某些实际限制.

当您需要计算任何UTC时间的本地时间时,只需执行以下操作:

SELECT DATEADD('m', SUM(OffsetMinutes), @inputdatetime) AS LocalDateTime
FROM   TZOffsets
WHERE  StartDateTime <= @inputdatetime
       AND RegionClassId = @RegionClassId;
Run Code Online (Sandbox Code Playgroud)

您可能希望在应用程序中缓存此表并使用LINQ或类似方法来执行查询而不是访问数据库.

此数据可以从公共域tz数据库中提取.

这种方法的优点和脚注:

  1. 没有规则被编入代码,您可以轻松调整新区域或日期范围的偏移.
  2. 您不必支持每个日期或区域范围,您可以根据需要添加它们.
  3. 区域不必直接对应地缘政治边界,并且为了避免重复行(例如,美国大多数州以相同的方式处理DST),您可以拥有在另一个表中链接到更传统的列表的广泛RegionClass条目国家,国家等
  4. 对于像美国这样的情况,过去几年DST的开始和结束日期发生了变化,这很容易处理.
  5. 由于StartDateTime字段也可以存储时间,因此可以轻松处理2:00 AM标准转换时间.
  6. 世界上并非所有地方都使用1小时的夏令时.这很容易处理这些情况.
  7. 数据表是跨平台的,可以是一个单独的开源项目,可供几乎使用任何数据库平台或编程语言的开发人员使用.
  8. 这可用于与时区无关的偏移.例如,不时发生的1秒调整,以调整地球的自转,历史调整和公历等.
  9. 由于这是在数据库表中,标准报表查询等可以利用数据而无需通过业务逻辑代码.
  10. 如果您需要,它还可以处理时区偏移,甚至可以考虑将区域分配到另一个时区的特殊历史情况.您所需要的只是一个初始日期,它为每个区域分配一个时区偏移,并且开始日期最短.这需要为每个时区创建至少一个区域,但是可以让您提出一些有趣的问题:"Yuma,Arizona和Seattle,Washington,1989年2月2日上午5:00之间的当地时间有什么不同?" (只需从另一个中减去一个SUM()).

现在,这种方法或任何其他方法的唯一缺点是本地时间到GMT的转换并不完美,因为任何对时钟具有负偏移的DST改变都会重复给定的本地时间.我担心,没有简单的方法可以解决这个问题,这也是存储当地时间的一个原因.

  • 您的数据库想法已经作为Olson数据库实现.夏令时确实会产生重叠,指定日光特定时区可以帮助解决问题.美国东部时间2:15和美国东部夏令时间2:15是不同的时间.正如在其他帖子中指出的那样,指定偏移也解决了模糊性. (8认同)
  • 保留自己的数据库的一个大问题是保持更新.Olson和Windows都是为您维护的.由于表格过时,我遇到了不止一次DST转换错误的情况.完全剥离它们并依赖于框架或OS级别数据库更加可靠. (5认同)
  • **不要创建自己的数据库**:始终依赖系统的API! (4认同)

Ian*_*ose 14

我已经在两种类型的系统上实现了这一点,"轮班规划系统(例如工厂工人)"和"气体依赖管理系统"......

23和25小时的长日是一个痛苦应对,因此8小时轮班需要7小时或9小时.问题是你会发现每个客户,甚至客户的部门都有不同的规则(通常没有记录)他们在这些特殊情况下做了什么.

在他们为您的"现成"软件付款之前,最好不要询问客户的一些问题.在购买软件时,很难找到预先考虑此类问题的客户.

我认为在所有情况下,您都应该记录UTC时间并在存储日期/时间之前转换为/从本地时间转换.但是,即使知道哪些时间占用了一段时间,也可能很难使用夏令时和时区.

  • 我的女朋友,一名护士,晚上工作,他们必须在DST切换期间写下时区.例如,2AM CST vs 2AM CDT (6认同)

Joo*_*oon 13

我最近在一个Web应用程序中遇到了一个问题,在Ajax回发时,返回到我的服务器端代码的日期时间与提供的日期时间不同.

它很可能与客户端上的JavaScript代码有关,它构建了以字符串形式发回客户端的日期,因为JavaScript正在调整时区和夏令时,并且在某些浏览器中计算何时应用夏令时似乎与其他人不同.

最后,我选择完全删除客户端上的日期和时间计算,然后使用整数键将其发回给我的服务器,然后将其转换为服务器上的日期时间,以实现一致的转换.

我从中学到:除非你绝对必须,否则不要在Web应用程序中使用JavaScript日期和时间计算.


Mat*_*int 12

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

常见的建议是将服务器的时区设置为UTC.这确实是一个很好的最佳实践,但它可以作为不遵循其他最佳实践的应用程序的创可贴.例如,服务可能正在写入具有本地时间戳而不是基于UTC的时间戳的日志文件,从而在夏令时回退过渡期间产生歧义.将服务器的时区设置为UTC将修复应用程序.但是真正的解决方案是应用程序使用UTC开始记录.

服务器端代码(包括网站)绝不应该期望服务器的本地时区特别是任何东西.

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

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


小智 11

将服务器设置为UTC,并确保它们都配置为ntp或等效服务器.

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


Yar*_*rin 11

对于网络来说,规则并不复杂......

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

其余的只是使用服务器端日期时间库的UTC /本地转换.很高兴...

  • 这是作为起点的好建议,但它完全取决于应用程序。这对于友好的网站来说可能没问题,但是如果您的应用程序有任何法律/司法/财务方面的人可能会起诉(我已经处理了几个),那么这是一种过度简化,因为有不同种类的 '时间”,如本页其他地方所述。 (3认同)

paq*_*etp 9

处理存储在FAT32文件系统中的时间戳时要小心 - 它始终保存在本地时间坐标(包括DST - 请参阅msdn文章)中.烧了那个.


Sol*_*yad 7

另一件事是,确保服务器应用了最新的夏令时补丁.

去年我们遇到过一种情况,即使我们使用的是基于UTC的系统,我们的时间在北美用户的三周时间内一直持续一小时.

事实证明它最终是服务器.他们只需要应用最新的补丁(Windows Server 2003).


Jon*_*han 6

PHP的DateTimeZone::listAbbreviations()输出

这个PHP方法返回一个包含一些"主要"时区(如CEST)的关联数组,这些时区本身包含更具体的"地理"时区(如欧洲/阿姆斯特丹).

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

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

例如,欧洲/阿姆斯特丹可以在此功能的输出中找到六次.两次出现(抵消1172/4772)是阿姆斯特丹时间,直到1937年; 两个(1200/4800)是1937年至1940年间使用的时间; 两个(3600/4800)是自1940年以来使用的时间.

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

如果你想知道某个时区的当前偏移/ DST,你必须做这样的事情:

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


Don*_*ows 5

业务规则应始终适用于民事时间(除非立法另有说明).请注意,民用时间是一团糟,但它是人们使用的,所以它是重要的.

在内部,将时间戳保持在像纪元的民间时间之类的东西中.这个时代并不重要(我赞成Unix纪元)但它确实比其他选择更容易.假设闰秒不存在,除非你正在做一些真正需要它们的东西(例如,卫星跟踪).时间戳和显示时间之间的映射是应该应用DST规则的唯一点; 规则经常变化(在全球范围内,一年几次;责怪政治家)所以你应该确保你不对映射进行硬编码.Olson的TZ数据库非常宝贵.

  • 这里的问题是民用时间(又名日历时间)不能恰当地代表一个时刻.如果你采用从时代开始的秒数方法,你是否真的会考虑到为夏令时转换而跳过或重绕的每一刻?可能不是.Epoch基础仅适用于UTC或其他固定的瞬时时间参考. (3认同)

vwe*_*ert 5

如果您碰巧维护使用DST活动的数据库系统,请仔细检查它们是否需要在秋季过渡期间关闭.Mandy DBS(或其他系统)也不喜欢在(本地)时间两次传递相同的点,这正是你在秋季转回时钟时发生的事情.SAP已经通过(恕我直言,非常整洁)的解决方案解决了这个问题 - 他们只是让内部时钟以正常速度的一半运行两个小时......