Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaScript: Which browsers support parsing of ISO-8601 Date String with Date.parse

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"); 
like image 697
cat Avatar asked Apr 27 '11 10:04

cat


People also ask

How do I read the ISO 8601 date format?

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).

How would you get an ISO timestamp from a date object in Javascript?

Use the getTime() method to convert an ISO date to a timestamp, e.g. new Date(isoStr). getTime() .

What is date parse in Javascript?

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.

What is ISO date format in Javascript?

The standard is called ISO-8601 and the format is: YYYY-MM-DDTHH:mm:ss.sssZ.


1 Answers

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

like image 53
ckozl Avatar answered Sep 21 '22 10:09

ckozl