我有一个特定时区的日期时间作为字符串,我想将其转换为本地时间。但是,我不知道如何在Date对象中设置时区。

例如,我有2013年2月28日东部时间晚上7点,然后我可以

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

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

我尝试使用添加/减去UTC的偏移量,但我不知道如何对抗夏令时。我不确定我走的方向是否正确。

如何在javascript中将时间从不同的时区转换为本地时间?


当前回答

我也有同样的问题,但是我们可以使用我们想要的时区 我们使用。tolocaledatestring ()

例如: var day=new Date(); const选项={日:“数字”,月:“长”,年:“数字”,时区:“亚洲/加尔各答”}; const今天=。toLocaleDateString(“en-IN”,选项); console.log(今天);

其他回答

背景

JavaScript的Date对象在内部以UTC时间跟踪时间,但通常接受输入并以运行它的计算机的本地时间产生输出。它很少有使用其他时区时间的设施。

Date对象的内部表示是一个数字,表示自UTC时间1970-01-01 00:00:00以来经过的毫秒数,不考虑闰秒。

Date对象本身中没有存储时区或字符串格式。

当使用Date对象的各种函数时,计算机的本地时区将应用于内部表示形式。如果函数生成一个字符串,则可能会考虑计算机的语言环境信息,以确定如何生成该字符串。每个函数的细节不同,有些是特定于实现的。

Date对象对非本地时区的唯一操作是:

It can parse a string containing a numeric UTC offset from any time zone. It uses this to adjust the value being parsed, and stores the UTC equivalent. The original local time and offset are not retained in the resulting Date object. For example: var d = new Date("2020-04-13T00:00:00.000+08:00"); d.toISOString() //=> "2020-04-12T16:00:00.000Z" d.valueOf() //=> 1586707200000 (this is what is actually stored in the object) In environments that have implemented the ECMASCript Internationalization API (aka "Intl"), a Date object can produce a locale-specific string adjusted to a given time zone identifier. This is accomplished via the timeZone option to toLocaleString and its variations. Most implementations will support IANA time zone identifiers, such as 'America/New_York'. For example: var d = new Date("2020-04-13T00:00:00.000+08:00"); d.toLocaleString('en-US', { timeZone: 'America/New_York' }) //=> "4/12/2020, 12:00:00 PM" // (midnight in China on Apring 13th is noon in New York on April 12th) Most modern environments support the full set of IANA time zone identifiers (see the compatibility table here). However, keep in mind that the only identifier required to be supported by Intl is 'UTC', thus you should check carefully if you need to support older browsers or atypical environments (for example, lightweight IoT devices).

There are several libraries that can be used to work with time zones. Though they still cannot make the Date object behave any differently, they typically implement the standard IANA timezone database and provide functions for using it in JavaScript. Modern libraries use the time zone data supplied by the Intl API, but older libraries typically have overhead, especially if you are running in a web browser, as the database can get a bit large. Some of these libraries also allow you to selectively reduce the data set, either by which time zones are supported and/or by the range of dates you can work with.

下面是需要考虑的库:

Intl-based库

新的开发应该从这些实现中选择一个,这些实现依赖于Intl API的时区数据:

Luxon (Moment.js的继承者) date-fns-tz (date-fns的扩展名) Day.js(当使用它的Timezone插件时)

Non-Intl库

这些库是可以维护的,但是需要打包它们自己的时区数据,这些数据可能相当大。

Js-joda /timezone (Js-joda的扩展名) moment-timezone* (Moment.js的扩展) Date-fns-timezone(旧版本的扩展名)。X of date-fns) BigEasy /时区 tz.js

*虽然Moment和Moment- timezone之前是推荐的,Moment团队现在更喜欢用户选择Luxon进行新的开发。

停止库

这些库已经正式停止使用,不应该再使用。

WallTime-js 时区JS

未来的建议

TC39 Temporal提案旨在提供一组新的标准对象,用于在JavaScript语言本身中处理日期和时间。这将包括对时区感知对象的支持。

常见的错误

有几种经常尝试的方法是错误的,通常应该避免。

解析

new Date(new Date().toLocaleString('en', {timeZone: 'America/New_York'}))

上面的方法正确地使用Intl API创建特定时区的字符串,但是它错误地将该字符串传递回Date构造函数。在这种情况下,解析将是特定于实现的,并且可能完全失败。如果成功,结果Date对象现在很可能表示错误的时间瞬间,因为在解析期间将应用计算机的本地时区。

时代的转变

var d = new Date();
d.setTime(d.getTime() + someOffset * 60000);

上述方法试图通过将Unix时间戳按其他时区偏移量移动来操作Date对象的时区。但是,由于Date对象只跟踪UTC时间,它实际上只是使Date对象表示不同的时间点。

有时直接在构造函数上使用相同的方法,这也是无效的。

Epoch shift有时在日期库内部用作避免编写日历算术的快捷方式。这样做时,必须避免对非utc属性的任何访问。例如,一旦移位,对getthours的调用将是可以接受的,但对getHours的调用将是无效的,因为它使用本地时区。

它被称为“epoch shift”,因为如果正确使用,Unix epoch (1970-01-01T00:00:00.000Z)现在不再与0的时间戳相关,而是根据偏移量转移到不同的时间戳。

如果您没有创建日期库,则不应该进行epoch转移。

要了解更多关于时代转移的细节,请观看格雷格·米勒在2015年CppCon上的视频剪辑。该视频是关于c++中的time_t,但解释和问题是相同的。(对于JavaScript爱好者,每次听到Greg提到time_t时,只要想到“Date object”就可以了。)

尝试创建一个“UTC日期”

var d = new Date();
var utcDate = new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate(), d.getUTCHours(), d.getUTCMinutes(), d.getUTCSeconds(), d.getUTCMilliseconds()));

在本例中,d和utcDate都是相同的。构造utcDate的工作是多余的,因为d已经用UTC表示了。检查toISOString、getTime或valueOf函数的输出将为这两个变量显示相同的值。

类似的方法如下:

var d = new Date();
var utcDate = new Date(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate(), d.getUTCHours(), d.getUTCMinutes(), d.getUTCSeconds(), d.getUTCMilliseconds());

这种方法将UTC值传递给Date构造函数,其中需要使用本地时间值。结果Date对象现在表示一个完全不同的时间点。这本质上与前面描述的历元偏移的结果相同,因此应该避免。

获取基于utc的Date对象的正确方法是new Date()。如果你需要一个UTC的字符串表示,那么使用new Date(). toisostring()。

对于Ionic用户来说,我遇到了麻烦,因为. toisostring()必须与html模板一起使用。

这将获取当前日期,但当然也可以添加到先前选定日期的答案中。

我用这个解决了它:

date = new date (); public currentDate: any = new Date(this.date.getTime() - this.date.getTimezoneOffset()*60000).toISOString();

*60000表示UTC -6,即CST,因此无论需要什么时区,数字和差异都可以更改。

简单,支持Node.JS

传入时区与UTC时间的偏移量

function initDateInTimezone(offsetHours) {
  const timezoneOffsetInMS = offsetHours * 60 * 60000;
  let d = new Date().getTimezoneOffset() * 60000 + timezoneOffsetInMS;
  const date = new Date(new Date().getTime() - d);
    return date
}

我发现最受支持的方法是使用getTimezoneOffset来计算适当的时间戳,或者更新时间,然后使用正常的方法来获得必要的日期和时间。

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();

EDIT

我以前在执行日期转换时使用UTC方法,这是不正确的。通过将偏移量添加到时间上,使用本地get函数将返回所需的结果。

我在运行GCP云函数时遇到了这个问题。当然,它在本地机器上工作,但是在云中运行使得new Date()的操作系统默认值(本地)无关紧要。在我的例子中,来自云的api调用需要东部标准时间,ISO格式(不带“Z”),偏移量为“-0500”或“-0400”,取决于DST,例如:

2021 - 12 - 01 - t00:00:00.000 - 0500

同样,这不是浏览器格式问题,所以我被迫采用这种格式,以便api调用能够正确工作。

使用@chickens代码作为开始,这是有效的:

var date = new Date(); 
var now_utc =  Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(),
date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds());

var dt = new Date(now_utc);

let utcDate = new Date(dt.toLocaleString('en-US', { timeZone: "UTC" }));
let tzDate = new Date(dt.toLocaleString('en-US', { timeZone: "America/New_York" }));
let offset1 = utcDate.getTime() - tzDate.getTime();
let offset2 = offset1/60000;
let o1 = Math.abs(offset2);
console.log(offset2)
var offsetValue1 =  (offset2 < 0 ? "+" : "-") + ("00" + Math.floor(o1 / 60)).slice(-2) + ("00" + (o1 % 60)).slice(-2);
console.log(offsetValue1)
dt.setTime(dt.getTime() - offset1);

console.log(dt.toISOString());
console.log(dt.toISOString().slice(0,-1)+offsetValue1);