JavaScript、时区和夏令时

Posted

技术标签:

【中文标题】JavaScript、时区和夏令时【英文标题】:JavaScript, time zones, and daylight savings time 【发布时间】:2012-03-21 13:31:06 【问题描述】:

欢迎收看本周的又一个时区问题

我对 SO 进行了相当多的阅读,试图操纵 moment.js 和 date.js 来帮助我,并且自从我开始尝试解决这个问题以来,我通常会感到沮丧,所以如果有人可以帮助或指出我无法找到的关于 SO 的重复问题,那太棒了。


我有一个页面。此页面显示一系列时间,例如:7:28、7:38、7:48。我知道这些是上午/下午。这些时间始终是美国/纽约(夏令时更改时它们不会更改,因为无论 DST 如何,它们对应的事件总是在那个时间发生)。让我们称它们为时间表。我想强调下一个即将到来的时间。

这对于生活在美国/纽约的人们来说是微不足道的。 这对于生活在美国/洛杉矶的人来说并不算太糟糕(假设我的逻辑有效)。 我可以把计算机在美国/洛杉矶的当前时间,转换成UTC,然后判断美国/洛杉矶当前是否正在观察夏令时,并确定美国/纽约应该是-0400还是-0500 ,将其应用于 UTC,并进行比较。这有点伤人,因为您仍然总是在处理位于美国/洛杉矶的 Date 并且实际上并没有更改 Date 对象的时区,但是我有一种可靠的方法可以从 UTC 回滚(或向前)小时时间。

但是,当我尝试确定是否从完全不遵守夏令时的地区的计算机上遵守夏令时时会发生什么?

据我所知,javascript 只会为当前时区创建 Date 对象,然后根据该 Date 对象来确定 DST。

我应该不在乎吗?无论如何,时代主要只与生活在美国/纽约的人有关。我只是想构建一个从另一个时区查看时有意义的应用程序,这样当它在 country_without_DST 的凌晨 3 点和在美国/纽约的下午 2 点时,“时间表”突出显示下午 2:05 的事情即将发生并且不是凌晨 3:05 的事情。

【问题讨论】:

您能否在 jsfiddle 上创建一个显示问题行为的最小失败示例?一个失败的 qunit 测试会很棒。 jsfiddle.net/bBdL5 - 为了看到这种现象,您需要先在具有 DST 的时区中观察页面。您将看到两个偏移量返回不同。然后将您的时区设置为不遵守 DST 的时区,退出浏览器并重新启动它。请参阅以下两张图片:i.imgur.com/pxqIj.jpg 和 i.imgur.com/ZaXi6.jpg - 我不知道是否有另一种方法来确定 DST 是否发生而不是我所显示的(这就是 Date.js 的做法) 现在我正在构建示例,我想我可以简单地对一些日期进行硬编码来帮助我确定是否是夏令时,但是我想转换的区域是否应该停止观察 DST,如果没有代码维护就会失败。 那个和一个时区的一天可能是不同时区的不同一天(例如:纽约时区变化的前一天是时区变化的那天北京时间)。不仅如此,似乎即使是同时遵守夏令时的国家也可能在不同的日子观察它们(欧盟和美国在 3 月是不同的日子),所以即使从 DST 观察中计算,结果有时仍然是错误的时区。 我看不到这里有什么问题。看起来您已经证明 date.js 非常擅长确定本地时间的时区偏移量。如果您想显示另一个时区的时间,请考虑使用 setTimezoneOffset? 【参考方案1】:

所有与时间的比较都应使用您的实例的getTime() 完成。这将返回自 UTC 纪元以来的毫秒数。 DST 没关系。您将getTime() 值发送到您的服务器。然后,您的客户端脚本会将此值转换回 JavaScript Date 对象,如下所示:

mydate = new Date(longmillisFromAnotherTZ);

然后使用mydate 上的任何方法来显示您想要的日期。这有意义吗?我看不出有什么问题。不过,我很乐意澄清任何事情。

编辑:

只是为了 100% 清楚...

如果两个不同的客户端需要在不同的时区相互显示他们的操作,我建议您只使用来自(new Date()).getTime() 的值,然后将其保存到服务器。然后,服务器将此值发送给每个相应的客户端。然后,客户端负责在其自己的适当语言环境中显示它。

另外,如果您想要一个可以很好地获取时区和偏移量的库,getTimezoneOffset() 被称为 flakey,您应该查看这个库:http://www.pageloom.com/automatic-timezone-detection-with-javascript

【讨论】:

嗯,没有直接的服务器/javascript 通信,但我知道你在做什么。我确实可以让服务器输出自 UTC 纪元以来的 ms 以及归一化到 EST 的时间,我可以完全忽略这些 EST 时间,并与服务器在页面上隐藏在它们旁边的内容进行比较。这通常是你的意思吗?我不想误解,因为我已经很难用文字表达我遇到的问题了:) 好的,我明白你在说什么。在这种情况下,服务器将 EST 页面上的文本显示给可能在任何地方的客户端。虽然我需要在页面上以 EST 显示时间,但我绝对可以使用服务器获取那些时间的 UTC-since-epoch,并将它们放入可以与 JavaScript 进行比较的数据属性中。这应该可行,并且符合您始终使用 getTime() 并完全忽略时区之间的转换的建议。 有趣的是,当我不得不筛选一个流行的体育网站时,我也遇到了同样的问题;p 我完全按照你的说法做了。【参考方案2】:

啊,我想我终于明白你在说什么了。您想说“NYC 的当前时间是 _”,基于用户计算机上的时间,虽然有对 setTimezone("EDT") 的支持(至少在文档中),但没有似乎不支持setTimezone("America/New York")。您必须硬编码在 EDT 和 EST 之间切换的日期(基于当前时间 GMT,您可以从用户的计算机获取),或者使用第 3 方 API(或在服务器端执行此操作) .

【讨论】:

绝对是解释这个问题的绝佳而简洁的方式。在确定什么是问题的最佳答案之前,我将再给这个问题多一点时间,但是现有的两个答案当然都值得一票,所以现在就在这里......

以上是关于JavaScript、时区和夏令时的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Dynamics CRM 中获取时区的夏令时开始和结束?

时区转换和夏令时

时区和夏令时 CodeIgniter

org.joda.time |夏令时 (DST) 和本地时区偏移

带有时区和夏令时的纪元的日期和时间(以秒为单位)

通用时区:你应该知道的数据库时区知识