Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / Javascript

How to Sort Date and/or Time in JavaScript

5.00/5 (2 votes)
25 Jul 2013CPOL2 min read 66.2K  
How to sort Date and/or Time in JavaScript

Introduction

I have recently been working on a JavaScript project where I needed to sort Dates by descending order and Time by ascending order. For this project, I am already using Moment.js as my Date Time JavaScript Library. The aggregate I am sorting contains moment objects and not native Date JavaScript objects.

Sorting by the JavaScript Date object is easy enough, but I have not found many methods on sorting by Date and Time independently. Therefore, the goal of this post is to come up with a solution for sorting by descending Date and ascending Time.

Sort by Date

In JavaScript, sorting by Date and Time in either ascending or descending order is pretty much built in through the Date’s greater than ( > ) and less than ( < ) operators.

Example 1

JavaScript
var 
    //MomentJs Objects to Sort
    momentDates = […],
    //Sort Date By Ascending Order Algorithm            
    sortByDateAsc = function (lhs, rhs)  { return lhs > rhs ? 1 : lhs < rhs ? -1 : 0; },
    //Sort Date By Descending Order Algorithm
    sortByDateDesc = function (lhs, rhs) { return lhs < rhs ? 1 : lhs > rhs ? -1 : 0; },
    
//Sort Date By Ascending Order 
momentDates.sort(sortByDateAsc);
//Sort Date By Descending Order
momentDates.sort(sortByDateDesc);

Sort by Time

With JavaScript alone, I have not found a quick and easy solution to sort specifically by time; therefore, we need to create one.

I am going to breakdown the hours, minutes and seconds, then compare them individually. I am going to start with comparing hours first and only if the hours are identical, I will compare minutes. If minutes are identical, I will finally compare seconds. One could easily go as precise as milliseconds, but that level of accuracy is not necessary for my needs.

Example 2

JavaScript
var
sortByTimeAsc = function (lhs, rhs)  {
    var results;

    results = lhs.hours() > rhs.hours() ? 1 : lhs.hours() < rhs.hours() ? -1 : 0;

    if (results === 0)
        results = lhs.minutes() > rhs.minutes() ? 1 : lhs.minutes() < rhs.minutes() ? -1 : 0;

    if (results === 0)
        results = lhs.seconds() > rhs.seconds() ? 1 : lhs.seconds() < rhs.seconds() ? -1 : 0;

    return results;
},
sortByTimeDesc = function (lhs, rhs) {
    var results;

    results = lhs.hours() < rhs.hours() ? 1 : lhs.hours() > rhs.hours() ? -1 : 0;

    if (results === 0)
        results = lhs.minutes() < rhs.minutes() ? 1 : lhs.minutes() > rhs.minutes() ? -1 : 0;

    if (results === 0)
        results = lhs.seconds() < rhs.seconds() ? 1 : lhs.seconds() > rhs.seconds() ? -1 : 0;

    return results;
};

//Sort Only Time by Ascending Order 
momentDates.sort(sortByTimeAsc);
//Sort Only Time by Descending Order
momentDates.sort(sortByTimeDesc); 

Sort by Descending Date and Ascending Time

It would be nice to simply combine both of these algorithms into a nice easy to use function:

Example 3

JavaScript
sortByDateDescAndTimeAsc = function (lhs, rhs) {
    var results = sortByDateDesc(lhs,rhs);

    if (results === 0)
        results = sortByTimeDesc(lhs, rhs);
    
    return results;
}, 

Unfortunately, as I previously stated, the greater than ( > ) and less than ( < ) operators sort by Date and Time; Therefore, this approach would not work because sortByDateDesc would only ever return “0” if both of the Date and Time are identical, effectively bypassing or uselessly executing the Time sorting portion of the code.

I have decided we could segregate the Date portion into Years, Months and Days, similarly to how we sorted Times (e.g., If the Years, Months and Days are identical, then compare the Time portion as we previously did).

Example 4

JavaScript
sortByDateDescAndTimeAsc = function (lhs, rhs) {
    var results;

    results = lhs.years() < rhs.years() ? 1 : lhs.years() > rhs.years() ? -1 : 0;

    if (results === 0)
        results = lhs.months() < rhs.months() ? 1 : lhs.months() > rhs.months() ? -1 : 0;

    if (results === 0)
        results = lhs.date() < rhs.date() ? 1 : lhs.date() > rhs.date() ? -1 : 0;

    if (results === 0)
        results = lhs.hours() > rhs.hours() ? 1 : lhs.hours() < rhs.hours() ? -1 : 0;

    if (results === 0)
        results = lhs.minutes() > rhs.minutes() ? 1 : lhs.minutes() < rhs.minutes() ? -1 : 0;

    if (results === 0)
        results = lhs.seconds() > rhs.seconds() ? 1 : lhs.seconds() < rhs.seconds() ? -1 : 0;

    return results;
}, 

Conclusion

By breaking down this problem, we were easily able to create a solution that works. But, I know you are not using Moment.js and you don’t want to use Moment.js just to sort Dates. Well, Moment.js is simply a wrapper, with amazing features, around a native Date object. You can easily alter my provided examples and use the Date object to accomplish the exact same thing. The only difference is instead of invoking the method seconds on a moment.js object, you would invoke getSeconds on a Date object.

To quickly generate the native JavaScript code, skillfully write a macro to find and replace (i.e., Find: hs.Replace: hs.get), capitalize the method names and perform a couple other small tweaks.

Example 5

JavaScript
sortByDateDescAndTimeAscDateObj = function (lhs, rhs) {
    var results;

    results = lhs.getYear() < rhs.getYear() ? 
    1 : lhs.getYear() > rhs.getYear() ? -1 : 0;

    if (results === 0)
        results = lhs.getMonth() < rhs.getMonth() ? 
        1 : lhs.getMonth() > rhs.getMonth() ? -1 : 0;

    if (results === 0)
        results = lhs.getDate() < rhs.getDate() ? 
        1 : lhs.getDate() > rhs.getDate() ? -1 : 0;

    if (results === 0)
        results = lhs.getHours() > rhs.getHours() ? 
        1 : lhs.getHours() < rhs.getHours() ? -1 : 0;

    if (results === 0)
        results = lhs.getMinutes() > rhs.getMinutes() ? 
        1 : lhs.getMinutes() < rhs.getMinutes() ? -1 : 0;

    if (results === 0)
        results = lhs.getSeconds() > rhs.getSeconds() ? 
        1 : lhs.getSeconds() < rhs.getSeconds() ? -1 : 0;

    return results;
},

I hope this can be of value to someone. You can find another example of the code here.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)