如何将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; }); });