34

我有一个 ISO 日期字符串,如下所示

 var startTimeISOString = "2013-03-10T02:00:00Z";

当我使用下面的代码将它转换为 javascript 中的日期对象时,它返回

var startTimeDate = new Date(startTimeISOString);

输出是

Date {Sun Mar 10 2013 07:30:00 GMT+0530 (India Standard Time)}

它确实将ISOString转换为日期,但它转换为本地时间,因为new Date()它取决于客户端。如何将iso日期时间字符串转换为日期和时间而不是本地日期时间..?

谢谢

4

5 回答 5

62

根据 MDN

假定时区的差异

给定日期字符串“2014 年 3 月 7 日”,parse() 假定为本地时区,但给定 ISO 格式,例如“2014-03-07”,它将假定时区为 UTC。因此,使用这些字符串生成的 Date 对象将代表不同的时间点,除非系统设置为 UTC 的本地时区。这意味着两个看起来相同的日期字符串可能会产生两个不同的值,具体取决于正在转换的字符串的格式(此行为在 ECMAScript ed 6 中进行了更改,因此两者都将被视为本地)。

我已经这样做了,现在正在获取 ISO 日期字符串中的确切时间,而不是本地时间

 var startTimeISOString = "2013-03-10T02:00:00Z";

 var startTime = new Date(startTimeISOString );
 startTime =   new Date( startTime.getTime() + ( startTime.getTimezoneOffset() * 60000 ) );

这将在 iso 日期字符串中给出相同的日期时间,这里的输出是

o/p

Date {Sun Mar 10 2013 02:00:00 GMT+0530 (India Standard Time)}
于 2013-03-22T10:52:40.833 回答
16

总结一下tracevipin帖子中的对话:

所有 Date 对象都基于自 1970-01-01T00:00:00Z 以来的毫秒时间值,因此它们的核心是 UTC。这与 UNIX 不同,UNIX 使用的值表示自同一纪元以来的秒数。

Date.prototype.toString方法返回一个依赖于实现的字符串,该字符串表示基于系统设置和客户端时区偏移量的时间(也称为本地时间)。

如果需要 UTC ISO8601 时间字符串,可以使用Date.prototype.toISOString方法。如果需要,很容易为此方法编写“垫片”。

最后,不要相信Date.parse来解析字符串。ES5 中指定了对 ISO8601 格式的 UTC 字符串的支持,但是它并没有在使用的浏览器中一致地实现。如果需要广泛的浏览器支持(例如典型的 Web 应用程序),手动解析字符串会更好(这并不难,有关于如何做的示例)。

简单的 ISO8601 UTC 时间戳解析器:

function dateObjectFromUTC(s) {
  s = s.split(/\D/);
  return new Date(Date.UTC(+s[0], --s[1], +s[2], +s[3], +s[4], +s[5], 0));
}

这是 toISOString 的垫片:

if (typeof Date.prototype.toISOString != 'function') {

  Date.prototype.toISOString = (function() {
  
    function z(n){return (n<10? '0' : '') + n;}
    function p(n){
      n = n < 10? z(n) : n;
      return n < 100? z(n) : n;
    }
    
    return function() {
      return this.getUTCFullYear() + '-' +
             z(this.getUTCMonth() + 1) + '-' +
             z(this.getUTCDate()) + 'T' +
             z(this.getUTCHours()) + ':' +
             z(this.getUTCMinutes()) + ':' +
             z(this.getUTCSeconds()) + '.' +
             p(this.getUTCMilliseconds()) + 'Z';
    } 
  }());
}
于 2013-03-20T08:45:27.883 回答
7

这是因为日期是使用toString默认返回本地时区的日期和时间的方法打印的。该方法toUTCString将为您提供所需的字符串。

Date实际上将日期保留为以毫秒为单位的 unix 时间,并提供操作它的方法。

于 2013-03-20T07:04:59.470 回答
0

在 vanilla javascript 中,没有办法创建一个假定您提供的 ISO 格式字符串的本地时间的日期。当您将 ISO 8601 格式的字符串传递给 javascript 时,会发生以下情况。我将使用非 UTC 时间,因为它比使用 ISO 格式的字符串更能说明问题:

  1. var startTime = new Date("2013-03-10T02:00:00+06:00"). 请注意,这也可以是2013-03-10T02:00:00Z或任何其他 ISO 格式的字符串。
  2. 读取时间,应用偏移量并计算自 1970-01-01T00:00:00Z 以来的毫秒数
  3. 您现在只有几毫秒 - 您已经丢失了所有时区信息。在这种情况下 1362859200000

除了为您提供该数字的 UTC 表示的函数之外,所有函数都将使用运行代码的计算机的时区将该数字解释为时间。

要做原始海报想要的,你需要做。

  1. 解析 ISO 字符串,将偏移量('Z' 或 '+06:00')解释为时区偏移量
  2. 存储时区偏移量
  3. 使用时区偏移量计算并存储自纪元以来的毫秒数
  4. 保持那个偏移量
  5. 每当尝试进行计算或打印日期时,应用时区偏移量。

这不是微不足道的,需要对 8601 规范进行完整的解释。太多的代码放在这里。

这正是moment.js的设计初衷。我强烈推荐使用它。使用 moment.js:

moment("2013-03-10T02:00:00Z").format()
"2013-03-10T02:00:00Z"

这将导致打印原始字符串的 ISO 时间,保留偏移量。

于 2015-07-10T09:05:30.587 回答
-1

它将返回 ISOdate

var getDate = () => {
    var dt = new Date();
    var off = dt.getTimezoneOffset() * 60000
    var newdt = new Date(dt - off).toISOString()
    return newdt.slice(0, 19)
}
于 2021-08-14T04:47:24.670 回答