Newtt
Newtt

Reputation: 6190

Sort javascript object based on date keys

I have a JavaScript object that looks like follows

testObj = {
    1/10/2015: {},
    2/10/2015: {},
    3/10/2015: {},
    4/10/2015: {},
    29/09/2015: {},
    30/09/2015: {}
}

Now, I'm trying to sort this such that the dates are arranged by date in increasing order. For that i've done the following

const orderedDates = {};
Object.keys(testObj).sort(function(a, b) {
    return moment(moment(b, 'DD/MM/YYYY') - moment(a, 'DD/MM/YYYY')).format('DD/MM/YYYY');
}).forEach(function(key) {
    orderedDates[key] = testObj[key];
})
rangeObj = orderedDates;

This however is not sorting the dates at all. It still returns the same exact object as testObj. How do I sort the object based on date keys?

Upvotes: 8

Views: 9552

Answers (5)

Gautam
Gautam

Reputation: 1696

You can also do it without the moment library. It will work for all js frameworks.

var testObj = {
  "3/10/2015": {},
  "2/10/2015": {},
  "1/10/2015": {},
  "4/10/2015": {},
  "29/09/2015": {},
  "30/09/2015": {}
};
var ordered = {};
Object.keys(testObj).sort(function(a, b) {
  return (dateConverter(a) - dateConverter(b));
}).forEach(function(key) {
  ordered[key] = testObj[key];
});

/* Convert DD/MM/YY to date object */
function dateConverter(date) {
  var dateParts = date.split("/");
  var dateObject = new Date(+dateParts[2], dateParts[1] - 1, +dateParts[0]); 
  return dateObject
}
/* ordered return now                                               
  "1/10/2015": {},
  "2/10/2015": {},
  "3/10/2015": {},
  "4/10/2015": {},
  "29/09/2015": {},
  "30/09/2015": {} */

Upvotes: 3

Azaz Khan
Azaz Khan

Reputation: 657

this can be achieved without using moment, console.log() could still mess up the order but iterating the keys would work like a charm, Yeah perks of ES5.

    const sortDatesObject = (unsortedDatesObject) => {
        const sortedObject = {};
        const reverseDate = date => date.split('/').reverse().join('/');
        Object.keys(unsortedDatesObject)
            .map(date => reverseDate(date))
            .sort((a, b) => { return new Date(a) - new Date(b) })
            .forEach((date) => {
                sortedObject[reverseDate(date)] = unsortedDatesObject[reverseDate(date)]
        });
        return sortedObject;
    }

    testObj = {
        "1/10/2015": {},
        "2/10/2015": {},
        "3/10/2015": {},
        "4/10/2015": {},
        "29/09/2015": {},
        "30/09/2015": {}
    }
    
    Object.keys(sortDatesObject(testObj)).forEach(key => console.log(key));

Upvotes: 0

Jonas Tomanga
Jonas Tomanga

Reputation: 1108

Without moment, easier sorting can be achieved if the date is in the format 'YYYYMMDD' with any separator.

const testObj = {
  "1/10/2015": {},
  "2/10/2015": {},
  "3/10/2015": {},
  "4/10/2015": {},
  "29/09/2015": {},
  "30/09/2015": {}
};

const orderedDates = {};
Object.keys(testObj).sort(function(a, b) {
  return a.split('/').reverse().join('').localeCompare(b.split('/').reverse().join(''));
}).forEach(function(key) {
  orderedDates[key] = testObj[key];
})

console.log(orderedDates);

Upvotes: 3

shapiro yaacov
shapiro yaacov

Reputation: 2346

Using the moment package, you can use:

const yourFormat = 'DD/MM/YYYY'
const sortDateMoments = (dates) => {
  const moments = dates.map(date => moment(date, yourFormat))
  moments.sort((a, b) => a.isBefore(b) ? 1 : -1)
  return moments
}

Upvotes: 0

CodingIntrigue
CodingIntrigue

Reputation: 78535

This line returns a string:

moment(moment(b, 'DD/MM/YYYY') - moment(a, 'DD/MM/YYYY')).format('DD/MM/YYYY')

But the sort method requires an integer value, so you need to compare the actual dates instead:

Object.keys(testObj).sort(function(a, b) {
    return moment(b, 'DD/MM/YYYY').toDate() - moment(a, 'DD/MM/YYYY').toDate();
}).forEach(function(key) {
    orderedDates[key] = testObj[key];
})

However you need to be aware that in ES5, the order of keys in an object was not guaranteed by the spec - although most browsers did iterate the keys in insertion order. In ES6 however, you can be guaranteed that if you iterate your objects keys they will be in order.

So console.log(orderedDates) may not show the keys in your expected order, but Object.keys(orderedDates).forEach(function(date) { console.log(date); }); will work as expected.

var testObj = {
    "1/10/2015": {},
    "2/10/2015": {},
    "3/10/2015": {},
    "4/10/2015": {},
    "29/09/2015": {},
    "30/09/2015": {}
};
var orderedDates = {};
Object.keys(testObj).sort(function(a, b) {
    return moment(b, 'DD/MM/YYYY').toDate() - moment(a, 'DD/MM/YYYY').toDate();
}).forEach(function(key) {
    orderedDates[key] = testObj[key];
})
Object.keys(orderedDates).forEach(function(date) {
   document.body.innerHTML += date + "<br />"
});
<script src="http://momentjs.com/downloads/moment.js"></script>

Upvotes: 14

Related Questions