解析ISO 8601日期字符串时如何假设本地时区?

时间:2013-03-20 06:47:10

标签: javascript

我有一个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 个答案:

答案 0 :(得分:50)

<强> According to MDN

  

假定时区的差异

     

给定日期字符串“2014年3月7日”,parse()假定当地时间   区域,但给定ISO格式,如“2014-03-07”,它将假设一个   UTC的时区。因此使用这些字符串生成Date对象   除非设置系统,否则将代表不同的时刻   UTC的当地时区。这意味着出现两个日期字符串   等效可能会导致两个不同的值,具体取决于格式   正在转换的字符串(此行为已更改)   ECMAScript编辑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)}

答案 1 :(得分:12)

总结来自tracevipin帖子的对话:

所有Date对象都基于time value,这是自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';
    } 
  }());
}

答案 2 :(得分:5)

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

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

答案 3 :(得分: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. 以来的毫秒数
  4. 您现在只有毫秒 - 您丢失了所有时区信息。在这种情况下1362859200000
  5. 除了提供该数字的UTC表示的函数外,所有函数都将使用运行代码的计算机的时区将该数字解释为时间。

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

    1. 解析ISO字符串,解释偏移量(&#39; Z&#39;或&#39; +06:00&#39;)作为时区偏移量
    2. 存储时区偏移量
    3. 使用偏移时区偏移量
    4. 计算并存储自纪元以来的ms
    5. 保持该偏移量
    6. 每当尝试进行计算或打印日期时,请应用时区偏移。
    7. 这不是一件小事,需要对8601规范进行完整的解释。太多的代码放在这里。

      这正是moment.js的目的。我强烈建议使用它。使用moment.js:

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

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