【问题标题】:Getting different result in IE and Chrome when converting UTC date time into local date time using getTimezoneOffset使用 getTimezoneOffset 将 UTC 日期时间转换为本地日期时间时,在 IE 和 Chrome 中获得不同的结果
【发布时间】:2017-01-25 19:13:18
【问题描述】:

我正在使用以下逻辑将 UTC 日期时间(以这种格式来自服务器 2017-01-25T23:08:08.453)转换为使用 JavaScript 在浏览器上的本地日期时间(不要求用户输入他的时区详细信息并假设客户端上的系统日期时间/时区机器是对的)。

 var jsDate = new Date(do.createdAt);
 var jsDate = new Date(jsDate.getTime() - jsDate.getTimezoneOffset() * 60000);

登录在 IE 中似乎工作正常,但在 chrome 中我得到不同的结果。

Execute this fiddle 在 IE 和 Chrome 中查看不同的结果

如果我使用 moment.js,我会在 IE 和 chrome 中得到正确的结果:

moment.utc(do.createdAt).toDate();

但我不想引入额外的依赖。

我查看了关于 SO 的多个相关帖子,但每个帖子都有多个 cmets 指出每种方法的缺点。

假设客户端机器上的本地时区正确,最好的方法是什么。

【问题讨论】:

  • 在不知道 do.createdAt 的值的情况下说不出来。但是,如果它是一个 ISO 8601 扩展格式字符串,例如“2017-01-25T12:00:00+0000”,那么它应该被正确解析(通过与 ECMAScript ed 5 及更高版本一致的浏览器),无需进一步帮助。
  • @RobG:我从服务器2017-01-25T23:08:08.453获取这种格式的日期
  • @RobG:更新了问题并包含了小提琴

标签: javascript jquery date datetime


【解决方案1】:

假设“UTC 日期时间”是一个 ISO 8601 格式字符串,并且您需要弄乱偏移量,那么它可能在字符串中没有偏移量。此外,如果您在不同的浏览器中得到不同的结果,那么它可能不是严格的 ISO 8601,例如类似:

"2017-01-25 12:00:00"

缺少“T”分隔符和时区。您可以解析字符串并添加缺少的 T 和时区(Z 会做),然后将其留给内置解析器,您可以跳过一个步骤并将其直接解析为自己的日期,或者将其提供给解析库(有很多选择)。

要将上述 ISO 8601 类字符串解析为 UTC,以下将完成这项工作:

/* Parse a string without timezone like "2017-01-25 12:00:00" as UTC
** @param {string} s - string to parse
** @returns {Date} returns an invalid date if any
**                 part is out of range.
*/
function parseAsUTC(s) {
  var b = s.split(/\D/);
  var d = new Date(Date.UTC(b[0], --b[1], b[2], b[3], b[4], b[5], b[6]||0));
  return d &&  // generated an object
         d.getUTCMonth() == b[1] &&  // month didn't roll over
         d.getUTCHours() == b[3] &&  // hour didn't roll over
         d.getUTCSeconds() == b[5] ? // seconds didn't roll over
         d : new Date(NaN);
}

console.log(parseAsUTC('2017-01-25 12:00:00')); // Valid date
console.log(parseAsUTC('2017-01-32 12:00:00')); // Invalid date

console.log(parseAsUTC('2017-01-25T23:08:08.453')); // 2017-01-25T23:08:08.453Z

只需要检查一些日期部分,就好像它没有改变,那么它和它的下一个最低单位必须在范围内,如果任何一个超出范围,更高的单位会因为滚动而改变超过自身或下一个最高单位。

编辑

如果 ISO 8601 日期字符串缺少时区,例如“2017-01-25T23:08:08.453”,那么如果使用内置解析器进行解析,它应该被视为当地的。但是,众所周知,使用 Date 构造函数(或 Date.parse,它们与解析等效)解析字符串是不可靠的。

所以上面的建议没有改变,parseAsUTC 函数从容应对。 :-)

顺便说一句,在您的代码中:

var jsDate = new Date('2017-01-25T23:08:08.453');
var jsDate = new Date(jsDate.getTime() - jsDate.getTimezoneOffset() * 60000);

您可以使用 setMinutes 直接应用时区偏移量,以避免创建不必要的额外日期。但同样,它依赖于内置解析器,因此请坚持使用提供的函数或库:

var s = '2017-01-25T23:08:08.453';
var d = new Date(s);
d.setMinutes(d.getMinutes() - d.getTimezoneOffset());

console.log('Date string  : ' + s +
          '\nAdjusted date: ' + d.toISOString());

【讨论】:

    猜你喜欢
    • 2012-10-07
    • 1970-01-01
    • 2022-11-14
    • 2011-05-06
    • 2019-06-21
    • 1970-01-01
    • 2018-07-15
    • 1970-01-01
    • 2016-07-29
    相关资源
    最近更新 更多