How to sort an array by date value in JavaScript

By

Learn how to sort a JavaScript array of objects by a date property, using sort() with a callback that subtracts the dates, and slice() to avoid mutating it.

~~~

To sort an array of objects by a date property, call sort() with a callback that subtracts the two dates. Subtracting two Date objects gives you the difference in milliseconds, which is exactly the kind of number sort() expects.

Say you have an array of objects like this, which contains a set of date objects:

const activities = [
  { title: 'Hiking', date: new Date('2019-06-28') },
  { title: 'Shopping', date: new Date('2019-06-10') },
  { title: 'Trekking', date: new Date('2019-06-22') }
]

You want to sort those activities by the date property.

You can use the sort() method of Array, which takes a callback function, which takes as parameters 2 objects contained in the array (which we call a and b):

const sortedActivities = activities.sort((a, b) => b.date - a.date)

When we return a positive value, the function communicates to sort() that the object b takes precedence in sorting over the object a. Returning a negative value will do the opposite.

Why does subtracting dates work? When you use the - operator on two Date objects, JavaScript converts them to their timestamps, the number of milliseconds since Jan 1, 1970. So we’re comparing plain numbers.

Newest first or oldest first?

b.date - a.date sorts in descending order, newest first:

activities.sort((a, b) => b.date - a.date)
//Hiking, Trekking, Shopping

Swap the operands to sort in ascending order, oldest first:

activities.sort((a, b) => a.date - b.date)
//Shopping, Trekking, Hiking

Avoid mutating the original array

Be careful with sort(): it sorts the original array in place, and returns a reference to that same array. Both sortedActivities and activities point to the same, now sorted, data.

One option to protect the original array from being modified is to use the slice() method to create a copy of the array prior to sorting, as follows:

const sortedActivities = activities.slice().sort((a, b) => b.date - a.date)

What if the dates are strings?

This is a pitfall I’ve hit with data coming from an API. If date holds a string like '2019-06-28' instead of a Date object, the subtraction returns NaN and the sorting breaks.

The fix is to convert inside the callback:

activities.sort((a, b) => new Date(b.date) - new Date(a.date))

You can generate this kind of comparator function interactively with the sort comparator builder.

~~~

Related posts about js: