1

I have a datatable I'm using which has 5 columns ( http://datatables.net/ )

The columns are

  1. Date in format of: Jan 5
  2. Time in format of: 10:31 AM (xx:xx XX)
  3. Columns 3, 4, 5 aren't important, they're just data that I dont care about the sorting as long as 1 & 2 are correct.

I want to sort by Date FIRST (most recent), then I want to sort by Time (most recent at top).

So Jan 5, 4:58 PM should show before 4:58 AM, and obviously all the other numbers need to work as well for all other times. The format is always the same, ie: 12:34 AM, 4:15 PM, 12:00 AM, etc.

For the date, that already works perfectly. There's only 2 days of data max in the datatable, so even when it rolls over to the 1st of the month, that will still show at the top which is fine. I have looked at the documentation and I'm confused how to do the correct sorting for my Time column.

Here is my code:

oTable = $('#posts').dataTable({
    "bSort": true,
    "aaSorting": [ [0,'desc'], [1,'asc'] ],
    "aoColumns": [
                null,
                { "sType": 'time-sort' },
                null,
                null,
                null
           ]

});

This is from here: http://datatables.net/release-datatables/examples/basic_init/multi_col_sort.html

I take it now I have to build some sort of custom sorting algorithm for time using the sType property for "aoColumns" (you can see it in the example link above where he sorts case sensitively), and I have zero idea how to do this :( I'm not quite even sure if I did this right so far. It seems to sort the two columns fine, but now I need to make it so time is proper...

Here is the other part of the code that I believe I need. (once again, this is from the example). I'm 99% sure this is where I need to put in my custom time sorting code for both ascending and decending.

/* Define two custom functions (asc and desc) for time sorting */
jQuery.fn.dataTableExt.oSort['time-sort-asc']  = function(x,y) {
    return ???;
};

jQuery.fn.dataTableExt.oSort['time-sort-desc'] = function(x,y) {
    return ???
};
Tallboy
  • 12,847
  • 13
  • 82
  • 173
  • So "Feb 28" is above "Mar 1" but "Mar 31" is below "Apr 1" (i.e. calendar order is reversed)? – RobG Jan 06 '12 at 02:08
  • Theres only 2 days max of data, .. but it needs to display most recent to oldest. so Apr 1 is at the top, then March 31, march 1, feb 28 (if it showed that much data, that is) – Tallboy Jan 06 '12 at 02:18
  • now that i think about it, I think date might need custom sorting as well but thats not as important as time. i can figure that out soon. According to the descending order above the 1st of the month could be above or below, which wouldnt be right. – Tallboy Jan 06 '12 at 02:19
  • yes that was retarded of me to think that it would be sorted appropriately for date. But its only 1 day out of the month I need to worry about that so time would be the essential thing, then ill figure out date – Tallboy Jan 06 '12 at 02:21

3 Answers3

3

You can do this by parsing the time from your input string into a date object and then comparing the date objects:

Working Demo here: http://live.datatables.net/erefom/2/edit#preview

Source here: http://live.datatables.net/erefom/2/edit

Also see this answer: What is the best way to parse a time into a Date object from user input in Javascript?

Community
  • 1
  • 1
techfoobar
  • 65,616
  • 14
  • 114
  • 135
  • interesting, I will take a look over this. Thank you! – Tallboy Jan 06 '12 at 01:58
  • It still doesnt seem to work: I added some trickier times: http://live.datatables.net/erefom/4/edit#preview – Tallboy Jan 06 '12 at 03:11
  • I also removed the multicolumn sorting for the sake of this example so we can eliminate that variable entirely and focus on just getting the time to work, not relative to another column being sorted first. – Tallboy Jan 06 '12 at 03:11
  • Edit: i see now it was because it was lowercase p. I changed it to P (as in PM/AM), The only problem is now the times around the rage of 12 are showing wrong – Tallboy Jan 06 '12 at 03:18
  • http://live.datatables.net/erefom/7/edit#preview with the AM/PM thing fixed, except the 12 oclock part – Tallboy Jan 06 '12 at 03:20
  • 1
    http://live.datatables.net/erefom/8/edit#preview - With the 12-o-clock issue fixed. – techfoobar Jan 06 '12 at 03:48
  • It seems 12:20 PM is still in wrong spot? Thanks too, i really appreciate this :) – Tallboy Jan 06 '12 at 03:53
  • 2
    http://live.datatables.net/erefom/11/edit#preview - This one should work. Reworked the previous one quite a bit. :) – techfoobar Jan 06 '12 at 04:17
  • @Tallboy: Fantastic! May I include your answer on the DataTables sorting plug-ins page ( http://datatables.net/plug-ins/sorting )? If so, what credit (name/link) would you like? – Allan Jardine Jan 06 '12 at 08:09
  • @AllanJardine - As for the answer, feel free to. – techfoobar Jan 06 '12 at 09:55
  • @techfoobar: Oops - sorry that should have been @ you :-). Fantastic - thanks. Would you like a specific credit or just "techfoobar"? – Allan Jardine Jan 06 '12 at 10:55
  • @AllanJardine - Techfoobar is my just my code name. You can use my official name Vijayakrishnan and my blog url http://techfoobar.com – techfoobar Jan 06 '12 at 12:14
0

Elaborating from earlier examples; following snippet will sort even if the time cell is empty.

function getTimeValue(x) {
  // if the cell is not empty then parse it, otherwise just return 0 as the value; so it will be sorted appropriately.      
  if (x != '') {
    var time = x.match(/(\d+)(?::(\d\d))?\s*(P?)/);  
    var h = parseInt(time[1]) + (time[3] ? 12 : 0);
    if(!time[3] && parseInt(time[1])==12) h = 0;
    if(time[3] && parseInt(time[1])==12) h = 12;

    return h * 60 + ( parseInt(time[2]) || 0 );
  } else {
    return 0;
  }
}
Gajen Sunthara
  • 4,470
  • 37
  • 23
0

This is what worked for me

jQuery.extend(jQuery.fn.dataTableExt.oSort, {
    "time-sort-pre": function(a) {
        if (a == '')
            return null;

        var time = a.match(/(\d+)(:(\d\d))?\s*(p?)/i);
        if (time == null)
            return null;

        var hours = parseInt(time[1], 10);
        if (hours == 12 && !time[4]) {
            hours = 0;
        }
        else {
            hours += (hours < 12 && time[4]) ? 12 : 0;
        }

        var d = new Date();
        d.setHours(hours);
        d.setMinutes(parseInt(time[3], 10) || 0);
        d.setSeconds(0, 0);
        return d;
    },
    "time-sort-asc": function(a, b) {
        return ((a < b) ? -1 : ((a > b) ? 1 : 0));
    },
    "time-sort-desc": function(a, b) {
        return ((a < b) ? 1 : ((a > b) ? -1 : 0));
    }
});

using a piece of code from this answer What is the best way to parse a time into a Date object from user input in Javascript? and tested with dataTables 1.9.4, this code need to be called after the dataTables.js as a plugin, then just need to set de sType to your column {sType: "time-sort"}. Example:

$('#datatable-list').dataTable(
    aoColumns: [{sType: "time-sort"}]
);

Assuming that your table only have one column with the time values

Community
  • 1
  • 1
Castro Roy
  • 7,623
  • 13
  • 63
  • 97