javascript 中的日期解析在 safari 和 chrome 之间是不同的

IT技术 javascript parsing date google-chrome safari
2021-01-24 14:12:27

我有以下代码

var c = new Date(Date.parse("2011-06-21T14:27:28.593Z"));
console.log(c);

在 Chrome 上,它会在控制台上正确打印日期。在 Safari 中它失败了。谁是正确的,更重要的是处理这个问题的最佳方法是什么?

6个回答

你不能真正使用 Date.parse。我建议你使用: new Date (year, month [, date [, hours [, minutes [, seconds [, ms ] ] ] ] ] )

要拆分字符串,您可以尝试

var s = '2011-06-21T14:27:28.593Z';
var a = s.split(/[^0-9]/);
//for (i=0;i<a.length;i++) { alert(a[i]); }
var d=new Date (a[0],a[1]-1,a[2],a[3],a[4],a[5] );
alert(s+ " "+d);
2021-03-17 14:12:27
这仅适用于在当地时间给出日期的情况。它剥离时区并应用本地。示例:您在 -0500 时区,您在 UTC 时间上午 11 点发送它,您应该在当地时间上午 6 点返回,但在当地时间上午 11 点返回。
2021-03-17 14:12:27
Date.parse 刚刚用旧的 safari 发现了我,谢谢你的回答。
2021-03-18 14:12:27
正如disso所说,这个答案忽略了时区。它接受一个偏移量为 00:00 ("Z") 的字符串并将其解析为本地字符串。应该使用 Date.UTC。
2021-04-05 14:12:27
这些日期字符串来自服务器。如果您有办法将它们解析为单独的组件,我将非常乐意听到。
2021-04-09 14:12:27

我的类似问题是由 Safari 不知道如何以 RFC 822 时区格式读取时区造成的。我能够通过使用 ISO 8601 格式来解决这个问题。如果您可以控制日期格式,我就可以使用 java 的 SimpleDateFormat "yyyy-MM-dd'T'HH:mm:ss.sssXXX" 为我生成,即。“2018-02-06T20:00:00.000+04:00”。无论出于何种原因,Safari 都无法读取“2018-02-06T20:00:00.000+0400”,请注意时区格式中缺少冒号。

// Works
var c = new Date("2018-02-06T20:00:00.000+04:00"));
console.log(c);

// Doesn't work
var c = new Date("2018-02-06T20:00:00.000+0400"));
console.log(c);
发现相同的行为;还没有能够找到这是一个已知错误的文档。然而,这两种格式(带冒号和不带冒号)似乎都是可接受的格式The UTC offset is appended to the time in the same way that 'Z' was above, in the form ±[hh]:[mm], ±[hh][mm], or ±[hh]. 事实上,Chrome 和 Firefox 能够解析没有冒号的偏移量
2021-03-15 14:12:27
如果您需要带时区的日期,那就完美了。请注意,它也new Date("2020-04-16T20:00+04:00"))适用于各种浏览器(Chrome、Firefox、Safari、Edge)。
2021-03-16 14:12:27
这篇博文解释了这个问题和一个正则表达式解决方案,适用于 Safari 和 Internet Explorer,但仍然没有表明 Safari 或 IE 是否在某处承认它们与 ISO 规范不匹配
2021-03-18 14:12:27
啊,这里是:bugs.webkit.org/show_bug.cgi?id=160287 尚未解决,鉴于 IE 肯定不会有修复程序,如果可以的话,可能最简单的是包含冒号。
2021-03-20 14:12:27

Date.parse根据这个问题的其他答案,我倾向于避免它似乎不是可靠处理日期的可移植方式。

相反,我使用了类似下面的函数。这使用 jQuery 将字符串数组映射到数字数组,但这是一个非常容易删除/更改的依赖项。我还包括我认为合理的默认值,以允许您解析2007-01-092007-01-09T09:42:00使用相同的函数。

function dateFromString(str) {
  var a = $.map(str.split(/[^0-9]/), function(s) { return parseInt(s, 10) });
  return new Date(a[0], a[1]-1 || 0, a[2] || 1, a[3] || 0, a[4] || 0, a[5] || 0, a[6] || 0);
}

我在几个浏览器中检查过,是的,safari 返回invalid date. 顺便说一句,您不必Date.parse在这里使用也可以使用new Date([datestring])Safari 显然需要对您提供的日期字符串进行更多格式化。如果将“-”替换为“/”,删除 T 和点 (.593Z) 之后的所有内容,它将为您提供有效日期。此代码经过测试并在 Safari 中工作

var datestr = '2011-06-21T14:27:28.593Z'.split(/[-T.]/);
var safdat = new Date( datestr.slice(0,3).join('/')+' '+datestr[3] );

或使用String.replace(...)

new Date("2016-02-17T00:05:01+0000".replace(/-/g,'/').replace('T',' ').replace(/(\..*|\+.*/,""))
这会导致您丢失时区和生成的 Date 对象的几分之一秒。我想你可以在最后添加一些额外的代码来重新添加这些组件。
2021-03-24 14:12:27
只是使用.replace(/-/g,'/')作品。我的日期字符串是这样的“2019-06-26 23:59:59”
2021-03-31 14:12:27
不需要第三个正则表达式中的括号: new Date("2016-02-17T00:05:01+0000".replace(/-/g,'/').replace('T',' ').replace(/\..*|\+.*/,""))
2021-04-06 14:12:27

我使用以下函数来解析带时区的日期。Chrome 和 Safari 都可以正常工作:

function parseDate(date) {
  const parsed = Date.parse(date);
  if (!isNaN(parsed)) {
    return parsed;
  }

  return Date.parse(date.replace(/-/g, '/').replace(/[a-z]+/gi, ' '));
}

console.log(parseDate('2017-02-09T13:22:18+0300'));  // 1486635738000 time in ms

这是最安全的方法。我想您应该将最后一个替换更改为类似/[a-z]+/gi, 以匹配更广泛的受众,例如使用 UTC 而不是 T 的日期。
2021-03-18 14:12:27
@Narayon 感谢您的评论,我已经更改了答案。
2021-03-29 14:12:27