How to sort json data first by data and then by time?

I have json data like below. I am trying to sort it using the below code

function comp(a, b) {

    return new Date(a.event_date) - new Date(b.event_date);
}

data=data.sort(comp)    

      

But the problem is that two events can be on the same dates, but at different times, which is another json data item called event_time as seen in the same json data.

How do I sort so that, firstly, sort by event_date, and if they are equal then sort by their respective times?

Thank you in advance?

{
    id: "xxxx",
    feed_id: "yyyy",
    title: "abcd ",
    detail: "efgh.",
    event_date: "Tue, 26 May 2015 00:00:00 +1000",
    event_time: "6:30pm",
    date: "Thu, 23 Apr 2015 23:05:04 +1000",
    expires_at: 1432634400,
    end_time: "8:00pm",
    timestamp: 1429794304
},
{
    id: "xxxx",
    feed_id: "yyyy",
    title: "efgh",
    detail: "efgh.",
    event_date: "Tue, 26 May 2015 00:00:00 +1000",
    event_time: "4:30pm",
    date: "Thu, 23 Apr 2015 23:05:04 +1000",
    expires_at: 1432634400,
    end_time: "8:00pm",
    timestamp: 1429794304
},    {
    id: "xxxx",
    feed_id: "yyyy",
    title: "ijkl",
    detail: "efgh.",
    event_date: "Tue, 27 May 2015 00:00:00 +1000",
    event_time: "1:30pm",
    date: "Thu, 23 Apr 2015 23:05:04 +1000",
    expires_at: 1432634400,
    end_time: "8:00pm",
    timestamp: 1429794304
}

      

+3


source to share


6 answers


If you subtract the results of two dates in 0

(no difference), include the time in the equation. Something like:



var result = document.querySelector('#result');
result.textContent = 
   JSON.stringify(getData().sort(sortDateTime), null, ' ') +
   '\n\n**using sortDateTime2\n'+
   JSON.stringify(getData().sort(sortDateTime2), null, ' ');



function sortDateTime(a, b) {
  var A = new Date(a.event_date);
  var B = new Date(b.event_date);
  if (A - B == 0) {
    // no difference, include event_time
    var tA = a.event_time.split(':');
    var tB = b.event_time.split(':');
    A.setHours( /pm/i.test(tA[1]) ? +tA[0]+12 : tA[0] );
    A.setMinutes(+tA[1].replace(/[a-z]/gi, ''));
    B.setHours(/pm/i.test(tB[1]) ? +tB[0]+12 : tB[0]);
    B.setMinutes(+tB[1].replace(/[a-z]/gi, ''));
  }
  return A - B;
}

// sorting on date/time using setTime helper
function sortDateTime2(a, b) {
  return setTime(new Date(a.event_date), a.event_time) - 
         setTime(new Date(b.event_date), b.event_time);
}

// bonus: helper to set time from a time string
function setTime(thisDate, timeStr) {
  return new Date(
           [ [ thisDate.getFullYear(), 
               thisDate.getMonth()+1, 
               thisDate.getDate() 
             ].join('/'),
             timeStr.replace(/(a|p)/, function (m) {return ' ' + m;} ) ]
             .join(' ')
  );
}

function getData() {
  return [{
     id: "xxxx",
     feed_id: "yyyy",
     title: "abcd ",
     detail: "efgh.",
     event_date: "Tue, 26 May 2015 00:00:00 +1000",
     event_time: "6:30pm",
     date: "Thu, 23 Apr 2015 23:05:04 +1000",
     expires_at: 1432634400,
     end_time: "8:00pm",
     timestamp: 1429794304
    },
    {
     id: "xxxx",
     feed_id: "yyyy",
     title: "abcd ",
     detail: "efgh.",
     event_date: "Tue, 26 May 2015 00:00:00 +1000",
     event_time: "4:30pm",
     date: "Thu, 23 Apr 2015 23:05:04 +1000",
     expires_at: 1432634400,
     end_time: "8:00pm",
     timestamp: 1429794304
    },    {
     id: "xxxx",
     feed_id: "yyyy",
     title: "abcd ",
     detail: "efgh.",
     event_date: "Tue, 27 May 2015 00:00:00 +1000",
     event_time: "1:30pm",
     date: "Thu, 23 Apr 2015 23:05:04 +1000",
     expires_at: 1432634400,
     end_time: "8:00pm",
     timestamp: 1429794304
    }
  ];
}
      

<pre id="result"></pre>
      

Run codeHide result


+3


source


Here's a simple solution:

function comp(a, b) {
  var d1= new Date(a.event_date)*1,
      d2= new Date(b.event_date)*1,
      t1= new Date('1/1/1970 '+(a.event_time.replace(/(a|p)/i, ' $1')))*1,
      t2= new Date('1/1/1970 '+(b.event_time.replace(/(a|p)/i, ' $1')))*1;

  return (d1+t1)-(d2+t2);
} //comp

      

This code:



  • Inserts a space before pm or am to make the time valid.
  • Added every time up to date 1/1/1970 and converts it to Date.
  • Makes all dates numeric (number of milliseconds since 1/1/1970).
  • Subtracts the sum of b.event_date and b.event_time (as date) from the sum of a.event_date and a.event_time (as date).

It works regardless of the case of "pm" or "am" or the number of spaces (0 or more) before "pm" or "am". If "pm" or "am" is missing, it assumes 24 hour military time.

Fiddle

+4


source


I don't think that Date.parse

works for your time format. You can use something like this:

function parseDateTime(d, t) {
  var date = new Date(d);
  var a = t.slice(-2);
  var t = +t.replace(/[apm:]/g, '');
  var h = ~~(t/100);
  var m = t%100;

  if(a == "pm" && h < 12) h += 12;
  if(a == "am" && h == 12) h -= 12;
  date.setHours(h);
  date.setMinutes(m);
  return date;
}

function comp(a, b) {
  var da = parseDateTime(a.event_date, a.event_time);
  var db = parseDateTime(b.event_date, b.event_time);

  return da - db;
}
      

Run codeHide result


function parseTime(t) {
  var a = t.slice(-2);
  var t = +t.replace(/[apm:]/g, '');

  if(a == "pm" && ~~(t/100) < 12) t += 1200;
  if(a == "am" && ~~(t/100) == 12) t -= 1200;
  return t;
}

console.log(Date.parse('8:00pm'));
// NaN

console.log(parseTime('8:00am'));
console.log(parseTime('11:59am'));
console.log(parseTime('12:00pm'));
console.log(parseTime('12:01pm'));
// 800
// 1159
// 1200
// 1201

console.log(parseTime('8:00pm'));
console.log(parseTime('11:59pm'));
console.log(parseTime('12:00am'));
console.log(parseTime('12:01am'));
// 2000
// 2359
// 0
// 1
      

Run codeHide result


+2


source


You can use this:

function comp(a, b) {
    // Compare dates
    if (new Date(a.event_date).getTime() != new Date(b.event_date).getTime())
        return new Date(a.event_date) - new Date(b.event_date);

    // If dates are equal, compare hours
    return Date.parse(a.event_time) - Date.parse(b.event_time);
}

data=data.sort(comp)  

      

EDIT I added a custom date parser (inspired by this ) and a string sorter.

function parseDate(dateString) {
    var d = new Date();
    var time = dateString.match(/(\d+)(?::(\d\d))?\s*(p?)/);
    d.setHours( parseInt(time[1]) + (time[3] ? 12 : 0) );
    d.setMinutes( parseInt(time[2]) || 0 );
    return d;
}

function comp(a, b) {
    // Compare dates
    if (new Date(a.event_date).getTime() != new Date(b.event_date).getTime())
        return new Date(a.event_date) - new Date(b.event_date);

    // If dates are equal, compare hours
    var hourA = parseDate(a.event_time);
    var hourB = parseDate(b.event_time);
    if (hourA.getTime() != hourB.getTime())
        return hourA - hourB;

    // If hours are equal, compare titles
    if(a.title > b.title)
        return -1;
    else
        return 1;
}

      

+1


source


You can use moment.js to create date objects forevent_time

var sortedJ = _j.sort(function(a,b){

    var result = new Date(a.event_date) - new Date(b.event_date);

    if(result === 0)
    {
        return new moment("01/01/2000 "+a.event_time,"MM/DD/YYYY h:mm:ss a") - moment("01/01/2000 "+b.event_time,"MM/DD/YYYY h:mm:ss a");
    }

    return result;
});

      

Here is a working JS FIDDLE

+1


source


You can try this

function comp(a, b) {
    var diff = new Date(a.event_date) - new Date(b.event_date);
    if(diff < 0) return -1;
    else if(diff > 0) return 1;
    else if(parseTime(a.event_time) < parseTime(b.event_time)) return -1;
    else if(parseTime(a.event_time) > parseTime(b.event_time)) return 1;
    else return 0;
}

      

But why not make event_date and event_time one single property?

change:

You can also define a sortBy function to help you sort any arbitrary number of properties.

function sortBy(list, f) {
  list.sort(function(a, b) {
    var fa = f(a), fb = f(b);
    if(fa < fb) return -1;
    else if(fa > fb) return 1;
    else return 0;
  });
}

      

Then you can sort by date, time and title like this

sortBy(list, function(o) {
  return [new Date(o.event_date), parseTime(o.event_time), o.title];
});

      

0


source







All Articles