date sort issue using natural sort function
date sort issue using natural sort function
gurusudhakar
Posts: 6Questions: 0Answers: 0
I`m facing date sort issues, the date format what I have used was "MMM DD YYYY" format. ex:- "Dec 23 2011".
I had a look around this forum and have used natural sort technique to sort the custom date format, its sorting fine except one issue.
The issue is if the dates are fallen under same year its sorting properly, but if the dates are fallen under different years it’s not sorting as expected.
Ex:- if I’ve dates from oct2011 - Feb2012 like 'Oct 01 2011', 'Nov 01 2011', 'Dec 01 2011', 'Jan 01 2012', 'Feb 01 2012'.
(In descending order)
Expected behavior should be: 'Feb 01 2012', 'Jan 01 2012', 'Dec 01 2011' ,'Nov 01 2011', 'Oct 01 2011'.
but Current behavior is 'Feb 01 2012', 'Jan 01 2012', 'Nov 01 2011', 'Oct 01 2011', 'Dec 01 2011'.
similarly ascending order also is not working as expected.
I have been struggling with this for quite some time so, any feedback would be great, here is my code:
/* Defined two custom functions (asc and desc) for sorting */
jQuery.fn.dataTableExt.oSort['natural-asc'] = function(a,b) {
// Making sure to remove any HTML code sorrounding the value to be sorted.
var x = a.replace( /<.*?>/g, "" );
var y = b.replace( /<.*?>/g, "" );
return naturalSort(x,y);
};
jQuery.fn.dataTableExt.oSort['natural-desc'] = function(a,b) {
// Making sure to remove any HTML code sorrounding the value to be sorted.
var x = a.replace( /<.*?>/g, "" );
var y = b.replace( /<.*?>/g, "" );
return naturalSort(x,y) * -1;
};
/*Getting month index value*/
function getMonthIdx(monthName) {
var months = {
'Jan':0, 'Feb':1, 'Mar':2, 'Apr':3, 'May':4, 'Jun':5
, 'Jul':6, 'Aug':7, 'Sep':8, 'Oct':9, 'Nov':10, 'Dec':11
};
return months[monthName];
}
//This method can sort any field in natural order. It has some special handling for date fields
//to handle dates in 'MMM dd yyyy' format.
function naturalSort (a, b) {
var re = /(^-?[0-9]+(\.?[0-9]*)[df]?e?[0-9]?$|^0x[0-9a-f]+$|[0-9]+)/gi,
sre = /(^[ ]*|[ ]*$)/g,
dre = /(^([\w ]+,?[\w ]+)?[\w ]+,?[\w ]+\d+:\d+(:\d+)?[\w ]?|^\d{1,4}[\/\-]\d{1,4}[\/\-]\d{1,4}|^\w+, \w+ \d+, \d{4})/,
hre = /^0x[0-9a-f]+$/i,
ore = /^0/,
// convert all to strings and trim()
x = a.toString().replace(sre, '') || '',
y = b.toString().replace(sre, '') || '',
// chunk/tokenize
xN = x.replace(re, '\0$1\0').replace(/\0$/,'').replace(/^\0/,'').split('\0'),
yN = y.replace(re, '\0$1\0').replace(/\0$/,'').replace(/^\0/,'').split('\0'),
// numeric, hex or date detection
xD = parseInt(x.match(hre)) || (xN.length != 1 && x.match(dre) && Date.parse(x)),
yD = parseInt(y.match(hre)) || xD && y.match(dre) && Date.parse(y) || null;
// first try and sort Hex codes or Dates
if (yD)
if ( xD < yD ) return -1;
else if ( xD > yD ) return 1;
// natural sorting through split numeric strings and default strings
for(var cLoc=0, numS=Math.max(xN.length, yN.length); cLoc < numS; cLoc++) {
// find floats not starting with '0', string or 0 if not defined (Clint Priest)
oFxNcL = !(xN[cLoc] || '').match(ore) && parseFloat(xN[cLoc]) || xN[cLoc] || 0;
oFyNcL = !(yN[cLoc] || '').match(ore) && parseFloat(yN[cLoc]) || yN[cLoc] || 0;
// handle numeric vs string comparison - number < string - (Kyle Adams)
if (isNaN(oFxNcL) !== isNaN(oFyNcL)) return (isNaN(oFxNcL)) ? 1 : -1;
// rely on string comparison if different types - i.e. '02' < 2 != '02' < '2'
else if(isNaN(oFxNcL) && isNaN(oFyNcL)) {
//This is a date column and the value is 'mmm' part of date.
//Lets convert this to numeric value for easier comparison.
oFxNcL = getMonthIdx(oFxNcL.replace(/^\s+|\s+$/g,""));
oFyNcL = getMonthIdx(oFyNcL.replace(/^\s+|\s+$/g,""));
} else if (typeof oFxNcL !== typeof oFyNcL) {
oFxNcL += '';
oFyNcL += '';
}
if (oFxNcL < oFyNcL) return -1;
if (oFxNcL > oFyNcL) return 1;
}
return 0;
}
Thanks,
Guru
I had a look around this forum and have used natural sort technique to sort the custom date format, its sorting fine except one issue.
The issue is if the dates are fallen under same year its sorting properly, but if the dates are fallen under different years it’s not sorting as expected.
Ex:- if I’ve dates from oct2011 - Feb2012 like 'Oct 01 2011', 'Nov 01 2011', 'Dec 01 2011', 'Jan 01 2012', 'Feb 01 2012'.
(In descending order)
Expected behavior should be: 'Feb 01 2012', 'Jan 01 2012', 'Dec 01 2011' ,'Nov 01 2011', 'Oct 01 2011'.
but Current behavior is 'Feb 01 2012', 'Jan 01 2012', 'Nov 01 2011', 'Oct 01 2011', 'Dec 01 2011'.
similarly ascending order also is not working as expected.
I have been struggling with this for quite some time so, any feedback would be great, here is my code:
/* Defined two custom functions (asc and desc) for sorting */
jQuery.fn.dataTableExt.oSort['natural-asc'] = function(a,b) {
// Making sure to remove any HTML code sorrounding the value to be sorted.
var x = a.replace( /<.*?>/g, "" );
var y = b.replace( /<.*?>/g, "" );
return naturalSort(x,y);
};
jQuery.fn.dataTableExt.oSort['natural-desc'] = function(a,b) {
// Making sure to remove any HTML code sorrounding the value to be sorted.
var x = a.replace( /<.*?>/g, "" );
var y = b.replace( /<.*?>/g, "" );
return naturalSort(x,y) * -1;
};
/*Getting month index value*/
function getMonthIdx(monthName) {
var months = {
'Jan':0, 'Feb':1, 'Mar':2, 'Apr':3, 'May':4, 'Jun':5
, 'Jul':6, 'Aug':7, 'Sep':8, 'Oct':9, 'Nov':10, 'Dec':11
};
return months[monthName];
}
//This method can sort any field in natural order. It has some special handling for date fields
//to handle dates in 'MMM dd yyyy' format.
function naturalSort (a, b) {
var re = /(^-?[0-9]+(\.?[0-9]*)[df]?e?[0-9]?$|^0x[0-9a-f]+$|[0-9]+)/gi,
sre = /(^[ ]*|[ ]*$)/g,
dre = /(^([\w ]+,?[\w ]+)?[\w ]+,?[\w ]+\d+:\d+(:\d+)?[\w ]?|^\d{1,4}[\/\-]\d{1,4}[\/\-]\d{1,4}|^\w+, \w+ \d+, \d{4})/,
hre = /^0x[0-9a-f]+$/i,
ore = /^0/,
// convert all to strings and trim()
x = a.toString().replace(sre, '') || '',
y = b.toString().replace(sre, '') || '',
// chunk/tokenize
xN = x.replace(re, '\0$1\0').replace(/\0$/,'').replace(/^\0/,'').split('\0'),
yN = y.replace(re, '\0$1\0').replace(/\0$/,'').replace(/^\0/,'').split('\0'),
// numeric, hex or date detection
xD = parseInt(x.match(hre)) || (xN.length != 1 && x.match(dre) && Date.parse(x)),
yD = parseInt(y.match(hre)) || xD && y.match(dre) && Date.parse(y) || null;
// first try and sort Hex codes or Dates
if (yD)
if ( xD < yD ) return -1;
else if ( xD > yD ) return 1;
// natural sorting through split numeric strings and default strings
for(var cLoc=0, numS=Math.max(xN.length, yN.length); cLoc < numS; cLoc++) {
// find floats not starting with '0', string or 0 if not defined (Clint Priest)
oFxNcL = !(xN[cLoc] || '').match(ore) && parseFloat(xN[cLoc]) || xN[cLoc] || 0;
oFyNcL = !(yN[cLoc] || '').match(ore) && parseFloat(yN[cLoc]) || yN[cLoc] || 0;
// handle numeric vs string comparison - number < string - (Kyle Adams)
if (isNaN(oFxNcL) !== isNaN(oFyNcL)) return (isNaN(oFxNcL)) ? 1 : -1;
// rely on string comparison if different types - i.e. '02' < 2 != '02' < '2'
else if(isNaN(oFxNcL) && isNaN(oFyNcL)) {
//This is a date column and the value is 'mmm' part of date.
//Lets convert this to numeric value for easier comparison.
oFxNcL = getMonthIdx(oFxNcL.replace(/^\s+|\s+$/g,""));
oFyNcL = getMonthIdx(oFyNcL.replace(/^\s+|\s+$/g,""));
} else if (typeof oFxNcL !== typeof oFyNcL) {
oFxNcL += '';
oFyNcL += '';
}
if (oFxNcL < oFyNcL) return -1;
if (oFxNcL > oFyNcL) return 1;
}
return 0;
}
Thanks,
Guru
This discussion has been closed.