javascript日期时区问题

IT技术 javascript date datetime timezone
2021-02-03 17:57:27

我需要一个具有指定日期和年份值的 js Date 对象。我希望 new Date("2000-01-01")给我 2000 的 Date 对象作为 的值getFullYear(),但是如果我的计算机的时间设置设置为芝加哥时区,我得到Fri Dec 31 1999 18:00:00 GMT-0600 (CST),对于布宜诺斯艾利斯:Fri Dec 31 1999 22:00:00 GMT-0200 (ARST)

有没有办法创建 Date 对象,并.getFullYear()返回我们在构造函数中设置的日期,无论用户机器上设置了什么时区?

更新:我需要在另一个库中使用这个 Date 对象(它调用它的.getFullYear()方法,所以使用 UTC getter 并没有真正的帮助。

3个回答

Date在 JavaScript 中将字符串解析为 a时,YYYY-MM-DD格式中的值被解释为UTC值,而不是本地时间值。

关键是各部分用连字符隔开,字符串中没有时区信息。ECMAScript 5.1 规范在§15.9.1.15 中

... 不存在时区偏移的值是“Z”。

这意味着,如果您不指定偏移量,它将假定您指的是 UTC。

请注意,由于这与 ISO-8601 所说的相反,因此这种行为已在 ECMAScript 2015 (6.0) 中更改,在§20.3.1.16中说

... 如果不存在时区偏移,则日期时间将被解释为本地时间。

因此,当 ES6 的这一规定被正确实施时,这种格式的字符串值,以前被解释为 UTC 将被解释为本地时间。我已经在这里写了关于这个的博客

解决方法很简单。用斜杠替换连字符:

var s = "2000-01-01";
var dt = new Date(s.replace(/-/g, '/'));

另一种可接受的解决方法是为日期指定中午时间而不是午夜时间。这将被解析为本地时间,并且距离足够远以避免任何 DST 冲突。

var s = "2000-01-01";
var dt = new Date(s + "T12:00:00");

或者,考虑一个更明智的库,比如moment.js

var s = "2000-01-01";
var dt = moment(s, 'YYYY-MM-DD').toDate();
使用斜杠使其成为不符合 ISO 的字符串,大多数实现将其解释为本地时间。保持yyyy/mm/dd格式而不是mm/dd/yyyydd/mm/yyyy也有助于消除区域问题。
2021-03-16 17:57:27
如果我也有时间怎么办,比如:"2015-06-01T11:31:01"不使用moment.js 的任何方法?谢谢
2021-03-23 17:57:27
谢谢!拯救了我的一天!但是斜线的技巧从何而来?
2021-03-24 17:57:27
这对我来说还是有点模棱两可的。也许:“仅日期形式被视为UTC。日期+时间(无时区)被视为本地,日期+时间+时区被视为好像它们在时区中”或类似的东西。
2021-04-07 17:57:27
@eagor - 用T空格替换它,它应该可以工作。
2021-04-11 17:57:27

您可以为“Date.prototype”编写新方法,并使用它来获取包含本地时区偏移量的日期。

  //return the date with depend of Local Time Zone
  Date.prototype.getUTCLocalDate = function () {
    var target = new Date(this.valueOf());
    var offset = target.getTimezoneOffset();
    var Y = target.getUTCFullYear();
    var M = target.getUTCMonth();
    var D = target.getUTCDate();
    var h = target.getUTCHours();
    var m = target.getUTCMinutes();
    var s = target.getUTCSeconds();

    return new Date(Date.UTC(Y, M, D, h, m + offset, s));
  };

这是一个可以帮助某人的小技巧:

let date = new Date();
console.log(date); // -> Fri May 28 2021 01:04:26 GMT+0200 (Central European Summer Time)

const tzOffsetMin = Math.abs(date.getTimezoneOffset()) // the minutes of the offset timezone
const tzOffsetHour = tzOffsetMin / 60; // timezone offset in hour
console.log(tzOffsetHour); // -> 2

date.setHours(date.getHours() + tzOffsetHour); // sum to date hour the timezoneoffset
const isovalue = date.toISOString();
console.log(isovalue); // -> 2021-05-28T01:04:26.156Z

通过这种方式,无论您身在何处,您都可以“绕过”时区偏移