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);
},
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"
});
@ -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);
},
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"
});
@ -1812,19 +1814,22 @@
},
format: function(s, table, cell, cellIndex) {
if (s) {
var c = table.config,
var date, d,
c = table.config,
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;
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") {
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") {
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") {
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"
});
@ -1835,7 +1840,8 @@
return (/^(([0-2]?\d:[0-5]\d)|([0-1]?\d:[0-5]\d\s?([AP]M)))$/i).test(s);
},
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"
});

View File

@ -5,9 +5,20 @@
;(function($){
"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)
* 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({
id: "extractUSLongDate",
@ -16,14 +27,19 @@
return false;
},
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);
return date ? $.tablesorter.formatFloat((new Date(date[0]).getTime() || ''), table) || s : s;
var date,
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"
});
/*! extract MMDDYYYY (ignore any other text)
* demo: http://jsfiddle.net/Mottie/abkNM/2418/
* demo: http://jsfiddle.net/Mottie/abkNM/4166/
*/
$.tablesorter.addParser({
id: "extractMMDDYYYY",
@ -32,14 +48,19 @@
return false;
},
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);
return date ? $.tablesorter.formatFloat((new Date(date[0]).getTime() || ''), table) || s : s;
var date,
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"
});
/*! extract DDMMYYYY (ignore any other text)
* demo: http://jsfiddle.net/Mottie/abkNM/2419/
* demo: http://jsfiddle.net/Mottie/abkNM/4167/
*/
$.tablesorter.addParser({
id: "extractDDMMYYYY",
@ -48,10 +69,11 @@
return false;
},
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);
if (date) {
date = date[0].replace(/(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/, "$2/$1/$3");
return $.tablesorter.formatFloat((new Date(date).getTime() || ''), table) || s;
var date,
str = s ? s.replace(/\s+/g," ").replace(/[\-.,]/g, "/").match(regex.dmy) : s;
if (str) {
date = new Date( str[0].replace(regex.dmyreplace, "$2/$1/$3") );
return date instanceof Date && isFinite(date) ? date.getTime() : s;
}
return s;
},
@ -59,7 +81,7 @@
});
/*! extract YYYYMMDD (ignore any other text)
* demo: http://jsfiddle.net/Mottie/abkNM/2420/
* demo: http://jsfiddle.net/Mottie/abkNM/4168/
*/
$.tablesorter.addParser({
id: "extractYYYYMMDD",
@ -68,10 +90,11 @@
return false;
},
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);
if (date) {
date = date[0].replace(/(\d{4})[\/\s](\d{1,2})[\/\s](\d{1,2})/, "$2/$3/$1");
return $.tablesorter.formatFloat((new Date(date).getTime() || ''), table) || s;
var date,
str = s ? s.replace(/\s+/g," ").replace(/[\-.,]/g, "/").match(regex.ymd) : s;
if (str) {
date = new Date( str[0].replace(regex.ymdreplace, "$2/$3/$1") );
return date instanceof Date && isFinite(date) ? date.getTime() : s;
}
return s;
},

View File

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

View File

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

View File

@ -1,16 +1,18 @@
/*! 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 */
;(function($){
"use strict";
var ts = $.tablesorter,
// 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
// 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, {
regxxxxyy: /(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{2})/,
@ -18,21 +20,26 @@
});
ts.formatDate = function(s, regex, format, table){
var n = s
// replace separators
.replace(/\s+/g," ").replace(/[-.,]/g, "/")
// reformat xx/xx/xx to mm/dd/19yy;
.replace(regex, format),
d = new Date(n),
y = d.getFullYear(),
rng = table && table.config.dateRange || range,
now = new Date().getFullYear();
// if date > 50 years old (set range), add 100 years
// this will work when people start using "50" and mean "2050"
while (now - y > rng) {
y += 100;
if (s) {
var y, rng,
n = s
// replace separators
.replace(/\s+/g," ").replace(/[-.,]/g, "/")
// reformat xx/xx/xx to mm/dd/19yy;
.replace(regex, format),
d = new Date(n);
if ( d instanceof Date && isFinite(d) ) {
y = d.getFullYear();
rng = table && table.config.dateRange || range;
// if date > 50 years old (set range), add 100 years
// this will work when people start using "50" and mean "2050"
while (now - y > rng) {
y += 100;
}
return d.setFullYear(y);
}
}
return d.setFullYear(y) || s;
return s;
};
$.tablesorter.addParser({

View File

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

View File

@ -6,7 +6,7 @@
"use strict";
/*! Sugar (http://sugarjs.com/dates#comparing_dates)
* demo: http://jsfiddle.net/Mottie/abkNM/551/
* demo: http://jsfiddle.net/Mottie/abkNM/4163/
*/
$.tablesorter.addParser({
id: "sugar",
@ -14,13 +14,14 @@
return false;
},
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"
});
/*! Datejs (http://www.datejs.com/)
* demo: http://jsfiddle.net/Mottie/abkNM/550/
* demo: http://jsfiddle.net/Mottie/abkNM/4164/
*/
$.tablesorter.addParser({
id: "datejs",
@ -28,7 +29,8 @@
return false;
},
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"
});

View File

@ -11,7 +11,7 @@
<script src="docs/js/jquery-latest.min.js"></script>
<script src="js/jquery.tablesorter.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="testing/testing.js"></script>
<script src="testing/testing-ipv6.js"></script>