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?
Does anyone know the actual status of which browsers can parse this format? I assume IE6, and 7 will fail too.
var d = Date.parse("2011-04-26T13:16:50Z");
ISO 8601 represents date and time by starting with the year, followed by the month, the day, the hour, the minutes, seconds and milliseconds. For example, 2020-07-10 15:00:00.000, represents the 10th of July 2020 at 3 p.m. (in local time as there is no time zone offset specified—more on that below).
Use the getTime() method to convert an ISO date to a timestamp, e.g. new Date(isoStr). getTime() .
The Date. parse() method parses a string representation of a date, and returns the number of milliseconds since January 1, 1970, 00:00:00 UTC or NaN if the string is unrecognized or, in some cases, contains illegal date values (e.g. 2015-02-31). Only the ISO 8601 format ( YYYY-MM-DDTHH:mm:ss.
The standard is called ISO-8601 and the format is: YYYY-MM-DDTHH:mm:ss.sssZ.
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(...)
test a browser to see if the shim will be used:
http://jsbin.com/efivib/1/edit
works in all major browsers, used these references:
http://dev.w3.org/html5/spec/common-microsyntaxes.html
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/wz6stk2z(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:
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
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
-- 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:
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...
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 ;)
HERE IS AN ADAPTED VERSION COMPATIBLE WITH 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
(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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With