我正在使用Javascript中的一组对象,需要按日期和时间对它们进行排序。这是设置:
地方
从概念上讲,该应用程序允许用户创建他们计划去的地方列表。事件数组首先手动排序,用户可以选择向地点添加日期和时间值。我提供了一个按日期排序的按钮...需要将具有空日期的地点放在列表的底部。
目前,它在浏览器中的表现不同。这是代码(假设我在_places数组和_list对象上有句柄):
var _orderByDate = function (e) {
YUE.preventDefault(e); // yui
_places.sort(function (a, b) {
var dateA = new Date(a.date),
dateB = new Date(b.date);
if ((!dateA === null) && (dateB === null)) return 0; //they're both null and equal
else if ((dateA === null) && (dateB != null)) return -1; //move a downwards
else if ((dateA != null) && (dateB === null)) return 1; //move b downwards
else if ((dateA == dateB)) return (a.time > b.time) ? 1 : ((b.time > a.time) ? -1 : 0);
else return (dateA > dateB) ? 1 : ((dateB > dateA) ? -1 : 0);
});
_list.updatePlaces(_places);
}
如果您认识到上面的排序代码,那是因为我从另一篇文章中得到了基础知识,但我觉得这个应该是自己的,因为它处理日期......另一个只是处理空值和文本。
无论如何,在Chrome中,列表似乎按随机顺序排序,并且每次执行_orderByDate函数时它都会保持不同的排序。在Safari中,它首次排序大部分是正确的,但是在列表的顶部放置一个空日期。在Firefox中,根本没有任何事情发生。
我是一个初学者,我根本没有CS背景,所以我不擅长数组,日期,时间等基础...我的调试技巧仅限于Firebug控制台。没有错误报告,所以我真的不知道出了什么问题。
有一点需要注意,如果我从函数中删除日期类型,以便将项目排序为字符串,它可以正常工作......但这意味着1/10/2011将在2011年9月1日之前排序,所以我我觉得我需要那里的日期类型。
任何想法出了什么问题?有没有更聪明的方法来做我想做的事情?
编辑:添加日志值
答案 0 :(得分:3)
<强> [See it in action] 强>
_places.sort(function (a, b) {
var dateA = new Date(a.date + a.time), // merge the date & time
dateB = new Date(b.date + b.time); // depending on the format
if (!a.date && b.date) return 1;
else if (a.date && !b.date) return -1;
else if (dateA === dateB) return 0;
else return (dateA > dateB) ? 1 : (dateB > dateA ? -1 : 0);
});
答案 1 :(得分:3)
如果您预先处理数组,那么您可以大大简化排序算法,使其具有您要排序的列的数字表示。
在表中添加一列,其中包含例如日期的UTC等效值。然后,您可以通过UTC属性安全地对数组进行排序,但您仍将显示字符串值。
for (var idx in _places)
_places[idx].UTC = _places[idx].date ? new Date(_places[idx].date).UTC() : 0;
_places.sort(function(a, b)
{
return a.UTC > b.UTC ? 1 : a.UTC < b.UTC ? -1 : 0;
});
如果您不想使用Date对象(1970年以前的日期):
for (var idx in _places)
{
var row = _places[idx];
if (!row.date)
{
row.sortable = 0;
continue;
}
var date = row.date.split('/');
row.sortable = 10000 * parseInt(date[2]) + 100 * parseInt(date[0]) + parseInt(date[1]); // year, month, day
}
_places.sort(function(a, b)
{
return a.sortable > b.sortable ? 1 : a.sortable < b.sortable ? -1 : 0;
});
当然,这假设您的日期始终具有相同的M / D / Y格式。
以上是上面的算法:http://jsfiddle.net/krNnn/
答案 2 :(得分:0)
好的,我们忙着构建一个相当复杂的功能,适用于所有浏览器。我们的一些要求非常特殊(在遥远的过去的日期,需要在底部对空日期进行排序,按时间分类)。这就是我们所做的:
var _orderByDate = function(e) {
YUE.preventDefault(e);
_places.sort(function(a,b) {
var Ay, Am, Ad, By, Bm, Bd;
var Ah, Am, Bh, Bm;
var dateA = a.date.split("/");
if( !dateA.length || dateA.length != 3 || isNaN(dateA[0]) ||
isNaN(dateA[1]) || isNaN(dateA[2]) ) {
dateA = -1;
} else {
Ay = parseInt(dateA[2]);
Am = parseInt(dateA[0]);
Ad = parseInt(dateA[1]);
}
var dateB = b.date.split("/");
if( !dateB.length || dateB.length != 3 || isNaN(dateB[0]) ||
isNaN(dateB[1]) || isNaN(dateB[2]) ) {
dateB = -1;
} else {
By = parseInt(dateB[2]);
Bm = parseInt(dateB[0]);
Bd = parseInt(dateB[1]);
}
// null checks
if(dateA == -1 && dateB == -1) return 0;
if(dateA == -1 && dateB != -1) return 1;
if(dateA != -1 && dateB == -1) return -1;
// year check
if(Ay > By) return 1;
if(By > Ay) return -1;
// month check
if(Am > Bm) return 1;
if(Bm > Am) return -1;
// day check
if(Ad > Bd) return 1;
if(Bd > Ad) return -1;
var timeA = a.time.split(":");
if( !timeA.length || timeA.length != 2 || isNaN(timeA[0]) ) {
timeA = -1;
} else {
if( timeA[1].match(/am/) ) {
Ah = parseInt(timeA[0]);
Am = parseInt(timeA[1].match(/\d+/));
} else if( timeA[1].match(/pm/) ) {
Ah = parseInt((timeA[0] * 1) + 12);
Am = parseInt(timeA[1].match(/\d+/));
}
}
var timeB = b.time.split(":");
if( !timeB.length || timeB.length != 2 || isNaN(timeB[0]) ) {
timeB = -1;
} else {
if( timeB[1].match(/am/) ) {
Bh = parseInt(timeB[0]);
Bm = parseInt(timeB[1].match(/\d+/));
} else if( timeB[1].match(/pm/) ) {
Bh = parseInt((timeB[0] * 1) + 12);
Bm = parseInt(timeB[1].match(/\d+/));
}
}
// null time checks
if(timeA == -1 && timeB == -1) return 0;
if(timeA == -1 && timeB != -1) return 1;
if(timeA != -1 && timeB == -1) return -1;
// hour check
if(Ah > Bh) return 1;
if(Bh > Ah) return -1;
// minute check
if(Am > Bm) return 1;
if(Bm > Am) return -1;
return 0;
} );
_list.updatePlaces(_places);
}