Как сортировать данные json сначала по данным, а затем по времени?
У меня есть данные json, подобные приведенным ниже. Я пытаюсь отсортировать его, используя приведенный ниже код
function comp(a, b) {
return new Date(a.event_date) - new Date(b.event_date);
}
data=data.sort(comp)
Но проблема в том, что два события могут быть в одни и те же даты, но в разное время, что является еще одним элементом в данных json под названием event_time, как можно видеть на тех же данных json.
Как отсортировать так, чтобы сначала он сортировал по event_date, а если они равны, то сортировал по их соответствующим временам ?
Заранее спасибо?
{
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
}
6 ответов:
Если вычитание двух дат приводит к
0(без разницы), включите время в уравнение. Что-то вроде:
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>
Вот простое решение:
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Этот код:
- вставляет пробел перед "pm "или" am", чтобы сделать время действительным.
- добавляет каждый раз к дате 1/1/1970 и преобразует ее в дату.
- делает все даты числовыми (число миллисекунд с 1/1/1970).
- вычитает сумму b. event_date и b. event_time (в виде даты) из суммы a.event_date и A.event_time (в виде даты).
Он работает независимо от случая "pm" или " am", или количество пробелов (0 или более) перед "pm "или" am."Если "ПМ" или " ам " отсутствуют, это предполагает 24-часовое военное время.
Скрипка
Я не думаю, что
Date.parseработает для вашего формата времени. Вы можете использовать что-то вроде этого:
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; }
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
Вы можете использовать это :
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 Я добавил пользовательский парсер дат (вдохновленный этим ) и сортировщик строк.
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; }
Вы можете использовать момент .js для создания объектов даты для
event_timevar 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; });Здесь работает JS FIDDLE
Вы можете попробовать это
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; }Но почему бы не сделать event_date и event_time одним свойством?
Правка:
Вы также можете определить для себя функцию sortBy, которая поможет вам Сортировать по любому произвольному числу свойств.
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; }); }Затем вы можете сортировать по дате, времени и названию, как это
sortBy(list, function(o) { return [new Date(o.event_date), parseTime(o.event_time), o.title]; });
Comments