如何将JavaScriptdate初始化为特定的时区

我有一个特定的时区作为一个string的date时间,我想将其转换为当地时间。 但是,我不知道如何在Date对象中设置时区。

例如,我有Feb 28 2013 7:00 PM ET,那么我可以

 var mydate = new Date(); mydate.setFullYear(2013); mydate.setMonth(02); mydate.setDate(28); mydate.setHours(7); mydate.setMinutes(00); 

据我所知,我可以设置UTC时间或本地时间。 但是,如何在另一个时区设置时间?

我试图使用添加/减去UTC的偏移量,但我不知道如何抵消夏令时。 我不确定我是否正在朝着正确的方向前进。

我怎样才能把时间从不同的时区转换到JavaScript的本地时间?

背景

JavaScript的Date对象在UTC内部跟踪时间,但通常在运行计算机的本地时间内接受input和输出。 它没有任何时间在其他时区工作的设施。 您可以parsing并输出UTC或本地date,但不能直接与其他时区一起使用。

为了绝对精确, Date对象的内部表示是一个单一的数字,表示自1970-01-01 00:00:00 UTC以来经过的毫秒数,不考虑闰秒。 Date对象本身没有存储时区或string格式。 当使用Date对象的各种function时,计算机的本地时区将应用于内部表示。 如果该函数产生一个string,那么可以考虑计算机的地区信息来确定如何产生该string。 每个function的细节都不相同,有些是针对特定实现的。

图书馆

幸运的是,有些库可以实现这一点。 他们在JavaScript中实现标准的Olson / IANA时区数据库。 如果你在networking浏览器上运行,这会有一些开销,因为如果你想要整个事情,数据库可能会有点大。 幸运的是,许多这样的库允许你有select地select你想要支持的区域,使得数据的大小更加可口。

有六个这样的库,我知道:

  • 那一刻,时区
  • JS-乔达
  • BigEasy /时区
  • WallTime-js (已停产)
  • TimeZoneJS
  • tz.js

矩时区是moment.js的延伸,相当稳定,function强大。 (作为一个合作者,我偏向于这个图书馆,但是我相信它是大多数现代化发展的最合适的select。)

js-joda是Joda-Time API(来自Java)的JavaScript实现,并且通过一个单独的模块包括时区支持。

BigEasy / TimeZone也似乎走上了正轨。

WallTime-js 已经达到了生命周期 ,业主正在迁移到瞬间时区。

TimeZoneJS时间最长,但已知有一些长期存在的错误,特别是在夏令时过渡时期。 希望这些将在未来的某个时候被固定下来。

tz.js也有一段时间了,但没有很好的logging,恕我直言。

你应该评估这些库,看看哪些会满足你的需求。 如果不确定,请与时刻/时刻一起。

现代浏览器的原生支持

如果您可以将您的使用限制在现代的Web浏览器上,那么现在可以执行以下操作,而无需任何特殊的库:

 new Date().toLocaleString("en-US", {timeZone: "America/New_York"}) 

这不是一个全面的解决scheme,但它适用于只需要输出转换(从UTC或本地时间到特定时区,而不是其他方向)的许多scheme。 这是ECMAScript国际化API(ECMA-402)的一部分。 看到这个职位了解更多详情。 这个兼容性表跟踪支持哪些版本。

您可以在new Date()指定时区偏移量,例如:

 new Date('Feb 28 2013 19:00:00 EST') 

要么

 new Date('Feb 28 2013 19:00:00 GMT-0500') 

由于Date存储UTC时间(即getTime返回UTC),JavaScript会将它们转换为UTC时间,当你调用像toString javascript的东西时,将UTC时间转换为浏览器的本地时区,并在本地时区返回string,即如果我使用UTC+8

 > new Date('Feb 28 2013 19:00:00 GMT-0500').toString() < "Fri Mar 01 2013 08:00:00 GMT+0800 (CST)" 

你也可以使用普通的getHours/Minute/Second方法:

 > new Date('Feb 28 2013 19:00:00 GMT-0500').getHours() < 8 

(这意味着时间转换成当地时间 – UTC+8 ,小时数为8

我知道这3年已经太晚了,但也许它可以帮助别人,因为我发现除了时区图书馆之外,还发现了类似于他在这里要求的东西。

我为德国时区做了类似的事情,这有点复杂,因为夏令时和闰年有366天。

它可能需要一些与“isDaylightSavingTimeInGermany”function的工作,而不同的时区在不同的时间夏令时的变化。

无论如何,看看这个网页: https : //github.com/zerkotin/german-timezone-converter/wiki

主要的方法是:convertLocalDateToGermanTimezone convertGermanDateToLocalTimezone

为了logging下来,所以不会太混乱。

尝试: 从时区的date ,它会解决预期的date与本地可用Intl.DateTimeFormat帮助。

我已经在我的项目中使用了这种方法已经有好几年了,但现在我决定将它作为小型的OS项目发布:)

我遇到了unit testing的类似问题(特别是当unit testing在本地运行创build快照,然后CI服务器(可能)运行在不同的时区导致快照比较失败时运行)。 我嘲笑我们的Date和一些支持方法如下:

 describe('...', () => { let originalDate; beforeEach(() => { originalDate = Date; Date = jest.fn( (d) => { let newD; if (d) { newD = (new originalDate(d)); } else { newD = (new originalDate('2017-05-29T10:00:00z')); } newD.toLocaleString = () => { return (new originalDate(newD.valueOf())).toLocaleString("en-US", {timeZone: "America/New_York"}); }; newD.toLocaleDateString = () => { return (new originalDate(newD.valueOf())).toLocaleDateString("en-US", {timeZone: "America/New_York"}); }; newD.toLocaleTimeString = () => { return (new originalDate(newD.valueOf())).toLocaleTimeString("en-US", {timeZone: "America/New_York"}); }; return newD; } ); Date.now = () => { return (Date()); }; }); afterEach(() => { Date = originalDate; }); });