JavaScript:哪些浏览器支持使用 Date.parse 解析 ISO-8601 日期字符串
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5802461/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
JavaScript: Which browsers support parsing of ISO-8601 Date String with Date.parse
提问by cat
I failed to parse an ISO-8601 date "2011-04-26T13:16:50Z" on IE8 and Safari 5, but it worked on Chrome 10, FF4. Support seems to be quite mixed?
我未能在 IE8 和 Safari 5 上解析 ISO-8601 日期“2011-04-26T13:16:50Z”,但它适用于 Chrome 10、FF4。支持似乎很复杂?
Does anyone know the actual status of which browsers can parse this format? I assume IE6, and 7 will fail too.
有谁知道哪些浏览器可以解析这种格式的实际状态?我假设 IE6 和 7 也会失败。
var d = Date.parse("2011-04-26T13:16:50Z");
采纳答案by asgeo1
回答by ckozl
I say shim it only if needed via a few tests,
我说只有通过一些测试需要时才填充它,
here is one I already written:
这是我已经写过的一个:
(function() {
var d = window.Date,
regexIso8601 = /^(\d{4}|\+\d{6})(?:-(\d{2})(?:-(\d{2})(?:T(\d{2}):(\d{2}):(\d{2})\.(\d{1,3})(?:Z|([\-+])(\d{2}):(\d{2}))?)?)?)?$/;
if (d.parse('2011-11-29T15:52:30.5') !== 1322581950500 ||
d.parse('2011-11-29T15:52:30.52') !== 1322581950520 ||
d.parse('2011-11-29T15:52:18.867') !== 1322581938867 ||
d.parse('2011-11-29T15:52:18.867Z') !== 1322581938867 ||
d.parse('2011-11-29T15:52:18.867-03:30') !== 1322594538867 ||
d.parse('2011-11-29') !== 1322524800000 ||
d.parse('2011-11') !== 1320105600000 ||
d.parse('2011') !== 1293840000000) {
d.__parse = d.parse;
d.parse = function(v) {
var m = regexIso8601.exec(v);
if (m) {
return Date.UTC(
m[1],
(m[2] || 1) - 1,
m[3] || 1,
m[4] - (m[8] ? m[8] + m[9] : 0) || 0,
m[5] - (m[8] ? m[8] + m[10] : 0) || 0,
m[6] || 0,
((m[7] || 0) + '00').substr(0, 3)
);
}
return d.__parse.apply(this, arguments);
};
}
d.__fromString = d.fromString;
d.fromString = function(v) {
if (!d.__fromString || regexIso8601.test(v)) {
return new d(d.parse(v));
}
return d.__fromString.apply(this, arguments);
};
})();
and in your code just always use Date.fromString(...)
instead of new Date(...)
并在您的代码中始终使用Date.fromString(...)
而不是new Date(...)
test a browser to see if the shim will be used:
测试浏览器以查看是否会使用垫片:
http://jsbin.com/efivib/1/edit
http://jsbin.com/efivib/1/edit
works in all major browsers, used these references:
适用于所有主要浏览器,使用这些参考:
http://dev.w3.org/html5/spec/common-microsyntaxes.html
http://dev.w3.org/html5/spec/common-microsyntaxes.html
http://www.ecma-international.org/ecma-262/5.1/#sec-15.9.1.15
http://www.ecma-international.org/ecma-262/5.1/#sec-15.9.1.15
http://msdn.microsoft.com/en-us/library/windows/apps/ff743760(v=vs.94).aspx
http://msdn.microsoft.com/en-us/library/windows/apps/ff743760(v=vs.94).aspx
http://msdn.microsoft.com/en-us/library/windows/apps/wz6stk2z(v=vs.94).aspx
http://msdn.microsoft.com/en-us/library/windows/apps/wz6stk2z(v=vs.94).aspx
http://msdn.microsoft.com/en-us/library/windows/apps/k4w173wk(v=vs.94).aspx
http://msdn.microsoft.com/en-us/library/windows/apps/k4w173wk(v=vs.94).aspx
!- microsoft connect requires a log in to view:
!- microsoft connect 需要登录才能查看:
IE9 was failing on milliseconds with digit counts other than 3: (fixed in IE10) https://connect.microsoft.com/IE/feedback/details/723740/date-parse-and-new-date-fail-on-valid-formats
IE9 以毫秒为单位失败,数字计数不是 3:(在 IE10 中已修复) https://connect.microsoft.com/IE/feedback/details/723740/date-parse-and-new-date-fail-on-valid -格式
IE10 is still (as of 1/17/2013) failing when the time zone is omitted (according to ECMA, this should defalt to Z or UTC, not local): https://connect.microsoft.com/IE/feedback/details/776783/date-parse-and-new-date-fail-on-valid-formats
当省略时区时,IE10 仍然(截至 2013 年 1 月 17 日)失败(根据 ECMA,这应该默认为 Z 或 UTC,而不是本地):https://connect.microsoft.com/IE/feedback/ 详细信息/776783/date-parse-and-new-date-fail-on-valid-formats
-- Read this if you care about where the standard is now / going in the future and why I can't get the IE team to recognize that their IE10 implementation is technically incorrect:
-- 如果您关心标准现在/将来的发展方向以及为什么我无法让 IE 团队认识到他们的 IE10 实现在技术上是不正确的,请阅读此内容:
ECMAScript-262 v6.0 is going to move to the slightly more iso8601 compliant version of "if time zone indicator is omitted, assume local time"... so now there is a discrepancy, this implementation, chrome, mobile safari and opera all follow ECMAScript-262 v5.1, whereas IE10, firefox, desktop safari all seem to be following the more iso8601 compliant ECMAScript-262 v6.0 specification... this is confusing to say the least. When chrome or mobile safari pull the trigger and move to the ES6 implementation, I think this implementation should go with it leaving ES5.1 in the minority. I've read that this is listed in the "errata" of version 5.1 though I haven't found it. I'm more of the opinion that it's a little early to be pulling the trigger on ES6 just yet, but I'm also of the opinion that code needs to be practical, not ideal and move to where the browser makers move to. That said, it seems to be a 50/50 decision right now, so below is the "future" version of this code...
ECMAScript-262 v6.0 将转向更符合 ISO8601 的版本“如果省略时区指示器,则假定为本地时间”......所以现在有一个差异,这个实现,chrome,mobile safari 和 opera遵循 ECMAScript-262 v5.1,而 IE10、firefox、桌面 safari 似乎都遵循更符合 iso8601 的 ECMAScript-262 v6.0 规范......至少可以说这令人困惑。当 chrome 或 mobile safari 扣动扳机并转向 ES6 实现时,我认为这个实现应该随之而来,将 ES5.1 留在少数。我已经读到这列在 5.1 版的“勘误表”中,但我还没有找到。我更倾向于认为现在在 ES6 上扣动扳机还为时过早,但我' 我也认为代码需要实用,而不是理想的,并移动到浏览器制造商移动的地方。也就是说,现在似乎是 50/50 的决定,所以下面是这段代码的“未来”版本......
I should also mention that either version of the code will normalize "non-compliant" browsers to match the behavior of the other one, since that's what shims do ;)
我还应该提到,代码的任一版本都会使“不兼容”浏览器规范化以匹配另一个版本的行为,因为这就是 shims 的作用;)
HERE IS AN ADAPTED VERSION COMPATIBLE WITH ECMAScript-262 v6.0 (JavaScript Future)
这是与 ECMAScript-262 v6.0 兼容的改编版本(JavaScript Future)
see relevant sections here: (this is the only online html version of the spec I could find) http://people.mozilla.org/~jorendorff/es6-draft.html#sec-15.9.1.15
请在此处查看相关部分:(这是我能找到的唯一在线 html 版规范)http://people.mozilla.org/~jorendorff/es6-draft.html#sec-15.9.1.15
(function() {
var d = window.Date,
regexIso8601 = /^(\d{4}|\+\d{6})(?:-(\d{2})(?:-(\d{2})(?:T(\d{2}):(\d{2}):(\d{2})\.(\d{1,})(Z|([\-+])(\d{2}):(\d{2}))?)?)?)?$/,
lOff, lHrs, lMin;
if (d.parse('2011-11-29T15:52:30.5') !== 1322599950500 ||
d.parse('2011-11-29T15:52:30.52') !== 1322599950520 ||
d.parse('2011-11-29T15:52:18.867') !== 1322599938867 ||
d.parse('2011-11-29T15:52:18.867Z') !== 1322581938867 ||
d.parse('2011-11-29T15:52:18.867-03:30') !== 1322594538867 ||
d.parse('2011-11-29') !== 1322524800000 ||
d.parse('2011-11') !== 1320105600000 ||
d.parse('2011') !== 1293840000000) {
d.__parse = d.parse;
lOff = -(new Date().getTimezoneOffset());
lHrs = Math.floor(lOff / 60);
lMin = lOff % 60;
d.parse = function(v) {
var m = regexIso8601.exec(v);
if (m) {
return Date.UTC(
m[1],
(m[2] || 1) - 1,
m[3] || 1,
m[4] - (m[8] ? m[9] ? m[9] + m[10] : 0 : lHrs) || 0,
m[5] - (m[8] ? m[9] ? m[9] + m[11] : 0 : lMin) || 0,
m[6] || 0,
((m[7] || 0) + '00').substr(0, 3)
);
}
return d.__parse.apply(this, arguments);
};
}
d.__fromString = d.fromString;
d.fromString = function(v) {
if (!d.__fromString || regexIso8601.test(v)) {
return new d(d.parse(v));
}
return d.__fromString.apply(this, arguments);
};
})();
hope this helps -ck
希望这有帮助 -ck
回答by Oleksandr Tsurika
Simple function to parse ISO8601 date format in any browser:
在任何浏览器中解析 ISO8601 日期格式的简单函数:
function dateFromISO8601(isoDateString) {
var parts = isoDateString.match(/\d+/g);
var isoTime = Date.UTC(parts[0], parts[1] - 1, parts[2], parts[3], parts[4], parts[5]);
var isoDate = new Date(isoTime);
return isoDate;
}
回答by Vik David
Yes, Date.parse is not consistent for different browsers. You could:
是的,不同浏览器的 Date.parse 不一致。你可以:
- Use Date.UTCinstead, which breaks up the date-string into separate inputs
- Use a wrapper library like jQuery's parseDate
- 改用Date.UTC,它将日期字符串分解为单独的输入
- 使用像jQuery 的 parseDate这样的包装库
回答by kennebec
Some older browsers return the wrongdate (and not NaN)if you parse an ISO date string.
如果您解析 ISO 日期字符串,一些较旧的浏览器会返回错误的日期(而不是 NaN)。
You can use your own method across all browsers, or use Date.parse if it is implemented correctly- check a known timestamp.
您可以在所有浏览器中使用您自己的方法,或者使用 Date.parse(如果它实现正确的话)——检查一个已知的时间戳。
Date.fromISO= (function(){
var diso= Date.parse('2011-04-26T13:16:50Z');
if(diso=== 1303823810000) return function(s){
return new Date(Date.parse(s));
}
else return function(s){
var day, tz,
rx= /^(\d{4}\-\d\d\-\d\d([tT][\d:\.]*)?)([zZ]|([+\-])(\d\d):(\d\d))?$/,
p= rx.exec(s) || [];
if(p[1]){
day= p[1].split(/\D/).map(function(itm){
return parseInt(itm, 10) || 0;
});
day[1]-= 1;
day= new Date(Date.UTC.apply(Date, day));
if(!day.getDate()) return NaN;
if(p[5]){
tz= parseInt(p[5], 10)*60;
if(p[6]) tz += parseInt(p[6], 10);
if(p[4]== "+") tz*= -1;
if(tz) day.setUTCMinutes(day.getUTCMinutes()+ tz);
}
return day;
}
return NaN;
}
})()
回答by Will Holley
The ES5 spec deviates from the ISO8601 spec, especially when it comes to the treatment of dates without a timezone indicator / offset. There is a bug ticket at https://bugs.ecmascript.org/show_bug.cgi?id=112describing the problem and it looks like it will be fixed in ES6.
ES5 规范偏离了 ISO8601 规范,尤其是在处理没有时区指示符/偏移量的日期时。https://bugs.ecmascript.org/show_bug.cgi?id=112 上有一个错误票描述了这个问题,看起来它会在 ES6 中修复。
For now, I recommend looking at https://github.com/csnover/js-iso8601for a cross-browser implementation. I use https://github.com/csnover/js-iso8601/tree/laxwhich doesn't conform to the ES5 spec but has better interoperability with other JSON serialisation libraries such as JSON.NET.
现在,我建议查看https://github.com/csnover/js-iso8601以获取跨浏览器的实现。我使用https://github.com/csnover/js-iso8601/tree/lax,它不符合 ES5 规范,但与其他 JSON 序列化库(如 JSON.NET)具有更好的互操作性。
回答by Tracker1
As mentioned previously ISO 8601 style dates were added in ECMAScript version 5, where implementation is not consistent, and not available in all browsers. There are a numberofscript stubs available, but you may wish to simply add your own Date.parse* method.
如前所述,在 ECMAScript 版本 5 中添加了 ISO 8601 样式日期,其中实现不一致,并且并非在所有浏览器中都可用。有一个数量的可用的脚本存根,但是你可能希望简单地添加自己的Date.parse *方法。
(function() {
//ISO-8601 Date Matching
var reIsoDate = /^(\d{4})-(\d{2})-(\d{2})((T)(\d{2}):(\d{2})(:(\d{2})(\.\d*)?)?)?(Z|[+-]00(\:00)?)?$/;
Date.parseISO = function(val) {
var m;
m = typeof val === 'string' && val.match(reIsoDate);
if (m) return new Date(Date.UTC(+m[1], +m[2] - 1, +m[3], +m[6] || 0, +m[7] || 0, +m[9] || 0, parseInt((+m[10]) * 1000) || 0));
return null;
}
//MS-Ajax Date Matching
var reMsAjaxDate = /^\?\/Date\((\-?\d+)\)\?\/$/;
Date.parseAjax = function(val) {
var m;
m = typeof val === 'string' && val.match(reMsAjaxDate);
if (m) return new Date(+m[1]);
return null;
}
}();
I use the above method for JSON.parse hydration of dates...
我将上述方法用于日期的 JSON.parse 水化...
JSON.parse(text, function(key, val) {
return Date.parseISO(val) || Date.parseAjax(val) || val;
});
回答by Googol
I found ckozl answer really useful and interesting, but the regexp is not perfect and it didn't work in my case.
我发现 ckozl 的答案非常有用和有趣,但正则表达式并不完美,在我的情况下它不起作用。
Apart from the fact that dates without minutes, secs or milisecs are not parsed, ISO 8501 spec says that the '-' and ':' separators are optional, so "2013-12-27" and "20131227" are both valid. In my case, this is important because I'm setting the server date and time in a JavaScript variable from PHP:
除了不解析没有分钟、秒或毫秒的日期这一事实之外,ISO 8501 规范还说“-”和“:”分隔符是可选的,因此“2013-12-27”和“20131227”都是有效的。就我而言,这很重要,因为我正在 PHP 的 JavaScript 变量中设置服务器日期和时间:
var serverDate = new Date(Date.parse("<?php date(DateTime::ISO8601); ?>"));
This code generates something like this:
此代码生成如下内容:
<script>
var serverDate = new Date(Date.parse("2013-12-27T15:27:34+0100"));
</script>
The important part is the time zone designator "+0100" where the ':' is missing. Although Firefox parses that string correctly, IE (11) fails (if the ':' is added, then IE also works). The headache about the zonetime and the ECMAScript specifications described by ckozl is unimportant in my case, because PHP always add the time zone designator.
重要的部分是时区指示符“+0100”,其中缺少“:”。尽管 Firefox 正确解析该字符串,但 IE (11) 失败(如果添加了“:”,则 IE 也可以工作)。ckozl 描述的关于 zonetime 和 ECMAScript 规范的头痛对我来说并不重要,因为 PHP 总是添加时区指示符。
The RegExp I'm using, instead of that one from ckozl is:
我正在使用的正则表达式,而不是来自 ckozl 的正则表达式是:
var regexIso8601 = /^(\d{4}|\+\d{6})(?:-?(\d{2})(?:-?(\d{2})(?:T(\d{2})(?::?(\d{2})(?::?(\d{2})(?:(?:\.|,)(\d{1,}))?)?)?(Z|([\-+])(\d{2})(?::?(\d{2}))?)?)?)?)?$/;
Keep in mind that this regexp is not perfect either. ISO 8501 allows week specification (2007-W01-1 for monday, 1 Jan 2007), or decimal fractions in hours and minutes (18.50 for 18:30:00, or 18:30.25 for 18:30:15). But they are quite unusual.
请记住,这个正则表达式也不完美。ISO 8501 允许周规范(2007-W01-1 为 2007 年 1 月 1 日,星期一),或以小时和分钟为单位的十进制小数(18:30:00 为 18.50,18:30:15 为 18:30.25)。但它们很不寻常。
P.D. This answer should be, I imagine, a comment to the original chozl answer, but I do not have reputation enough :(
PD 我想这个答案应该是对原始 chozl 答案的评论,但我的声誉不够:(
回答by Jürgen Thelen
ISO 8601date formats were added with ECMAScript-262v5. So if a browser is not v5 compatible, you simply cannot expectto be capable of handling ISO 8601 formats.
ECMAScript-262v5添加了ISO 8601日期格式。因此,如果浏览器与 v5 不兼容,您就不能指望能够处理 ISO 8601 格式。
Browsers not being v5 compatible may use any implementation specific date formats they want. Most of them do at least support RFC822/RFC1123date formats, though. Example:
不兼容 v5 的浏览器可以使用他们想要的任何实现特定的日期格式。不过,它们中的大多数至少支持RFC822/ RFC1123日期格式。例子:
var d = Date.parse("Wed, 26 Apr 2011 13:16:50 GMT+0200");
回答by leo
Microsoft Sharepoint 2013 is ALSO using a different notation eg "2013-04-30T22:00:00Z"
Microsoft Sharepoint 2013 也使用不同的符号,例如“2013-04-30T22:00:00Z”
If you want to use the REST services from sharepoint 2013 in combination with Internet Explorer 8 ( IE8 ) , then the solution from ckozl is NOT working. Youll get the NaN
如果您想将来自 sharepoint 2013 的 REST 服务与 Internet Explorer 8 (IE8) 结合使用,则来自 ckozl 的解决方案不起作用。你会得到 NaN
change the regex line TO:
将正则表达式行更改为:
regexIso8601 = /^(\d{4}|\+\d{6})(?:-(\d{2})(?:-(\d{2})(?:T(\d{2}):(\d{2}):(\d{2})(\.(\d{1,3}))?(?:Z|([\-+])(\d{2}):(\d{2}))?)?)?)?$/;
this will make the microseconds bit optional !
这将使微秒位可选!
cheerio, Leo
啦啦队,狮子座