How to sort an object array by date property?

JavascriptDatetime

Javascript Problem Overview


Say I have an array of a few objects:

var array = [{id: 1, date: Mar 12 2012 10:00:00 AM}, {id: 2, date: Mar 8 2012 08:00:00 AM}];

How can I sort this array by the date element in order from the date closest to the current date and time down? Keep in mind that the array may have many objects, but for the sake of simplicity I used 2.

Would I use the sort function and a custom comparator?

Javascript Solutions


Solution 1 - Javascript

Simplest Answer

array.sort(function(a,b){
  // Turn your strings into dates, and then subtract them
  // to get a value that is either negative, positive, or zero.
  return new Date(b.date) - new Date(a.date);
});

More Generic Answer

array.sort(function(o1,o2){
  if (sort_o1_before_o2)    return -1;
  else if(sort_o1_after_o2) return  1;
  else                      return  0;
});

Or more tersely:

array.sort(function(o1,o2){
  return sort_o1_before_o2 ? -1 : sort_o1_after_o2 ? 1 : 0;
});

Generic, Powerful Answer

Define a custom non-enumerable sortBy function using a Schwartzian transform on all arrays :

(function(){
  if (typeof Object.defineProperty === 'function'){
    try{Object.defineProperty(Array.prototype,'sortBy',{value:sb}); }catch(e){}
  }
  if (!Array.prototype.sortBy) Array.prototype.sortBy = sb;

  function sb(f){
    for (var i=this.length;i;){
      var o = this[--i];
      this[i] = [].concat(f.call(o,o,i),o);
    }
    this.sort(function(a,b){
      for (var i=0,len=a.length;i<len;++i){
        if (a[i]!=b[i]) return a[i]<b[i]?-1:1;
      }
      return 0;
    });
    for (var i=this.length;i;){
      this[--i]=this[i][this[i].length-1];
    }
    return this;
  }
})();

Use it like so:

array.sortBy(function(o){ return o.date });

If your date is not directly comparable, make a comparable date out of it, e.g.

array.sortBy(function(o){ return new Date( o.date ) });

You can also use this to sort by multiple criteria if you return an array of values:

// Sort by date, then score (reversed), then name
array.sortBy(function(o){ return [ o.date, -o.score, o.name ] };

See http://phrogz.net/JS/Array.prototype.sortBy.js for more details.

Solution 2 - Javascript

@Phrogz answers are both great, but here is a great, more concise answer:

array.sort(function(a,b){return a.getTime() - b.getTime()});

Using the arrow function way

array.sort((a,b)=>a.getTime()-b.getTime());

found here: https://stackoverflow.com/questions/16690035/sort-date-in-javascript

Solution 3 - Javascript

After correcting the JSON this should work for you now:

var array = [{id: 1, date:'Mar 12 2012 10:00:00 AM'}, {id: 2, date:'Mar 8 2012 08:00:00 AM'}];


array.sort(function(a, b) {
    var c = new Date(a.date);
    var d = new Date(b.date);
    return c-d;
});

Solution 4 - Javascript

Your data needs some corrections:

var array = [{id: 1, date: "Mar 12 2012 10:00:00 AM"},{id: 2, date: "Mar 28 2012 08:00:00 AM"}];

After correcting the data, you can use this piece of code:

function sortFunction(a,b){  
    var dateA = new Date(a.date).getTime();
    var dateB = new Date(b.date).getTime();
    return dateA > dateB ? 1 : -1;  
}; 

var array = [{id: 1, date: "Mar 12 2012 10:00:00 AM"},{id: 2, date: "Mar 28 2012 08:00:00 AM"}];
array.sort(sortFunction);​

Solution 5 - Javascript

I recommend GitHub: Array sortBy - a best implementation of sortBy method which uses the Schwartzian transform

But for now we are going to try this approach Gist: sortBy-old.js.
Let's create a method to sort arrays being able to arrange objects by some property.

Creating the sorting function

var sortBy = (function () {
  var toString = Object.prototype.toString,
      // default parser function
      parse = function (x) { return x; },
      // gets the item to be sorted
      getItem = function (x) {
        var isObject = x != null && typeof x === "object";
        var isProp = isObject && this.prop in x;
        return this.parser(isProp ? x[this.prop] : x);
      };
      
  /**
   * Sorts an array of elements.
   *
   * @param {Array} array: the collection to sort
   * @param {Object} cfg: the configuration options
   * @property {String}   cfg.prop: property name (if it is an Array of objects)
   * @property {Boolean}  cfg.desc: determines whether the sort is descending
   * @property {Function} cfg.parser: function to parse the items to expected type
   * @return {Array}
   */
  return function sortby (array, cfg) {
    if (!(array instanceof Array && array.length)) return [];
    if (toString.call(cfg) !== "[object Object]") cfg = {};
    if (typeof cfg.parser !== "function") cfg.parser = parse;
    cfg.desc = !!cfg.desc ? -1 : 1;
    return array.sort(function (a, b) {
      a = getItem.call(cfg, a);
      b = getItem.call(cfg, b);
      return cfg.desc * (a < b ? -1 : +(a > b));
    });
  };
  
}());

Setting unsorted data

var data = [
  {date: "2011-11-14T17:25:45Z", quantity: 2, total: 200, tip: 0,   type: "cash"},
  {date: "2011-11-14T16:28:54Z", quantity: 1, total: 300, tip: 200, type: "visa"},
  {date: "2011-11-14T16:30:43Z", quantity: 2, total: 90,  tip: 0,   type: "tab"},
  {date: "2011-11-14T17:22:59Z", quantity: 2, total: 90,  tip: 0,   type: "tab"},
  {date: "2011-11-14T16:53:41Z", quantity: 2, total: 90,  tip: 0,   type: "tab"},
  {date: "2011-11-14T16:48:46Z", quantity: 2, total: 90,  tip: 0,   type: "tab"},
  {date: "2011-11-31T17:29:52Z", quantity: 1, total: 200, tip: 100, type: "visa"},
  {date: "2011-11-01T16:17:54Z", quantity: 2, total: 190, tip: 100, type: "tab"},
  {date: "2011-11-14T16:58:03Z", quantity: 2, total: 90,  tip: 0,   type: "tab"},
  {date: "2011-11-14T16:20:19Z", quantity: 2, total: 190, tip: 100, type: "tab"},
  {date: "2011-11-14T17:07:21Z", quantity: 2, total: 90,  tip: 0,   type: "tab"},
  {date: "2011-11-14T16:54:06Z", quantity: 1, total: 100, tip: 0,   type: "cash"}
];

Using it

Finally, we arrange the array, by "date" property as string

//sort the object by a property (ascending)
//sorting takes into account uppercase and lowercase
sortBy(data, { prop: "date" });

If you want to ignore letter case, set the "parser" callback:

//sort the object by a property (descending)
//sorting ignores uppercase and lowercase
sortBy(data, {
    prop: "date",
    desc: true,
    parser: function (item) {
        //ignore case sensitive
        return item.toUpperCase();
    }
});

If you want to treat the "date" field as Date type:

//sort the object by a property (ascending)
//sorting parses each item to Date type
sortBy(data, {
    prop: "date",
    parser: function (item) {
        return new Date(item);
    }
});

Here you can play with the above example:
jsbin.com/lesebi

Solution 6 - Javascript

Above answers are all good , here is my implementation of sorting date in ES6 way, I'm using Date.parse (is global Date object) this will convert string representation of Date to number of milliseconds. Instead of instantiating new Date object every time.

var array = ["2021-08-10T07:24:30.087+0000" , "2021-09-30T07:24:30.087+0000", "2021-10-13T07:24:30.087+0000"];

// sorting with latest date
array.sort((a,b) => Date.parse(b) - Date.parse(a))

Solution 7 - Javascript

This should do when your date is in this format (dd/mm/yyyy).

  sortByDate(arr) {
    arr.sort(function(a,b){
      return Number(new Date(a.readableDate)) - Number(new Date(b.readableDate));
    });

    return arr;
  }

Then call sortByDate(myArr);

Solution 8 - Javascript

arr is an array of object and each object has date_prop which is a date. You can sort it in descending/decreasing order like this

 arr = arr.sort(function (a, b) {
      var dateA = new Date(a.date_prop).getTime();
      var dateB = new Date(b.date_prop).getTime();
      return dateA < dateB ? 1 : -1; // ? -1 : 1 for ascending/increasing order
    });

Solution 9 - Javascript

You could use sortBy in underscore js.

http://underscorejs.org/#sortBy

Sample:

var log = [{date: '2016-01-16T05:23:38+00:00', other: 'sample'}, 
           {date: '2016-01-13T05:23:38+00:00',other: 'sample'}, 
           {date: '2016-01-15T11:23:38+00:00', other: 'sample'}];

console.log(_.sortBy(log, 'date'));

Solution 10 - Javascript

With ES6 arrow functions, you can further write just one line of concise code (excluding variable declaration).

Eg.:

var isDescending = true; //set to false for ascending
console.log(["8/2/2020","8/1/2020","8/13/2020", "8/2/2020"].sort((a,b) => isDescending ? new Date(b).getTime() - new Date(a).getTime() : new Date(a).getTime() - new Date(b).getTime()));

Since time does not exists with the above dates, the Date object will consider following default time for sorting:

> 00:00:00

The code will work for both ascending and descending sort. Just change the value of isDescending variable as required.

Solution 11 - Javascript

Strings with dates are comparable in JavaScript (if they are syntactically the same), e.g.:

'2020-12-01' < '2020-12-02' == true

This means you can use this expression in a custom sort function:

var arr = [{id:1, date:'2020-12-01'}, {id:1, date:'2020-12-15'}, {id:1, date:'2020-12-12'}]

function sortByDate(a, b) {
    if (a.date < b.date) {
        return 1;
    }
    if (a.date > b.date) {
        return -1;
    }
    return 0;
}

const sorted = arr.sort(sortByDate);
console.log(sorted);

Solution 12 - Javascript

I'm going to add this here, as some uses may not be able to work out how to invert this sorting method.

To sort by 'coming up', we can simply swap a & b, like so:

your_array.sort ( (a, b) => {
      return new Date(a.DateTime) - new Date(b.DateTime);
});

Notice that a is now on the left hand side, and b is on the right, :D!

Solution 13 - Javascript

i was able to achieve sorting using below lines:

array.sort(function(a, b)
{
   if (a.DueDate > b.DueDate) return 1;
   if (a.DueDate < b.DueDate) return -1;
})

Solution 14 - Javascript

I personally use following approach to sort dates.

let array = ["July 11, 1960", "February 1, 1974", "July 11, 1615", "October 18, 1851", "November 12, 1995"];

array.sort(function(date1, date2) {
   date1 = new Date(date1);
   date2 = new Date(date2);
   if (date1 > date2) return 1;
   if (date1 < date2) return -1;
})

Solution 15 - Javascript

Adding absolute will give better results

var datesArray =[
      {"some":"data1","date": "2018-06-30T13:40:31.493Z"},
      {"some":"data2","date": "2018-07-04T13:40:31.493Z"},
      {"some":"data3","date": "2018-06-27T13:40:54.394Z"}
   ]

var sortedJsObjects = datesArray.sort(function(a,b){ 
    return Math.abs(new Date(a.date) - new Date(b.date)) 
});

Solution 16 - Javascript

Thank you Ganesh Sanap. sorting items by date field from old to new. Use it

 myArray = [{transport: "Air",
             load: "Vatican Vaticano",
             created: "01/31/2020"},
            {transport: "Air",
             load: "Paris",
             created: "01/30/2020"}] 

        myAarray.sort(function(a, b) {
            var c = new Date(a.created);
            var d = new Date(b.created);
            return c-d;
        });

Solution 17 - Javascript

["12 Jan 2018" , "1 Dec 2018", "04 May 2018"].sort(function(a,b) {
    return new Date(a).getTime() - new Date(b).getTime()
})

Solution 18 - Javascript

For anyone who is wanting to sort by date (UK format), I used the following:

//Sort by day, then month, then year
for(i=0;i<=2; i++){
	dataCourses.sort(function(a, b){
							  
		a = a.lastAccessed.split("/");
		b = b.lastAccessed.split("/");

		return a[i]>b[i] ? -1 : a[i]<b[i] ? 1 : 0;
	});	
}

Solution 19 - Javascript

I have just taken the Schwartzian transform depicted above and made as function. It takes an array, the sorting function and a boolean as input:

function schwartzianSort(array,f,asc){
    for (var i=array.length;i;){
      var o = array[--i];
      array[i] = [].concat(f.call(o,o,i),o);
    }
    array.sort(function(a,b){
      for (var i=0,len=a.length;i<len;++i){
        if (a[i]!=b[i]) return a[i]<b[i]?asc?-1:1:1;
      }
      return 0;
    });
    for (var i=array.length;i;){
      array[--i]=array[i][array[i].length-1];
    }
    return array;
  }

function schwartzianSort(array, f, asc) {
  for (var i = array.length; i;) {
    var o = array[--i];
    array[i] = [].concat(f.call(o, o, i), o);
  }
  array.sort(function(a, b) {
    for (var i = 0, len = a.length; i < len; ++i) {
      if (a[i] != b[i]) return a[i] < b[i] ? asc ? -1 : 1 : 1;
    }
    return 0;
  });
  for (var i = array.length; i;) {
    array[--i] = array[i][array[i].length - 1];
  }
  return array;
}

arr = []
arr.push({
  date: new Date(1494434112806)
})
arr.push({
  date: new Date(1494434118181)
})
arr.push({
  date: new Date(1494434127341)
})

console.log(JSON.stringify(arr));

arr = schwartzianSort(arr, function(o) {
  return o.date
}, false)
console.log("DESC", JSON.stringify(arr));

arr = schwartzianSort(arr, function(o) {
  return o.date
}, true)
console.log("ASC", JSON.stringify(arr));

Solution 20 - Javascript

If like me you have an array with dates formatted like YYYY[-MM[-DD]] where you'd like to order more specific dates before less specific ones, I came up with this handy function:

function sortByDateSpecificity(a, b) {
  const aLength = a.date.length
  const bLength = b.date.length
  const aDate = a.date + (aLength < 10 ? '-12-31'.slice(-10 + aLength) : '')
  const bDate = b.date + (bLength < 10 ? '-12-31'.slice(-10 + bLength) : '')
  return new Date(aDate) - new Date(bDate)
}

Solution 21 - Javascript

Thanks for those brilliant answers on top. I have thought a slightly complicated answer. Just for those who want to compare different answers.

const data = [
    '2-2018', '1-2018',
    '3-2018', '4-2018',
    '1-2019', '2-2019',
    '3-2019', '4-2019',
    '1-2020', '3-2020',
    '4-2020', '1-2021'
]

let eachYearUniqueMonth = data.reduce((acc, elem) => {
    const uniqueDate = Number(elem.match(/(\d+)\-(\d+)/)[1])
    const uniqueYear = Number(elem.match(/(\d+)\-(\d+)/)[2])


    if (acc[uniqueYear] === undefined) {
        acc[uniqueYear] = []        
    } else{    
       if (acc[uniqueYear]  && !acc[uniqueYear].includes(uniqueDate)) {
          acc[uniqueYear].push(uniqueDate)
      }
    }

    return acc;
}, {})


let group = Object.keys(eachYearUniqueMonth).reduce((acc,uniqueYear)=>{
	eachYearUniqueMonth[uniqueYear].forEach(uniqueMonth=>{
  	acc.push(`${uniqueYear}-${uniqueMonth}`)
  })
  
  return acc;
},[])

console.log(group);   //["2018-1", "2018-3", "2018-4", "2019-2", "2019-3", "2019-4", "2020-3", "2020-4"]


Solution 22 - Javascript

I have an array of objects in which key 'time' contains the date in ISO format

Example - 2021-12-24T11:02:20.370705

arr.sort(function(a,b){return a.time > b.time ? 1 : a.time < b.time ? -1 : 0 });

Above worked for me like a charm!

Solution 23 - Javascript

Here is the shortest way to solve your problem.

  var array = [{id: 1, date: 'Mar 12 2012 10:00:00 AM'}, {id: 2, date: 'Mar 8 2012 08:00:00 AM'}];

  var sortedArray = array.sort((a,b) => Date.parse(new Date(a.date)) - Date.parse(new Date(b.date)));

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionryandlfView Question on Stackoverflow
Solution 1 - JavascriptPhrogzView Answer on Stackoverflow
Solution 2 - JavascriptGalView Answer on Stackoverflow
Solution 3 - Javascriptqw3nView Answer on Stackoverflow
Solution 4 - JavascriptgabitzishView Answer on Stackoverflow
Solution 5 - JavascriptjheraxView Answer on Stackoverflow
Solution 6 - JavascriptSaranView Answer on Stackoverflow
Solution 7 - JavascriptEdison D'souzaView Answer on Stackoverflow
Solution 8 - JavascriptRohan Kumar ThakurView Answer on Stackoverflow
Solution 9 - JavascriptRobertView Answer on Stackoverflow
Solution 10 - Javascriptvarad11View Answer on Stackoverflow
Solution 11 - Javascriptsunwarr10rView Answer on Stackoverflow
Solution 12 - JavascriptJames111View Answer on Stackoverflow
Solution 13 - JavascriptAmay KulkarniView Answer on Stackoverflow
Solution 14 - JavascriptAravinda MeewalaarachchiView Answer on Stackoverflow
Solution 15 - JavascriptRajiv ShrivastavaView Answer on Stackoverflow
Solution 16 - JavascriptYanovView Answer on Stackoverflow
Solution 17 - JavascriptShravan ShettyView Answer on Stackoverflow
Solution 18 - JavascriptAndiView Answer on Stackoverflow
Solution 19 - JavascriptloretoparisiView Answer on Stackoverflow
Solution 20 - JavascriptdaviestarView Answer on Stackoverflow
Solution 21 - Javascripttcf01View Answer on Stackoverflow
Solution 22 - JavascriptUtkarshView Answer on Stackoverflow
Solution 23 - JavascriptDaggie Blanqx - Douglas MwangiView Answer on Stackoverflow