Parsers: Update all date parsers to ensure valid dates

This commit is contained in:
Mottie 2014-09-30 16:20:04 -05:00
parent 6fbdc1a3b9
commit 065342b825
8 changed files with 120 additions and 69 deletions

View File

@ -1762,7 +1762,8 @@
return (/^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}/).test(s); return (/^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}/).test(s);
}, },
format: function(s, table) { format: function(s, table) {
return s ? ts.formatFloat((s !== "") ? (new Date(s.replace(/-/g, "/")).getTime() || s) : "", table) : s; var date = s ? new Date( s.replace(/-/g, "/") ) : s;
return date instanceof Date && isFinite(date) ? date.getTime() : s;
}, },
type: "numeric" type: "numeric"
}); });
@ -1799,7 +1800,8 @@
return (/^[A-Z]{3,10}\.?\s+\d{1,2},?\s+(\d{4})(\s+\d{1,2}:\d{2}(:\d{2})?(\s+[AP]M)?)?$/i).test(s) || (/^\d{1,2}\s+[A-Z]{3,10}\s+\d{4}/i).test(s); return (/^[A-Z]{3,10}\.?\s+\d{1,2},?\s+(\d{4})(\s+\d{1,2}:\d{2}(:\d{2})?(\s+[AP]M)?)?$/i).test(s) || (/^\d{1,2}\s+[A-Z]{3,10}\s+\d{4}/i).test(s);
}, },
format: function(s, table) { format: function(s, table) {
return s ? ts.formatFloat( (new Date(s.replace(/(\S)([AP]M)$/i, "$1 $2")).getTime() || s), table) : s; var date = s ? new Date( s.replace(/(\S)([AP]M)$/i, "$1 $2") ) : s;
return date instanceof Date && isFinite(date) ? date.getTime() : s;
}, },
type: "numeric" type: "numeric"
}); });
@ -1812,19 +1814,22 @@
}, },
format: function(s, table, cell, cellIndex) { format: function(s, table, cell, cellIndex) {
if (s) { if (s) {
var c = table.config, var date, d,
c = table.config,
ci = c.$headers.filter('[data-column=' + cellIndex + ']:last'), ci = c.$headers.filter('[data-column=' + cellIndex + ']:last'),
format = ci.length && ci[0].dateFormat || ts.getData( ci, ts.getColumnData( table, c.headers, cellIndex ), 'dateFormat') || c.dateFormat; format = ci.length && ci[0].dateFormat || ts.getData( ci, ts.getColumnData( table, c.headers, cellIndex ), 'dateFormat') || c.dateFormat;
s = s.replace(/\s+/g," ").replace(/[\-.,]/g, "/"); // escaped - because JSHint in Firefox was showing it as an error d = s.replace(/\s+/g," ").replace(/[\-.,]/g, "/"); // escaped - because JSHint in Firefox was showing it as an error
if (format === "mmddyyyy") { if (format === "mmddyyyy") {
s = s.replace(/(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/, "$3/$1/$2"); d = d.replace(/(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/, "$3/$1/$2");
} else if (format === "ddmmyyyy") { } else if (format === "ddmmyyyy") {
s = s.replace(/(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/, "$3/$2/$1"); d = d.replace(/(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/, "$3/$2/$1");
} else if (format === "yyyymmdd") { } else if (format === "yyyymmdd") {
s = s.replace(/(\d{4})[\/\s](\d{1,2})[\/\s](\d{1,2})/, "$1/$2/$3"); d = d.replace(/(\d{4})[\/\s](\d{1,2})[\/\s](\d{1,2})/, "$1/$2/$3");
} }
date = new Date(d);
return date instanceof Date && isFinite(date) ? date.getTime() : s;
} }
return s ? ts.formatFloat( (new Date(s).getTime() || s), table) : s; return s;
}, },
type: "numeric" type: "numeric"
}); });
@ -1835,7 +1840,8 @@
return (/^(([0-2]?\d:[0-5]\d)|([0-1]?\d:[0-5]\d\s?([AP]M)))$/i).test(s); return (/^(([0-2]?\d:[0-5]\d)|([0-1]?\d:[0-5]\d\s?([AP]M)))$/i).test(s);
}, },
format: function(s, table) { format: function(s, table) {
return s ? ts.formatFloat( (new Date("2000/01/01 " + s.replace(/(\S)([AP]M)$/i, "$1 $2")).getTime() || s), table) : s; var date = s ? new Date( "2000/01/01 " + s.replace(/(\S)([AP]M)$/i, "$1 $2") ) : s;
return date instanceof Date && isFinite(date) ? date.getTime() : s;
}, },
type: "numeric" type: "numeric"
}); });

View File

@ -5,9 +5,20 @@
;(function($){ ;(function($){
"use strict"; "use strict";
var regex = {
usLong : /[A-Z]{3,10}\.?\s+\d{1,2},?\s+(?:\d{4})(?:\s+\d{1,2}:\d{2}(?::\d{2})?(?:\s+[AP]M)?)?/i,
mdy : /(\d{1,2}[\/\s]\d{1,2}[\/\s]\d{4}(\s+\d{1,2}:\d{2}(:\d{2})?(\s+[AP]M)?)?)/i,
dmy : /(\d{1,2}[\/\s]\d{1,2}[\/\s]\d{4}(\s+\d{1,2}:\d{2}(:\d{2})?(\s+[AP]M)?)?)/i,
dmyreplace : /(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/,
ymd : /(\d{4}[\/\s]\d{1,2}[\/\s]\d{1,2}(\s+\d{1,2}:\d{2}(:\d{2})?(\s+[AP]M)?)?)/i,
ymdreplace : /(\d{4})[\/\s](\d{1,2})[\/\s](\d{1,2})/
};
/*! extract US Long Date (ignore any other text) /*! extract US Long Date (ignore any other text)
* e.g. "Sue's Birthday! Jun 26, 2004 7:22 AM (8# 2oz)" * e.g. "Sue's Birthday! Jun 26, 2004 7:22 AM (8# 2oz)"
* demo: http://jsfiddle.net/abkNM/2293/ * demo: http://jsfiddle.net/Mottie/abkNM/4165/
*/ */
$.tablesorter.addParser({ $.tablesorter.addParser({
id: "extractUSLongDate", id: "extractUSLongDate",
@ -16,14 +27,19 @@
return false; return false;
}, },
format: function (s, table) { format: function (s, table) {
var date = s.match(/[A-Z]{3,10}\.?\s+\d{1,2},?\s+(?:\d{4})(?:\s+\d{1,2}:\d{2}(?::\d{2})?(?:\s+[AP]M)?)?/i); var date,
return date ? $.tablesorter.formatFloat((new Date(date[0]).getTime() || ''), table) || s : s; str = s ? s.match(regex.usLong) : s;
if (str) {
date = new Date( str[0] );
return date instanceof Date && isFinite(date) ? date.getTime() : s;
}
return s;
}, },
type: "numeric" type: "numeric"
}); });
/*! extract MMDDYYYY (ignore any other text) /*! extract MMDDYYYY (ignore any other text)
* demo: http://jsfiddle.net/Mottie/abkNM/2418/ * demo: http://jsfiddle.net/Mottie/abkNM/4166/
*/ */
$.tablesorter.addParser({ $.tablesorter.addParser({
id: "extractMMDDYYYY", id: "extractMMDDYYYY",
@ -32,14 +48,19 @@
return false; return false;
}, },
format: function (s, table) { format: function (s, table) {
var date = s.replace(/\s+/g," ").replace(/[\-.,]/g, "/").match(/(\d{1,2}[\/\s]\d{1,2}[\/\s]\d{4}(\s+\d{1,2}:\d{2}(:\d{2})?(\s+[AP]M)?)?)/i); var date,
return date ? $.tablesorter.formatFloat((new Date(date[0]).getTime() || ''), table) || s : s; str = s ? s.replace(/\s+/g," ").replace(/[\-.,]/g, "/").match(regex.mdy) : s;
if (str) {
date = new Date( str[0] );
return date instanceof Date && isFinite(date) ? date.getTime() : s;
}
return s;
}, },
type: "numeric" type: "numeric"
}); });
/*! extract DDMMYYYY (ignore any other text) /*! extract DDMMYYYY (ignore any other text)
* demo: http://jsfiddle.net/Mottie/abkNM/2419/ * demo: http://jsfiddle.net/Mottie/abkNM/4167/
*/ */
$.tablesorter.addParser({ $.tablesorter.addParser({
id: "extractDDMMYYYY", id: "extractDDMMYYYY",
@ -48,10 +69,11 @@
return false; return false;
}, },
format: function (s, table) { format: function (s, table) {
var date = s.replace(/\s+/g," ").replace(/[\-.,]/g, "/").match(/(\d{1,2}[\/\s]\d{1,2}[\/\s]\d{4}(\s+\d{1,2}:\d{2}(:\d{2})?(\s+[AP]M)?)?)/i); var date,
if (date) { str = s ? s.replace(/\s+/g," ").replace(/[\-.,]/g, "/").match(regex.dmy) : s;
date = date[0].replace(/(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/, "$2/$1/$3"); if (str) {
return $.tablesorter.formatFloat((new Date(date).getTime() || ''), table) || s; date = new Date( str[0].replace(regex.dmyreplace, "$2/$1/$3") );
return date instanceof Date && isFinite(date) ? date.getTime() : s;
} }
return s; return s;
}, },
@ -59,7 +81,7 @@
}); });
/*! extract YYYYMMDD (ignore any other text) /*! extract YYYYMMDD (ignore any other text)
* demo: http://jsfiddle.net/Mottie/abkNM/2420/ * demo: http://jsfiddle.net/Mottie/abkNM/4168/
*/ */
$.tablesorter.addParser({ $.tablesorter.addParser({
id: "extractYYYYMMDD", id: "extractYYYYMMDD",
@ -68,10 +90,11 @@
return false; return false;
}, },
format: function (s, table) { format: function (s, table) {
var date = s.replace(/\s+/g," ").replace(/[\-.,]/g, "/").match(/(\d{4}[\/\s]\d{1,2}[\/\s]\d{1,2}(\s+\d{1,2}:\d{2}(:\d{2})?(\s+[AP]M)?)?)/i); var date,
if (date) { str = s ? s.replace(/\s+/g," ").replace(/[\-.,]/g, "/").match(regex.ymd) : s;
date = date[0].replace(/(\d{4})[\/\s](\d{1,2})[\/\s](\d{1,2})/, "$2/$3/$1"); if (str) {
return $.tablesorter.formatFloat((new Date(date).getTime() || ''), table) || s; date = new Date( str[0].replace(regex.ymdreplace, "$2/$3/$1") );
return date instanceof Date && isFinite(date) ? date.getTime() : s;
} }
return s; return s;
}, },

View File

@ -9,13 +9,14 @@
"use strict"; "use strict";
var iso8601date = /^([0-9]{4})(-([0-9]{2})(-([0-9]{2})(T([0-9]{2}):([0-9]{2})(:([0-9]{2})(\.([0-9]+))?)?(Z|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?$/; var iso8601date = /^([0-9]{4})(-([0-9]{2})(-([0-9]{2})(T([0-9]{2}):([0-9]{2})(:([0-9]{2})(\.([0-9]+))?)?(Z|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?$/;
$.tablesorter.addParser({ $.tablesorter.addParser({
id : 'iso8601date', id : 'iso8601date',
is : function(s) { is : function(s) {
return s.match(iso8601date); return s ? s.match(iso8601date) : false;
}, },
format : function(s) { format : function(s) {
var result = s.match(iso8601date); var result = s ? s.match(iso8601date) : s;
if (result) { if (result) {
var date = new Date(result[1], 0, 1); var date = new Date(result[1], 0, 1);
if (result[3]) { date.setMonth(result[3] - 1); } if (result[3]) { date.setMonth(result[3] - 1); }
@ -24,7 +25,7 @@
if (result[8]) { date.setMinutes(result[8]); } if (result[8]) { date.setMinutes(result[8]); }
if (result[10]) { date.setSeconds(result[10]); } if (result[10]) { date.setSeconds(result[10]); }
if (result[12]) { date.setMilliseconds(Number('0.' + result[12]) * 1000); } if (result[12]) { date.setMilliseconds(Number('0.' + result[12]) * 1000); }
return date; return date.getTime();
} }
return s; return s;
}, },

View File

@ -1,5 +1,5 @@
/*! Month parser /*! Month parser
* Demo: http://jsfiddle.net/Mottie/abkNM/477/ * Demo: http://jsfiddle.net/Mottie/abkNM/4169/
*/ */
/*jshint jquery:true */ /*jshint jquery:true */
;(function($){ ;(function($){
@ -18,14 +18,20 @@
return false; return false;
}, },
format: function(s, table) { format: function(s, table) {
if (s) {
var j = -1, c = table.config, var j = -1, c = table.config,
n = c.ignoreCase ? s.toLocaleLowerCase() : s; n = c.ignoreCase ? s.toLocaleLowerCase() : s;
$.each(ts.dates[ 'month' + (c.ignoreCase ? 'Lower' : 'Cased') ], function(i,v){ $.each(ts.dates[ 'month' + (c.ignoreCase ? 'Lower' : 'Cased') ], function(i,v){
if (j < 0 && n.match(v)) { j = i; } if (j < 0 && n.match(v)) {
j = i;
return false;
}
}); });
// return s (original string) if there isn't a match // return s (original string) if there isn't a match
// (non-weekdays will sort separately and empty cells will sort as expected) // (non-weekdays will sort separately and empty cells will sort as expected)
return j < 0 ? s : j; return j < 0 ? s : j;
}
return s;
}, },
type: "numeric" type: "numeric"
}); });

View File

@ -1,16 +1,18 @@
/*! Two digit year parser /*! Two digit year parser
* Demo: http://jsfiddle.net/Mottie/abkNM/427/ * Demo: http://mottie.github.io/tablesorter/docs/example-parsers-dates.html
*/ */
/*jshint jquery:true */ /*jshint jquery:true */
;(function($){ ;(function($){
"use strict"; "use strict";
var ts = $.tablesorter,
// Make the date be within +/- range of the 2 digit year // Make the date be within +/- range of the 2 digit year
// so if the current year is 2020, and the 2 digit year is 80 (2080 - 2020 > 50), it becomes 1980 // so if the current year is 2020, and the 2 digit year is 80 (2080 - 2020 > 50), it becomes 1980
// if the 2 digit year is 50 (2050 - 2020 < 50), then it becomes 2050. // if the 2 digit year is 50 (2050 - 2020 < 50), then it becomes 2050.
range = 50; var range = 50,
// no need to change any of the code below
ts = $.tablesorter,
now = new Date().getFullYear();
ts.dates = $.extend({}, ts.dates, { ts.dates = $.extend({}, ts.dates, {
regxxxxyy: /(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{2})/, regxxxxyy: /(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{2})/,
@ -18,21 +20,26 @@
}); });
ts.formatDate = function(s, regex, format, table){ ts.formatDate = function(s, regex, format, table){
var n = s if (s) {
var y, rng,
n = s
// replace separators // replace separators
.replace(/\s+/g," ").replace(/[-.,]/g, "/") .replace(/\s+/g," ").replace(/[-.,]/g, "/")
// reformat xx/xx/xx to mm/dd/19yy; // reformat xx/xx/xx to mm/dd/19yy;
.replace(regex, format), .replace(regex, format),
d = new Date(n), d = new Date(n);
y = d.getFullYear(), if ( d instanceof Date && isFinite(d) ) {
rng = table && table.config.dateRange || range, y = d.getFullYear();
now = new Date().getFullYear(); rng = table && table.config.dateRange || range;
// if date > 50 years old (set range), add 100 years // if date > 50 years old (set range), add 100 years
// this will work when people start using "50" and mean "2050" // this will work when people start using "50" and mean "2050"
while (now - y > rng) { while (now - y > rng) {
y += 100; y += 100;
} }
return d.setFullYear(y) || s; return d.setFullYear(y);
}
}
return s;
}; };
$.tablesorter.addParser({ $.tablesorter.addParser({

View File

@ -1,5 +1,5 @@
/*! Weekday parser /*! Weekday parser
* Demo: http://jsfiddle.net/Mottie/abkNM/477/ * Demo: http://jsfiddle.net/Mottie/abkNM/4169/
*/ */
/*jshint jquery:true */ /*jshint jquery:true */
;(function($){ ;(function($){
@ -18,14 +18,20 @@
return false; return false;
}, },
format: function(s, table) { format: function(s, table) {
if (s) {
var j = -1, c = table.config; var j = -1, c = table.config;
s = c.ignoreCase ? s.toLocaleLowerCase() : s; s = c.ignoreCase ? s.toLocaleLowerCase() : s;
$.each(ts.dates[ 'weekday' + (c.ignoreCase ? 'Lower' : 'Cased') ], function(i,v){ $.each(ts.dates[ 'weekday' + (c.ignoreCase ? 'Lower' : 'Cased') ], function(i,v){
if (j < 0 && s.match(v)) { j = i; } if (j < 0 && s.match(v)) {
j = i;
return false;
}
}); });
// return s (original string) if there isn't a match // return s (original string) if there isn't a match
// (non-weekdays will sort separately and empty cells will sort as expected) // (non-weekdays will sort separately and empty cells will sort as expected)
return j < 0 ? s : j; return j < 0 ? s : j;
}
return s;
}, },
type: "numeric" type: "numeric"
}); });

View File

@ -6,7 +6,7 @@
"use strict"; "use strict";
/*! Sugar (http://sugarjs.com/dates#comparing_dates) /*! Sugar (http://sugarjs.com/dates#comparing_dates)
* demo: http://jsfiddle.net/Mottie/abkNM/551/ * demo: http://jsfiddle.net/Mottie/abkNM/4163/
*/ */
$.tablesorter.addParser({ $.tablesorter.addParser({
id: "sugar", id: "sugar",
@ -14,13 +14,14 @@
return false; return false;
}, },
format: function(s) { format: function(s) {
return Date.create ? Date.create(s).getTime() || s : new Date(s).getTime() || s; var date = Date.create ? Date.create(s) : s ? new Date(s) : s;
return date instanceof Date && isFinite(date) ? date.getTime() : s;
}, },
type: "numeric" type: "numeric"
}); });
/*! Datejs (http://www.datejs.com/) /*! Datejs (http://www.datejs.com/)
* demo: http://jsfiddle.net/Mottie/abkNM/550/ * demo: http://jsfiddle.net/Mottie/abkNM/4164/
*/ */
$.tablesorter.addParser({ $.tablesorter.addParser({
id: "datejs", id: "datejs",
@ -28,7 +29,8 @@
return false; return false;
}, },
format: function(s) { format: function(s) {
return Date.parse && Date.parse(s) || s; var date = Date.parse ? Date.parse(s) : s ? new Date(s) : s;
return date instanceof Date && isFinite(date) ? date.getTime() : s;
}, },
type: "numeric" type: "numeric"
}); });

View File

@ -11,7 +11,7 @@
<script src="docs/js/jquery-latest.min.js"></script> <script src="docs/js/jquery-latest.min.js"></script>
<script src="js/jquery.tablesorter.js"></script> <script src="js/jquery.tablesorter.js"></script>
<script src="js/jquery.tablesorter.widgets.js"></script> <script src="js/jquery.tablesorter.widgets.js"></script>
<script src="js/parsers/parser-ipv6.js"></script> <script src="js/parsers/parser-network.js"></script>
<script src="js/jquery.metadata.js"></script> <script src="js/jquery.metadata.js"></script>
<script src="testing/testing.js"></script> <script src="testing/testing.js"></script>
<script src="testing/testing-ipv6.js"></script> <script src="testing/testing-ipv6.js"></script>