UPDATE, 2011-06-21: The code formerly hosted here has been upgraded and moved to a GitHub repository.

ECMAScript revision 5 adds native support for ISO-8601 dates in the Date.parse method, but many browsers currently on the market (Safari 4, Chrome 4, IE 6-8) do not support it. Today, I wrote a simple duck punching replacement for Date.parse that will provide support for ISO-8601 strings if the native browser does not.

n.b. yes, I am aware that there are at least two other implementations of this on the Web; they are not nearly as efficient, they do not support all dates that ES5 supports, and they do not provide seamless support via the native Date.parse method.

15 Responses to this post

  1. I made two modifications to correctly parse the ISO dates returned by .NET (the 'O' format specifier):

    1) the minutesOffset was calculated incorrectly (line 15), struct[11] is a string..
    2) .NET returns 7 decimals (not three) for the second-fraction (I adjusted your regex accordingly)

    Thanks, you probably saved me some time.

  2. Hi Josef,

    Thanks for the feedback! Sorry about the trouble; I’ve updated the function so that it supports milliseconds-or-greater precision, which should allow you to parse those additional formats that have microsecond precision. I’ve also fixed the offset; embarrassing!

    Regards,

  3. The above script will pass but I noticed when I bastardise the logic and strip out the origParse to use just the regex for a JSON date parser it will fail on "May 21, 2010 14:28:00"
    a[7] is undefined.

    I just put in the below to get me by:
    if (a[7] ==undefined) {
    a[7] = '000';
    }

  4. Thank you for sharing this wonderful script.

    I did make some fields optional (by adding a '?' in the regular expression):
    1) the seconds
    2) the whole time part, starting from the 'T'

    It seems to work with just adding the question marks, but I've only tested it in IE8.

  5. in Chrome:

    Date.parse("2010-08-21T02:03:44Z")
    Sat Aug 21 2010 02:03:44 GMT-0400 (Eastern Daylight Time)

    NOTE: the time's are the same... but they shouldn't be (Z != EST)

  6. Hey Nick,

    The ISO-8601 Date.parse in Chrome is native code, so if you are having trouble with it ignoring the timezone, you’ll need to submit a bug report to them.

  7. According to the specs, 2010-08-21T02:03Z is a valid date (without the seconds specified), but your script didn't parse it. After adding an extra ? it'll also work for those dates:

    if (isNaN(timestamp)

  8. The code got swallowed. Let's try it as a link:

    http://pastebin.com/gTezmW12

  9. Thanks much, you've saved me a bunch of time and headache here.

  10. Hello colin,

    thank you for sharing your work with us! :D

    I am reading dates from a database via following php script:

    foreach($data as $row) {
    print "\n[Date.parse('$row[$timestamp]'),$row[$db_columnID]],";
    }

    The result in the final HTML file, which reaches the client is as follows:

    var data = [
    [Date.parse('2011-06-08 11:53:38'),-0.378],
    [Date.parse('2011-06-08 12:13:39'),-0.379],
    [Date.parse('2011-06-08 12:33:39'),-0.376],
    [Date.parse('2011-06-08 12:53:38'),-0.372],
    [Date.parse('2011-06-08 13:13:38'),-0.367],
    [Date.parse('2011-06-08 13:33:38'),-0.362],
    [Date.parse('2011-06-08 13:53:38'),-0.354],
    [Date.parse('2011-06-08 14:13:39'),-0.355],
    [Date.parse('2011-06-08 14:33:38'),-0.353],
    [Date.parse('2011-06-08 14:53:38'),-0.356],
    [Date.parse('2011-06-08 15:13:38'),-0.358],
    [Date.parse('2011-06-08 15:33:38'),-0.355],
    [Date.parse('2011-06-08 15:53:38'),-0.357],
    ];

    Operas (v11.11) Date.parse() can interpret the format perfectly. But IE8 and Firefox 4.0.1 cannot - they only say NaN.

    After using your script, IE is giving me timestamps - but only for the date, not for the time. And Firefox is saying, that 'data' is not definded, while it was prompting "NaN,value,NaN,value,..." for 'data' before.

    Would it be possible for you, to also cover this case?
    It would be very nice of you, if you could give me short reply, so that I can see, that my message did reach you. :)

    Thank you in advance!
    Peter

  11. @Peter,

    You need to add a timezone in order for those to be valid datetime values. If they are UTC, that is as simple as using {$row[$timestamp]}Z instead of $row[$timestamp].

    Regards,

  12. Love the script. Note that in the ES5 spec, the timezone specifier is optional. If absent, it should assume the date is in the local timezone.

    This requires an extra ? on the timezone section in the regex in order to parse the date, but unfortunately there is no local equivalent of Date.UTC (Date.Local?) to make it assume it's a local date. I had to add a check for struct[8] === "" and call +(new Date(...)) passing the same arguments as Date.UTC in order to get a local timestamp.

  13. @Daniel,

    Actually, that’s not correct. The original ES5 spec was badly written; ES5 errata states that the value of an absent time zone offset is “Z”. (Some would rightly argue that the errata is more wrong since ISO 8601 explicitly states that no time zone identifier indicates local time, but this is where we are today. :\)

    Regards,

  14. @Colin,

    Interesting, because Chrome (12.0.742.100), Firefox (5.0), and Opera (11.11) support ISO-8601 dates (though Opera doesn't let you enter more than 3 digits for the milliseconds component). If I run Date.parse("2011-06-27T10:12") in them, I get a local time, and Date.parse("2011-06-27T10:12Z") gives UTC time. The code Date.parse("2011-06-27T10:12") == Date.parse("2011-06-27T10:12Z") results in false.

    Seems that the actual browsers that support ISO-8601 dates ignore the errata, so when compared to the implementations of ES5, the errata is even MORE incorrect than simply being inconsistent with the original date spec. Looks like the browsers prefer to follow the actual ISO-8601 spec rather than ES5's version. If I want to have my date values interpreted consistently across browsers, I have to interpret no time zone as a local time.

    Also, my code was technically incorrect above - only IE gives an empty string for regex non-matches, and everything else (eg: Safari, which also doesn't support ISO-8601) gives undefined. Have to check for both.

    Cheers,

  15. Hi,

    Just wanted to thank you for publishing this script. It is very useful in my current project where I'm doing few parsing and encountered a problem with IE 8-9 and Safari. Thx!

    BR
    Sebastian