JavaScript Date.prototype.toISOString()失去了偏移量

时间:2015-10-08 21:55:53

标签: javascript date datetime timezone

为什么此方法使用UTC时区(Z)而不包括本地时间偏移量(+/-HH:SS)? " ISO"在方法名称refers到ISO 8601中 - 允许"time zone designations"表示为其格式的一部分。

换句话说,new Date()告诉我日期和时间以及时区偏移(通过getTimezoneOffset())。但是toISOString()只告诉我一个时区中的日期和时间 - 它会丢弃new Date()发起的语言环境中的时间信息。

toISOString()还包括原始时区与UTC的偏移量是否有意义? toISOString()省略+/- HH:SS如果用于序列化,则会丢失有关原始 Date的信息。

我的所有AJAX调用(Angular,jQuery)都通过toISOString()序列化,因此在与服务器通信时会丢失序列化日期的本地时间。有任何方法可以让JavaScript Date输出一个ISO格式的字符串,其中还包含偏移量(除了使用像Moment.js这样的库),还是我需要编写自己的方法?

1 个答案:

答案 0 :(得分:4)

这是其中之一“因为这是语言规范所说的”答案(见ECMA-262 §20.3.4.36)。 ISO 8601是一种格式,虽然它允许使用时区数据,但ECMAScript仅使用UTC。如果您愿意,可以使用自己的 toLocalISOString 方法扩展 Date.prototype 。顺便说一句,写这样的方法并不困难。

// Format date as ISO 8601 long format with local timezone offset
if (!Date.prototype.toLocalISOString) {
  Date.prototype.toLocalISOString = function() {
  
  // Helper for padding
  function pad(n, len) {
    return ('000' + n).slice(-len);
  }

  // If not called on a Date instance, or timevalue is NaN, return undefined
  if (isNaN(this) || Object.prototype.toString.call(this) != '[object Date]') return;

  // Otherwise, return an ISO format string with the current system timezone offset
  var d = this;
  var os = d.getTimezoneOffset();
  var sign = (os > 0? '-' : '+');
  os = Math.abs(os);

  return pad(d.getFullYear(), 4) + '-' +
         pad(d.getMonth() + 1, 2) + '-' +
         pad(d.getDate(), 2) +
         'T' + 
         pad(d.getHours(), 2) + ':' +
         pad(d.getMinutes(), 2) + ':' +
         pad(d.getSeconds(), 2) + '.' +
         pad(d.getMilliseconds(), 3) + 
       
         // Note sign of ECMASCript offsets are opposite to ISO 8601
         sign +
         pad(os/60 | 0, 2) + ':' +
         pad(os%60, 2);
  }
}
document.write(new Date().toLocalISOString())

修改

基于post by DanDascalescu,这里有一个替代方案可能更有效,因为它有更少的函数调用,但它创建了两个额外的Date对象:

// Return a string in ISO 8601 extended format with the host timezone offset
Date.prototype.toLocalISOString = function() {

    // If not called on a Date instance, or timevalue is NaN, return undefined
    if (isNaN(this) || Object.prototype.toString.call(this) != '[object Date]') return;

    // Copy date so don't modify original
    var d = new Date(+this);
    var offset = d.getTimezoneOffset();
    var offSign = offset > 0? '-' : '+';
    offset = Math.abs(offset);
    var tz = offSign + ('0' + (offset/60|0)).slice(-2) + ':' + ('0' + offset%60).slice(-2)
    return new Date(d.setMinutes(d.getMinutes() - d.getTimezoneOffset())).toISOString().slice(0,-1) + tz; 
}

console.log(new Date().toLocalISOString())