Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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:
http://jsfiddle.net/4tUZt/

Thanks in advance!

like image 661
Peter Avatar asked Aug 30 '12 08:08

Peter


People also ask

How do I sort by ISO date?

To sort a JavaScript array by ISO 8601 date, we can use the JavaScript array's sort method. We have the arr array that we want to sort by the date value. Then we call arr. sort with a callback that compares the strings to compare the date strings directly by their values lexigraphically.

Is ISO 8601 sortable?

The article is missing one of the best features of iso 8601: it's string form is naturally sortable. You don't need any specific logic for sorting, so e.g. your filesystem will automatically sort files correctly if you prefix them with a iso 8601 date.

What is the Z in ISO 8601?

Z is the zone designator for the zero UTC offset. "09:30 UTC" is therefore represented as "09:30Z" or "T0930Z". "14:45:15 UTC" would be "14:45:15Z" or "T144515Z". The Z suffix in the ISO 8601 time representation is sometimes referred to as "Zulu time" because the same letter is used to designate the Zulu time zone.


2 Answers

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

like image 86
Scott Avatar answered Sep 24 '22 01:09

Scott


You can avoid creating of dates and by using the built–in lexicographic compare function String.prototype.localeCompare, rather than the ?: compound operator or other expressions:

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'}  ];    // Oldest first  console.log(    myArray.sort((a, b) => a.date.localeCompare(b.date))  );    // Newest first  console.log(    myArray.sort((a, b) => -a.date.localeCompare(b.date))  );
like image 25
RobG Avatar answered Sep 20 '22 01:09

RobG