admin管理员组文章数量:1310273
I'm working with an array of objects in Javascript and need to sort them by date and time. Here's the setup:
place
- title
- date (optional)
- time (optional)
Conceptually, the application allows users to create a list of places they're planning to go. The array of events is manually ordered at first, and users can optionally add date and time values to places. I'm providing an button to sort by date...places with null dates need to be placed at the bottom of the list.
Right now, it's behaving differently across browsers. Here's the code (assume I have a handle on the _places array and the _list object):
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);
}
If you recognize the sort code above, that's because I got the basics from another post, but I felt this one deserved it's own since it deals with dates...the other was just dealing with null values and text.
Anyway, in Chrome, the list seems to sort in a random order, and it keeps sorting differently every time I execute the _orderByDate function. In Safari, it sorts mostly correct the first time, but puts one null date place at the top of the list. In Firefox, nothing happens at all.
I'm a bit of a beginner, and I don't have a CS background at all, so I'm not adept at the basics like arrays, dates, times etc...and my debugging skills are limited to the Firebug console. No errors are being reported, so I really have no idea what's going wrong.
One thing to note, if I eliminate the date type from the function so it sorts the items as strings, it works correctly...but that means 1/10/2011 would sort before 1/9/2011, so I think I need the date type in there.
Any ideas what's going wrong? Is there a smarter way to do what I'm trying to do?
EDIT: Adding log values
First sort (Chrome):
- 08/01/2010
- null
- null
- 08/03/2010
- null
- null
- null
- null
- 7/01/2010
- null
- null
- null
Second sort (Chrome):
- 08/01/2010
- null
- null
- null
- 07/01/2010
- null
- null
- null
- null
- null
- 8/03/2010
- null
- null
I'm working with an array of objects in Javascript and need to sort them by date and time. Here's the setup:
place
- title
- date (optional)
- time (optional)
Conceptually, the application allows users to create a list of places they're planning to go. The array of events is manually ordered at first, and users can optionally add date and time values to places. I'm providing an button to sort by date...places with null dates need to be placed at the bottom of the list.
Right now, it's behaving differently across browsers. Here's the code (assume I have a handle on the _places array and the _list object):
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);
}
If you recognize the sort code above, that's because I got the basics from another post, but I felt this one deserved it's own since it deals with dates...the other was just dealing with null values and text.
Anyway, in Chrome, the list seems to sort in a random order, and it keeps sorting differently every time I execute the _orderByDate function. In Safari, it sorts mostly correct the first time, but puts one null date place at the top of the list. In Firefox, nothing happens at all.
I'm a bit of a beginner, and I don't have a CS background at all, so I'm not adept at the basics like arrays, dates, times etc...and my debugging skills are limited to the Firebug console. No errors are being reported, so I really have no idea what's going wrong.
One thing to note, if I eliminate the date type from the function so it sorts the items as strings, it works correctly...but that means 1/10/2011 would sort before 1/9/2011, so I think I need the date type in there.
Any ideas what's going wrong? Is there a smarter way to do what I'm trying to do?
EDIT: Adding log values
First sort (Chrome):
- 08/01/2010
- null
- null
- 08/03/2010
- null
- null
- null
- null
- 7/01/2010
- null
- null
- null
Second sort (Chrome):
- 08/01/2010
- null
- null
- null
- 07/01/2010
- null
- null
- null
- null
- null
- 8/03/2010
- null
- null
-
Show us what the _places object looks like (output of
_places.toSource()
). – Matthew Flaschen Commented Jul 31, 2010 at 23:03
3 Answers
Reset to default 4[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);
});
You can simplify the sorting algorithm by a great deal if you pre-process your array so that it will have a numeric representation of the column you want to sort by.
Add a column to the table that contains the UTC equivalent of the dates for instance. Then you can safely sort the array by the UTC property, but you will still display the string value.
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;
});
If you don't want to use the Date object (pre-1970 dates):
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;
});
Of course this assumes that your dates will always have the same M/D/Y format.
Here's the above algorithm in action: http://jsfiddle/krNnn/
Ok, we got busy and built a rather plex function that works across all browsers. Some of the requirements we had were pretty special (dates in the distant past, need to sort null dates at the bottom, subsort by time). Here's what we did:
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);
}
本文标签: Problem sorting an array of objects by date amp time in Javascriptnull values allowedStack Overflow
版权声明:本文标题:Problem sorting an array of objects by date & time in Javascript - null values allowed - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741841787a2400545.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论