Date.toISOString(),但使用本地时间而不是UTC

Bas*_*asj 7 javascript timezone datetime date

假设我们有这个日期时间:

var d = new Date("Sat Jul 21 2018 14:00:00 GMT+0200");
Run Code Online (Sandbox Code Playgroud)

将其导出为字符串(console.log(d))会在浏览器之间产生不一致的结果:

  • Sat Jul 21 2018 14:00:00 GMT+0200 (Paris, Madrid (heure d’été)) 使用Chrome

  • Sat Jul 21 14:00:00 UTC+0200 2018 使用Internet Explorer等

因此我们不能将日期时间发送到格式不一致的服务器。

那么自然的想法是要求一个ISO8601日期时间,并使用d.toISOString();它,但它给出了UTC日期时间:2018-07-21T12:00:00.000Z而我想使用本地时区时间:

2018-07-21T14:00:00+0200
or
2018-07-21T14:00:00
Run Code Online (Sandbox Code Playgroud)

如何获得它(不依赖诸如momentjs之类的第三方依赖项)?

我尝试了一下,似乎可行,但是没有更自然的方法吗?

var d = new Date("Sat Jul 21 2018 14:00:00 GMT+0200");
Run Code Online (Sandbox Code Playgroud)

Man*_*ngo 13

技巧是通过时区调整时间,然后使用toISOString(). 您可以通过使用原始时间创建一个新日期并从原始时间中减去时区偏移量来完成此操作:

\n
var d = new Date("Sat Jul 21 2018 14:00:00 GMT+0200");\nvar newd = new Date(d.getTime() - d.getTimezoneOffset()*60000);\nconsole.log(newd.toISOString());    //  2018-07-21T22:00:00.000Z\n
Run Code Online (Sandbox Code Playgroud)\n

或者,您可以简单地调整原始日期变量:

\n
var d = new Date("Sat Jul 21 2018 14:00:00 GMT+0200");\nd.setTime(d.getTime() - d.getTimezoneOffset()*60000);\nconsole.log(d.toISOString());       //  2018-07-21T22:00:00.000Z\n
Run Code Online (Sandbox Code Playgroud)\n

但请注意,以这种方式调整原始日期将影响所有日期方法。

\n

为了您的方便,结果是自 1970 年 1 月 1 日以来的毫秒.getTime()数。但是,给出了与 UTC 的时区差异(以分钟为单位);这就是为什么你需要乘以才能以毫秒为单位得到这个值的原因。getTimezoneOffset()60000

\n

当然,新时间仍然是相对于UTC的,所以你\xe2\x80\x99必须忽略Z最后的:

\n
d = d.slice(0,-1);                  //  2018-07-21T22:00:00.000\n
Run Code Online (Sandbox Code Playgroud)\n


Rob*_*obG 10

ECMA-262中对带有时区的日期字符串进行格式设置的内置支持有限,既有实现依赖的toStringtoLocaleString方法,也有toISOString,始终为UTC。如果toISOString允许参数指定UTC或本地偏移量(默认值为UTC),那将是很好的。

编写自己的函数以生成具有本地偏移量的符合ISO 8601的时间戳并不难:

function toISOLocal(d) {
  var z  = n =>  ('0' + n).slice(-2);
  var zz = n => ('00' + n).slice(-3);
  var off = d.getTimezoneOffset();
  var sign = off < 0? '+' : '-';
  off = Math.abs(off);

  return d.getFullYear() + '-'
         + z(d.getMonth()+1) + '-' +
         z(d.getDate()) + 'T' +
         z(d.getHours()) + ':'  + 
         z(d.getMinutes()) + ':' +
         z(d.getSeconds()) + '.' +
         zz(d.getMilliseconds()) +
         sign + z(off/60|0) + ':' + z(off%60); 
}

console.log(toISOLocal(new Date()));
Run Code Online (Sandbox Code Playgroud)

  • 代码非常简单。唯一未知的是使用按位运算符来降低偏移量。我认为使用 `Math.floor(off/60)` 而不是 `off/60|0` 会更好。 (4认同)