【问题标题】:Date.toISOString() but local time instead of UTCDate.toISOString() 但本地时间而不是 UTC
【发布时间】:2018-08-26 01:48:37
【问题描述】:

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

var d = new Date("Sat Jul 21 2018 14:00:00 GMT+0200");

将其导出为字符串 (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

如何获得这个(不依赖像momentjs这样的第三方依赖)?

我试过这个,似乎可行,但是没有更自然的方法吗?

var pad = function(i) { return (i < 10) ? '0' + i : i; };

var d = new Date("Sat Jul 21 2018 14:00:00 GMT+0200");
Y = d.getFullYear();
m = d.getMonth() + 1;
D = d.getDate();
H = d.getHours();
M = d.getMinutes();
S = d.getSeconds();
s = Y + '-' +  pad(m) + '-' + pad(D) + 'T' + pad(H) + ':' + pad(M) + ':' + pad(S);
console.log(s);

【问题讨论】:

标签: javascript date datetime timezone


【解决方案1】:

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()));

【讨论】:

  • 每个操作的更详细解释见这个答案:stackoverflow.com/a/51643788/1412157
  • @LucaM——这个答案是一种完全不同的获取时间戳的方法,它没有解释上述方法。它也不包括偏移量。
  • 嗨@RobG,我总是更喜欢详细解释每个步骤的解决方案。这就是我链接该答案的原因。如果您可以在您的 sn-p 中包含一些 cmets,我认为它确实会提高您的答案的质量。 (只是我的 2 美分)
  • 代码很简单。唯一未知的是使用按位运算符来降低偏移量。我认为使用Math.floor(off/60) 而不是off/60|0 会更好。
【解决方案2】:

我的版本:

// https://stackoverflow.com/questions/10830357/javascript-toisostring-ignores-timezone-offset/37661393#37661393
// https://stackoverflow.com/questions/49330139/date-toisostring-but-local-time-instead-of-utc/49332027#49332027
function toISOLocal(d) {
  const z = n => ('0' + n).slice(-2);
  let off = d.getTimezoneOffset();
  const sign = off < 0 ? '+' : '-';
  off = Math.abs(off);
  return new Date(d.getTime() - (d.getTimezoneOffset() * 60000)).toISOString().slice(0, -1) + sign + z(off / 60 | 0) + ':' + z(off % 60);
}
console.log(toISOLocal(new Date()));

【讨论】:

    【解决方案3】:

    我找到了一个对我有用的解决方案。

    看到这个帖子:Modifying an ISO Date in Javascript

    我自己对此进行了测试,稍作修改以删除“T”,它正在工作。这是我正在使用的代码:

    // Create date at UMT-0
      var date = new Date();
    // Modify the UMT + 2 hours
      date.setHours(date.getHours() + 2);
    // Reformat the timestamp without the "T", as YYYY-MM-DD hh:mm:ss
      var timestamp = date.toISOString().replace("T", " ").split(".")[0];
    

    另一种方法是规定您需要的格式,如下所示:

    // Create the timestamp format
      var timeStamp = Utilities.formatDate(new Date(), "GMT+2", "yyyy-MM-dd' 'HH:mm:ss");
    

    注意:这些适用于一年中时间没有夏令时变化的地方

    已经指出,上述公式是针对特定时区的。

    为了获得ISO格式的本地时间,首先指定合适的Locale(“sv-SE”是最接近且最容易修改的),然后修改(将空格改为T)与ISO格式相同.像这样:

    var date = new Date(); // Create date
    var timestamp = date.toLocaleString("sv-SE").replace(" ", "T").split(".")[0]; // Reformat the Locale timestamp ISO YYYY-MM-DDThh:mm:ss
    

    参考资料:

    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleString)

    https://www.w3schools.com/Jsref/jsref_tolocalestring.asp

    https://www.w3schools.com/Jsref/tryit.asp?filename=tryjsref_tolocalestring_date_all

    【讨论】:

    • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
    • 第一个答案仅适用于您的计算机,因为并非所有人都在 GMT+2 时区
    • OP 提到了 GMT+2,因此在此基础上提供了初始解决方案,但是我现在添加了解决方案,该解决方案将根据用户时区返回本地日期和时间,无论他们身在何处,并采用 ISO 格式。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-09
    • 2020-11-06
    • 1970-01-01
    • 2012-03-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多