Sort a string date array
Asked Answered
M

5

30

I want to sort an array in ascending order. The dates are in string format

["09/06/2015", "25/06/2015", "22/06/2015", "25/07/2015", "18/05/2015"] 

Even need a function to check whether these dates are in continuous form:

eg - Valid   - ["09/06/2015", "10/06/2015", "11/06/2015"] 
     Invalid - ["09/06/2015", "25/06/2015", "22/06/2015", "25/07/2015"] 

Example code:

function sequentialDates(dates){
        var temp_date_array = [];

        $.each(dates, function( index, date ) {
            //var date_flag = Date.parse(date);
            temp_date_array.push(date);
        });

        console.log(temp_date_array);

        var last;
        for (var i = 0, l = temp_date_array.length; i < l; i++) {

          var cur = new Date();
          cur.setTime(temp_date_array[i]);
          last = last || cur;
          //console.log(last+' '+cur);

          if (isNewSequence(cur, last)) {
            console.log("Not Sequence");
          }
        }

        //return dates;
    }

     function isNewSequence(a, b) {
          if (a - b > (24 * 60 * 60 * 1000))
              return true;
          return false;
      }
Malloy answered 7/6, 2015 at 7:16 Comment(2)
Do you have some code already?Hereabouts
Use ISO 8601 when storing a Date as a String, it'll save you headachesTref
C
51

The Simple Solution

There is no need to convert Strings to Dates or use RegExp.

The simple solution is to use the Array.sort() method. The sort function sets the date format to YYYYMMDD and then compares the string value. Assumes date input is in format DD/MM/YYYY.

data.sort(function(a,b) {
  a = a.split('/').reverse().join('');
  b = b.split('/').reverse().join('');
  return a > b ? 1 : a < b ? -1 : 0;
  // return a.localeCompare(b);         // <-- alternative 
});

Update:

A helpful comment suggested using localeCompare() to simplify the sort function. This alternative is shown in the above code snippet.

Run Snippet to Test

<!doctype html>
<html>
<body style="font-family: monospace">
<ol id="stdout"></ol>
<script>
  var data = ["09/06/2015", "25/06/2015", "22/06/2015", "25/07/2015", "18/05/2015"];

data.sort(function(a,b) {
  a = a.split('/').reverse().join('');
  b = b.split('/').reverse().join('');
  return a > b ? 1 : a < b ? -1 : 0;
  
  // return a.localeCompare(b);         // <-- alternative 
  
});

for(var i=0; i<data.length; i++) 
  stdout.innerHTML += '<li>' + data[i];
</script>
</body>
</html>
Captive answered 7/6, 2015 at 7:37 Comment(2)
@RobG - Thanks, that was a good suggestion and I've noted the alternative in the answer.Captive
@ritesh - If your data contains same dates then you may need to add additional sorting criteria. See this SO question: stackoverflow.com/questions/2784230Captive
K
9

You will need to convert your strings to dates, and compare those dates, if you want to sort them. You can make use of the parameter that the sort method accepts, in order to achieve this:

var dateStrings = ["09/06/2015", "25/06/2015", "22/06/2015", "25/07/2015", "18/05/2015"];
var sortedStrings = dateStrings.sort(function(a,b) {
    var aComps = a.split("/");
    var bComps = b.split("/");
    var aDate = new Date(aComps[2], aComps[1], aComps[0]);
    var bDate = new Date(bComps[2], bComps[1], bComps[0]);
    return aDate.getTime() - bDate.getTime();
});

In order to reduce code redundancy, and to handle different date formats, you can add an additional function that will create the comparator needed by the sort method:

function createSorter(dateParser) {
    return function(a, b) {
        var aDate = dateParser(a);
        var bDate = dateParser(b);
        return aDate.getTime() - bDate.getTime();
    };
}

dateStrings.sort(createSorter(function(dateString) {
    var comps = dateString.split("/");
    return new Date(comps[2], comps[1], comps[0]);
}));

You can then use different date formatters by passing different functions to the createSorter call.

As for your second question, you can create an (sorted) array of dates from your strings, and perform your logic on that array:

function myDateParser(dateString) {
    var comps = dateString.split("/");
    return new Date(comps[2], comps[1], comps[0]);
}

var sortedDates = dateStrings.map(myDateParser).sort();

You can walk through the sortedDates array and if you find two non-consecutive dates, then you have dates with gaps between them.

Keyhole answered 7/6, 2015 at 7:36 Comment(0)
W
0
var dateRE = /^(\d{2})[\/\- ](\d{2})[\/\- ](\d{4})/;
function dmyOrdA(a, b){
a = a.replace(dateRE,"$3$2$1");
b = b.replace(dateRE,"$3$2$1");
if (a>b) return 1;
if (a <b) return -1;
return 0; }
function dmyOrdD(a, b){
a = a.replace(dateRE,"$3$2$1");
b = b.replace(dateRE,"$3$2$1");
if (a>b) return -1;
if (a <b) return 1;
return 0; }
function mdyOrdA(a, b){
a = a.replace(dateRE,"$3$1$2");
b = b.replace(dateRE,"$3$1$2");
if (a>b) return 1;
if (a <b) return -1;
return 0; }
function mdyOrdD(a, b){
a = a.replace(dateRE,"$3$1$2");
b = b.replace(dateRE,"$3$1$2");
if (a>b) return -1;
if (a <b) return 1;
return 0; } 

dateArray = new Array("09/06/2015", "25/06/2015", "22/06/2015", "25/07/2015", "18/05/2015");
var c = dateArray.sort( dmyOrdA );

console.log(c);
Warden answered 7/6, 2015 at 7:30 Comment(1)
it will return ["18/05/2015", "09/06/2015", "22/06/2015", "25/06/2015", "25/07/2015"]Warden
M
0

Here's another solution using es6 arrow functions; does the job in 2 lines.

The problem I see with the most voted answer here is that it would fail when the leading zero is missing for days/month which are single digit.

Ex: var data = ["9/6/2015", "12/6/2015", "22/6/2015", "25/7/2015", "18/5/2015"];.

The most reliable way to do this would be to use date sort instead of a string sort. Although in a performance point of view, it might look to be an overhead to cast these strings to Date.

<!doctype html>
<html>

  <body style="font-family: monospace; font-size: 16px;">
  <ol id="demo"></ol>

  <script>
    var data = ["09/06/2015", "25/06/2015", "22/06/2015", "25/07/2015", "18/05/2015"];
    const toDate = (el) => new Date(el.split('/').reverse().join('-'));
    data.sort((a, b) => toDate(a) - toDate(b));


    // renders the results in an ordered list
    for(var i=0; i<data.length; i++) 
      demo.innerHTML += `<li> ${data[i]}`;
  </script>

</body></html>
Movement answered 9/6, 2023 at 8:12 Comment(0)
G
-1

To sort your date string ascendingly without alteration to its value, try this:

var T = ["09/06/2015", "25/06/2015", "22/06/2015", "25/07/2015", "18/05/2015"];

var sortedT = T.sort(s1,s2){
    var sdate1 = s1.split('/');
    var sdate2 = s2.split('/');
    var date1 = s1[1]+'/'+s1[0]+'/'+s1[2];
    var date2 = s2[1]+'/'+s2[0]+'/'+s2[2];
    if (Date.parse(date1) > Date.parse(date2)) return 1;
    else if (Date.parse(date1) < Date.parse(date2) return -1;
    else return 0;
}

The resultant array sortedT should be a sorted array of date string.

NOTE:

Your date format is stored in dd/mm/yyyy but the standard date format of JavaScript is mm/dd/yyyy. Thus, in order to parse this string to Date without using external date format library, the date string is therefore needed to be converted for compatibility during sort.

Garton answered 7/6, 2015 at 7:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.