Fork Me
webcloud / log / JavaScript and ISO 8601

ISO 8601 is a standard that defines how dates/times should be formatted (YYYY-MM-DDThh:mm:ss.sTZD). Unfortunately, it doesn't play nice with many browser JavaScript implementations.

To complicate things further, It comes in different tasty flavors, behold:

Twitter API ⇒ Wed Apr 07 17:04:01 +0000 2010
YouTube API ⇒ 2010-06-05T22:07:03.000Z

Normally, when creating a new date object you pass the date string into the constructor.

var birthday = new Date("2010-06-05T22:07:03.000Z");

The above works fine in Firefox (to my knowledge 3.5 and above). However, Webkit (Safari and Chrome) and Internet Explorer (all versions) will throw an Invalid Date exception. This was somewhat confusing for me since I usually do all my development in Firefox and it took a while to figure out what was going on.

After scratching my head for a while, and spending some time looking into the issue I found two very valuable resources.

Parsing ISO 8601 with JavaScript

Paul Sowden has posted some useful code over at his blog. Thanks Paul.

Date.prototype.setISO8601 = function (string) {
    var regexp = "([0-9]{4})(-([0-9]{2})(-([0-9]{2})" +
        "(T([0-9]{2}):([0-9]{2})(:([0-9]{2})(\.([0-9]+))?)?" +
        "(Z|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?";
    var d = string.match(new RegExp(regexp));

    var offset = 0;
    var date = new Date(d[1], 0, 1);

    if (d[3]) { date.setMonth(d[3] - 1); }
    if (d[5]) { date.setDate(d[5]); }
    if (d[7]) { date.setHours(d[7]); }
    if (d[8]) { date.setMinutes(d[8]); }
    if (d[10]) { date.setSeconds(d[10]); }
    if (d[12]) { date.setMilliseconds(Number("0." + d[12]) * 1000); }
    if (d[14]) {
        offset = (Number(d[16]) * 60) + Number(d[17]);
        offset *= ((d[15] == '-') ? 1 : -1);
    }

    offset -= date.getTimezoneOffset();
    time = (Number(date) + (offset * 60 * 1000));
    this.setTime(Number(time));
}

By adding a method to the Date objects prototype we can now do the following:

var today = new Date();
today.setISO8601('2010-06-05T22:07:03.000Z');

Great Success! Though, beware that this code is somewhat performance heavy, and usually when working with API's it involves parsing a s*** load of data. Therefor, If you can, I suggest you do the parsing server-side.

Making ISO 8601 dates with JavaScript

The following snippet is taken from the Mozilla Developer Center and is useful if you want to convert dates into the IS0 8601 format:

function ISODateString(d) {
    function pad(n){
        return n<10 ? '0'+n : n
    }
    return d.getUTCFullYear()+'-'
    + pad(d.getUTCMonth()+1)+'-'
    + pad(d.getUTCDate())+'T'
    + pad(d.getUTCHours())+':'
    + pad(d.getUTCMinutes())+':'
    + pad(d.getUTCSeconds())+'Z'
}
var d = new Date();
print(ISODateString(d));

And that is all. Rejoice!