Search code examples
javascriptarrayssortingiso8601

Sort Array by ISO 8601 date


How can I sort this array by date (ISO 8601)?

var myArray = new Array();

myArray[0] = { name:'oldest', date:'2007-01-17T08:00:00Z' }
myArray[1] = { name:'newest', date:'2011-01-28T08:00:00Z' }
myArray[2] = { name:'old',    date:'2009-11-25T08:00:00Z' }

Playground:
https://jsfiddle.net/4tUZt/


Solution

  • Sort Lexicographically:

    As @kdbanman points out, ISO8601See General principles was designed for lexicographical sort. As such the ISO8601 string representation can be sorted like any other string, and this will give the expected order.

    '2007-01-17T08:00:00Z' < '2008-01-17T08:00:00Z' === true
    

    So you would implement:

    var myArray = [
        { name:'oldest', date:'2007-01-17T08:00:00Z' },
        { name:'newest', date:'2011-01-28T08:00:00Z' },
        { name:'old',    date:'2009-11-25T08:00:00Z' }
    ];
    
    myArray.sort(function(a, b) {
        return (a.date < b.date) ? -1 : ((a.date > b.date) ? 1 : 0);
    });
    

    Sort using JavaScript Date:

    Older versions of WebKit and Internet Explorer do not support ISO 8601 dates, so you have to make a compatible date. It is supported by FireFox, and modern WebKit though See here for more information about Date.parse support JavaScript: Which browsers support parsing of ISO-8601 Date String with Date.parse

    Here is a very good article for creating a Javascript ISO 8601 compatible date, which you can then sort like regular javascript dates.

    http://webcloud.se/log/JavaScript-and-ISO-8601/

    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));
    }
    

    Usage:

    console.log(myArray.sort(sortByDate));  
    
    function sortByDate( obj1, obj2 ) {
        var date1 = (new Date()).setISO8601(obj1.date);
        var date2 = (new Date()).setISO8601(obj2.date);
        return date2 > date1 ? 1 : -1;
    }
    

    Updated usage to include sorting technique credit @nbrooks