2

I am trying to sort an array which contains dates in string format (dd-mmm-yy), using the sort() function:

var array = ["1-jun-15", "1-feb-15", "1-apr-15", "1-may-15", "1-jan-15", "1-mar-15"];

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

But no success.

What's going wrong here? Here is the JSFiddle.

EDIT: While the sorting problem was solved with small correction, the primary issue is cross-browser support, which many of the answers below have differently addressed.

3
  • 5
    Those aren't valid dates Commented Nov 29, 2016 at 12:43
  • 2
    a and b are strings, what do you expect a.date and b.date to be? Commented Nov 29, 2016 at 12:50
  • Sorry it was a mistake @Teemu ! It will be a and b instead of the property accessors. Thanks! Commented Nov 29, 2016 at 12:57

6 Answers 6

6

You could split the date strings and use an object for the month values.

This proposal sorts first by year, then by month with the object and then by day.

var array = ["1-jun-15", "1-feb-15", "1-apr-15", "1-may-15", "1-jan-15", "1-mar-15"],
    MONTHS = { jan: 1, feb: 2, mar: 3, apr: 4, may: 5, jun: 6, jul: 7, aug: 8, sep: 9, oct: 10, nov: 11, dec: 12 };

array.sort(function (a, b) {
    var aa = a.split('-'),
        bb = b.split('-');

    return aa[2] - bb[2] || MONTHS[aa[1]] - MONTHS[bb[1]] || aa[0] - bb[0];
});

console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Sign up to request clarification or add additional context in comments.

Comments

2

You try to get date property from a and b in the comparator, but it's just a strings. So you need to parse it (Date.parse(a) or just new Date(a)).

Here is fixed jsfiddle.

Comments

2

Those aren't valid dates, and the strings have no date property, so every sort iteration just compares NaN instead of dates

Some browsers may be able to parse 1-jun-15, but it is not a IETF-compliant date, and there's no guarantee the javascript engine will know what to do with a date in that format.

As a matter of fact, a little testing in IE and Firefox shows they fail to parse that format all together, while Chrome has no issues with it, and that's why a standards compliant date or multiple arguments should always be passed to new Date.

You'll have to parse the dates yourself

var array = ["1-jun-15", "1-feb-15", "1-apr-15", "1-may-15", "1-jan-15", "1-mar-15"];

var months = [
	"jan", "feb","mar","apr","may","jun","jul","aug","sep","oct","nov", "dec"
];

function parse(date) {
    var parts = date.split('-');
    return new Date('20'+parts[2], months.indexOf(parts[1]), parts[0]);
}

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

console.log(array);

Comments

1

You need three steps:

  1. Convert the dates
  2. Sort the dates
  3. Convert the dates back again

Working example:

var dateArray = ["1-jun-15", "1-feb-15", "1-apr-15", "1-may-15", "1-jan-15", "1-mar-15"];

console.log(dateArray);

// STEP ONE - CONVERT THE ARRAY ITEMS

for (var i = 0; i < dateArray.length; i++) {

    var tempDateArray = dateArray[i].split('-');

// Convert the year into a 4-digit number 

    var year = '20' + tempDateArray[2];

// Convert the month into a 2-digit number

    var month = tempDateArray[1];

    switch(month) {
        case ('jan') : month = '01'; break;
        case ('feb') : month = '02'; break;
        case ('mar') : month = '03'; break;
        case ('apr') : month = '04'; break;
        case ('may') : month = '05'; break;
        case ('jun') : month = '06'; break;
        case ('jul') : month = '07'; break;
        case ('aug') : month = '08'; break;
        case ('sep') : month = '09'; break;
        case ('oct') : month = '10'; break;
        case ('nov') : month = '11'; break;
        case ('dec') : month = '12'; break;
    }

// Convert the date into a 2-digit number  

    var date = tempDateArray[0];

    if (date < 2) {
        date = '0' + date;
    }

// Recreate each array item as an 8-digit integer

dateArray[i] = year + month + date;

}

console.log(dateArray);


// STEP TWO  - SORT THE ARRAY ITEMS

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

console.log(dateArray);


// STEP THREE - CONVERT THE ARRAY ITEMS BACK AGAIN

for (var i = 0; i < dateArray.length; i++) {

    // Convert the date back again

    var date = dateArray[i].substring(6);

    if (date.substring(0,1) === '0') {
        var date = date.substring(1);
    }


    // Convert the month back again

    var month = dateArray[i].substring(4,6);

    switch(month) {
        case ('01') : month = 'jan'; break;
        case ('02') : month = 'feb'; break;
        case ('03') : month = 'mar'; break;
        case ('04') : month = 'apr'; break;
        case ('05') : month = 'may'; break;
        case ('06') : month = 'jun'; break;
        case ('07') : month = 'jul'; break;
        case ('08') : month = 'aug'; break;
        case ('09') : month = 'sep'; break;
        case ('10') : month = 'oct'; break;
        case ('11') : month = 'nov'; break;
        case ('12') : month = 'dec'; break;
    }


    // Convert the year back again

    var year = dateArray[i].substring(2,4);

    dateArray[i] = date + '-' + month + '-' + year;

}

console.log(dateArray);

Comments

0

An easy approach would be to convert the dates into Unix Timestamps, sort them, and then convert back to your original date format. Then you don't have to worry about doing string comparisons on the months.

Comments

0

You need to convert your date string into a valid date, then compare the timestamps.

var array = ["1-jun-15", "1-feb-15", "1-apr-15", "1-may-15", "1-jan-15", "1-mar-15"];
const months = ['jan', 'feb', 'mar', 'apr', 'may', 'jun']

const strToDate = str => {
  const params = str.split('-')
  params[0] = parseInt(params[0])
  params[1] = months.indexOf(params[1])
  params[2] = parseInt(params[2]) + 2000
  return new Date(...params.reverse())
  
}
array.sort(function(a, b) {
  return strToDate(a).getTime() - strToDate(b).getTime();
});

console.log(array)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.