How to initialize a JavaScript Date to a particular time zone
我将特定时区中的日期时间作为字符串,并希望将其转换为本地时间。但是,我不知道如何在日期对象中设置时区。
例如,我有
1 2 3 4 5 6 | var mydate = new Date(); mydate.setFullYear(2013); mydate.setMonth(02); mydate.setDate(28); mydate.setHours(7); mydate.setMinutes(00); |
据我所知,我可以设置UTC时间或本地时间。但是,如何在另一个时区设置时间?
我试着用加减法从UTC中减去偏移量,但我不知道如何抵消日光节约。我不确定我是否朝着正确的方向走。
如何在javascript中将时间从不同时区转换为本地时间?
背景
javascript的
准确地说,
幸运的是,有一些库可以用来处理时区。虽然它们仍然不能使
我知道有几个图书馆:
- 卢克森(Moment.js的继承人)
- 矩时区(moment.js的扩展)
- JS JoDA(Java JS端口)
- 日期Fns TZ/日期Fns时区(日期Fns的延长)
- BigEasy/时区
Walltime JS(已停产)- TimeZunNeJS
- TZ.JS
Luxon可能是所有现代应用中最安全的赌注,并且是最轻的重量,因为它使用
Moment TimeZone是Moment.js的扩展,并带来自己的时区数据。
JS JoDA是JordaTime API(来自Java)的JavaScript实现,并通过单独的模块包括时区支持。
日期Fns Tz是日期Fns 2.x的扩展。日期Fns时区是日期Fns 1.x的扩展。
BigEasy/TimeZone似乎也在正确的轨道上。
WalltimeJS已经到了生命的尽头,所有者正在迁移到Moment时区。
Timezonejs是最长的,但已知有一些长期存在的错误,特别是在夏时制转换附近。希望在将来的某个时候可以解决这些问题。
TZ.JS也存在一段时间了,但是没有很好的记录,imho。
您应该评估这些库,看看哪一个可以满足您的需求。如果不确定,请选择"时刻/时刻"时区。
现代浏览器中的本机支持如果您可以将您的使用限制在现代Web浏览器上,那么现在您可以在不使用任何特殊库的情况下执行以下操作:
1 | new Date().toLocaleString("en-US", {timeZone:"America/New_York"}) |
这不是一个全面的解决方案,但它适用于许多只需要输出转换的场景(从UTC或本地时间到特定时区,但不适用于其他方向)。这是ECMAScript国际化API(ECMA-402)的一部分。详情请参阅本帖。此兼容性表跟踪支持哪些版本。这是上面提到的
TC39临时提案旨在提供一组新的标准对象,用于使用JavaScript语言本身的日期和时间。这将包括对时区感知对象的支持。
您可以在
1 | new Date('Feb 28 2013 19:00:00 EST') |
或
1 | new Date('Feb 28 2013 19:00:00 GMT-0500') |
由于
1 2 | > new Date('Feb 28 2013 19:00:00 GMT-0500').toString() <"Fri Mar 01 2013 08:00:00 GMT+0800 (CST)" |
也可以使用普通的
1 2 | > new Date('Feb 28 2013 19:00:00 GMT-0500').getHours() < 8 |
(此
正如马特约翰逊所说
If you can limit your usage to modern web browsers, you can now do the
following without any special libraries:
new Date().toLocaleString("en-US", {timeZone:"America/New_York"}) This isn't a comprehensive solution, but it works for many scenarios
that require only output conversion (from UTC or local time to a
specific time zone, but not the other direction).
因此,尽管浏览器在创建日期时无法读取IANA时区,或者有任何方法可以更改现有日期对象上的时区,但似乎有一个漏洞:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | function changeTimezone(date,ianatz) { // suppose the date is 12:00 UTC var invdate = new Date(date.toLocaleString('en-US', { timeZone: ianatz })); // then invdate will be 07:00 in Toronto // and the diff is 5 hours var diff = date.getTime()-invdate.getTime(); // so 12:00 in Toronto is 17:00 UTC return new Date(date.getTime()+diff); } |
用法
1 2 | var there = new Date(when); var here = changeTimezone(there,"America/Toronto"); |
我在单元测试中遇到了类似的问题(特别是在jest中,当单元测试在本地运行以创建快照,然后CI服务器在(可能的)不同时区运行时,导致快照比较失败)。我嘲笑了我们的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | 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; }); }); |
我知道已经晚了3年了,但也许它可以帮助其他人,因为我没有发现类似的东西,除了时刻时区库,这和他在这里要求的不完全一样。
我为德国时区做了类似的事情,这有点复杂,因为夏令时和闰年有366天。
它可能需要一些"isDaylightSavingTimeingerMany"功能的工作,而不同的时区在不同的时间变化夏令时。
无论如何,请查看此页面:https://github.com/zerkotin/german-timezone-converter/wiki
主要方法有:将本地日期转换为时区将德国日期转换为本地时区
我努力把它记录下来,这样它就不会那么混乱了。
我发现在不担心第三方库的情况下,最受支持的方法是使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | var mydate = new Date(); mydate.setFullYear(2013); mydate.setMonth(02); mydate.setDate(28); mydate.setHours(7); mydate.setMinutes(00); // ET timezone offset in hours. var timezone = -5; // Timezone offset in minutes + the desired offset in minutes, converted to ms. // This offset should be the same for ALL date calculations, so you should only need to calculate it once. var offset = (mydate.getTimezoneOffset() + (timezone * 60)) * 60 * 1000; // Use the timestamp and offset as necessary to calculate min/sec etc, i.e. for countdowns. var timestamp = mydate.getTime() + offset, seconds = Math.floor(timestamp / 1000) % 60, minutes = Math.floor(timestamp / 1000 / 60) % 60, hours = Math.floor(timestamp / 1000 / 60 / 60); // Or update the timestamp to reflect the timezone offset. mydate.setTime(mydate.getTime() + offset); // Then Output dates and times using the normal methods. var date = mydate.getDate(), hour = mydate.getHours(); |
编辑
我以前在执行日期转换时使用
尝试使用NPM的CTOC。https://www.npmjs.com/package/ctoc_时区
它有简单的功能来改变时区(大多数时区在400左右)和所有你想要它显示的自定义格式。
尝试:从时区开始,在本地可用的
我在我的一个项目中使用了这种方法已经有几年了,但现在我决定把它作为一个小型操作系统项目来发布:)
面对同样的问题,用了这个
console.log(date.parse("2018年6月13日10:50:39 GMT+1"));
它将返回毫秒,你可以检查到有+100时区初始化英国时间。希望它有帮助!!