Incorrect sorting date / time with jquery tablesorter

i'm using plugin Tablesorter. I can not properly configure sort one of the columns. It looks like this (days hours minutes):

0d04h11m
4d22h26m
27d20h14m
0d09h50m
2d02h34m
1d11h02m

I tried to apply {sorter:'digits'}

After sorting:

4d22h26m
2d02h34m
27d20h14m
1d11h02m
0d09h50m
0d04h11m

That is not true sorts, if the two-digit days.

How can I solve this problem?

Upvotes: 3

Views: 445

Answers (2)

gabrielperales
gabrielperales

Reputation: 7785

UPDATED

You can use this funcition to sort your dates:

$(function() {
  var sortDates = (function(){
    function dateToNumber(date){
      return parseInt(
        date.match(/\d+/g)
          .map(function(field){
            return field.length === 1 ? '0' + field : field;
          }).join('')
      , 10);
    }
    return function(date1, date2){
      return dateToNumber(date1) - dateToNumber(date2);
    };
  }());

  $("#table").tablesorter({
    textSorter : {
      1 : sortDates
    }
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.tablesorter/2.25.1/js/jquery.tablesorter.min.js"></script>

<table id="table">
  <thead>
    <tr>
      <th>dates</th>
    </tr>
  </thead>
  <tr>
    <td>0d04h11m</td>
  </tr>
  <tr>
    <td>4d22h26m</td>
  </tr>
  <tr>
    <td>27d20h14m</td>
  </tr>
  <tr>
    <td>0d09h50m</td>
  </tr>
  <tr>
    <td>2d02h34m</td>
  </tr>
  <tr>
    <td>1d11h02m</td>
  </tr>
</table>

Upvotes: 0

Henrique Barcelos
Henrique Barcelos

Reputation: 7900

You need to add your own parser:

Disclaimer: the following will only work if your data has the same forma always. Otherwise, if you can have such things as 4d, 4d1h, you'll need to figure out another way.

$.tablesorter.addParser({
    id: 'custom_sort_function',
    is: function(s) {
        return false;
    },
    format: function(s) {
        return parseInt(s.replace(/\D/g, ''), 10); // '0d04h11m' --> '00411' --> 411
    },
    type: 'numeric'
});

Then you add:

{sorter:'custom_sort_function'}

For further functionalities, see the docs.


Edit:

This function will give you a safer parser:

format: function(s) {
    var regexParser = /(?:([0-9]{1,2})d)?(?:([0-9]{1,2})h)?(?:([0-9]{1,2})m)?(?:([0-9]{1,2})s)?/;
    var matches = regexParser.exec(s);
    var days = parseInt(matches[1], 10) || 0;
    var hours = parseInt(matches[2], 10) || 0;
    var minutes = parseInt(matches[3], 10) || 0;
    var seconds = parseInt(matches[4], 10) || 0;

    return  ((days * 24 + hours) * 60 + minutes) * 60 + seconds;
}

And if you add this:

is: function(s) {
    return /^(?:([0-9]{1,2})d)?(?:([0-9]{1,2})h)?(?:([0-9]{1,2})m)?(?:([0-9]{1,2})s)?$/.test(s);
}

you'll have an automatic parser, so you won't need the {sorter: 'custom_sort_function'}.

Upvotes: 1

Related Questions