From ff4d907df7a79ed209babd02d1254659fc0a08c9 Mon Sep 17 00:00:00 2001 From: ravestack Date: Sun, 30 Aug 2015 21:15:41 -0400 Subject: [PATCH 1/6] Leap year and general date validation for isDate(). --- test/validators.js | 7 +++++++ validator.js | 32 +++++++++++++++++++++++++++++++- 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/test/validators.js b/test/validators.js index 959ba1dbd..7b41959ef 100644 --- a/test/validators.js +++ b/test/validators.js @@ -860,6 +860,13 @@ describe('Validators', function () { , '2011.08.04' , '4. 8. 2011. GMT' , '2011-08-04 12:00' + , '2/29/24' + , '2-29-24' + , '12' + , '11/2/23 12:24' + , new Date() + , 'Mon Aug 17 2015 00:24:56 GMT-0500 (CDT)' + , '2/22/23 23:24:26' ] , invalid: [ 'foo' diff --git a/validator.js b/validator.js index 7a038d6bc..ac2c3f5dd 100644 --- a/validator.js +++ b/validator.js @@ -468,7 +468,37 @@ }; validator.isDate = function (str) { - return !isNaN(Date.parse(str)); + var normalizedDate = new Date((new Date(str)).toUTCString()); + var regularDay = String(normalizedDate.getDate()); + var utcDay = String(normalizedDate.getUTCDate()); + var dayOrYear, dayOrYearMatches, year; + if (isNaN(Date.parse(normalizedDate))) { + return false; + } + if (typeof str !== 'string') { + return true; //if Date.parse() passes, it's the current time + } + //check for valid double digits that could be late days + //check for all matches since a string like '12/23' is a valid date + //ignore everything with nearby colons + dayOrYearMatches = str.match(/(^|[^:])[23]\d([^:\d]|$)/g); + if (!dayOrYearMatches) { + return true; + } + dayOrYear = dayOrYearMatches.map(function(digitString) { + return digitString.match(/\d+/g)[0]; + }).join('/'); + year = String(normalizedDate.getFullYear()).slice(-2); + //local date and UTC date can differ, but both are valid, so check agains both + if (dayOrYear === regularDay || dayOrYear === utcDay || dayOrYear === year) { + return true; + } else if ((dayOrYear === (regularDay + '/' + year)) || (dayOrYear === (year + '/' + regularDay))) { + return true; + } else if ((dayOrYear === (utcDay + '/' + year)) || (dayOrYear === (year + '/' + utcDay))) { + return true; + } else { + return false; + } }; validator.isAfter = function (str, date) { From 4beed242b28fdc30d6556d723007f67c979c6bc0 Mon Sep 17 00:00:00 2001 From: ravestack Date: Sat, 26 Sep 2015 23:46:22 -0400 Subject: [PATCH 2/6] add ISO 8601 tests --- test/validators.js | 61 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 58 insertions(+), 3 deletions(-) diff --git a/test/validators.js b/test/validators.js index 7b41959ef..23c3333ca 100644 --- a/test/validators.js +++ b/test/validators.js @@ -854,24 +854,79 @@ describe('Validators', function () { test({ validator: 'isDate' , valid: [ + //NOTE: null pass as well in the regular function, but fails in the test suite '2011-08-04' + , '2011-09-30' , '04. 08. 2011.' , '08/04/2011' + , '08/31/2011' , '2011.08.04' - , '4. 8. 2011. GMT' - , '2011-08-04 12:00' , '2/29/24' , '2-29-24' + , '4. 8. 2011. GMT' + , '2. 28. 2011. GMT' + , '2. 29. 2008. GMT' + , '2011-08-04 12:00' + , '2/22/23' + , '2-23-22' , '12' , '11/2/23 12:24' , new Date() , 'Mon Aug 17 2015 00:24:56 GMT-0500 (CDT)' , '2/22/23 23:24:26' - ] + //valid ISO 8601 dates below + , '2009-12T12:34' + , '2009' + , '2009-05-19' + , '2009-05-19' + , '2009-05' + , '2009-001' + , '2009-05-19' + , '2009-05-19 00:00' + , '2009-05-19 14:31' + , '2009-05-19 14:39:22' + , '2009-05-19T14:39Z' + , '2009-05-19 14:39:22-06:00' + , '2009-05-19 14:39:22+0600' + , '2009-05-19 14:39:22-01' + , '2007-04-06T00:00' + , '2010-02-18T16:23:48.5' + , '200905' + , '2009-' + , '2009-05-19 14:' + , '200912-01' + ] , invalid: [ 'foo' , '2011-foo-04' + , '2011-09-31' + , '2. 29. 1987. GMT' + , '2. 29. 2011. GMT' + , '2/29/25' + , '2-29-25' , 'GMT' + //invalid ISO 8601 dates below + , '2009367' + , '2007-04-05T24:50' + , '2009-000' + , '2009-M511' + , '2009M511' + , '2009-05-19T14a39r' + , '2009-05-19T14:3924' + , '2009-0519' + , '2009-05-1914:39' + , '2009-05-19r14:39' + , '2009-05-19 14a39a22' + , '2009-05-19 14:39:22+06a00' + , '2009-05-19 146922.500' + , '2010-02-18T16.5:23.35:48' + , '2010-02-18T16:23.35:48' + , '2010-02-18T16:23.35:48.45' + , '2009-05-19 14.5.44' + , '2010-02-18T16:23.33.600' + , '2010-02-18T16,25:23:48,444' + , '2009-02-30 14:' + , '200912-32' ] }); }); From 88bf49a8709fe2876e5acd2a54ecf4a4dbcd207d Mon Sep 17 00:00:00 2001 From: ravestack Date: Sat, 26 Sep 2015 23:58:09 -0400 Subject: [PATCH 3/6] misspelling --- test/validators.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/validators.js b/test/validators.js index 23c3333ca..b6432d4b5 100644 --- a/test/validators.js +++ b/test/validators.js @@ -854,7 +854,7 @@ describe('Validators', function () { test({ validator: 'isDate' , valid: [ - //NOTE: null pass as well in the regular function, but fails in the test suite + //NOTE: null passes as well in the regular function, but fails in the test suite '2011-08-04' , '2011-09-30' , '04. 08. 2011.' From 2a6b4bd0160ab020e0be09a77260a6bfc1688462 Mon Sep 17 00:00:00 2001 From: ravestack Date: Mon, 5 Oct 2015 02:56:47 -0400 Subject: [PATCH 4/6] add RFC 2822 tests, enforce double digits in matching --- test/validators.js | 26 ++++++++++++++++++++++++-- validator.js | 2 +- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/test/validators.js b/test/validators.js index b6432d4b5..8f352534d 100644 --- a/test/validators.js +++ b/test/validators.js @@ -854,7 +854,7 @@ describe('Validators', function () { test({ validator: 'isDate' , valid: [ - //NOTE: null passes as well in the regular function, but fails in the test suite + // NOTE: null passes as well in the regular function, but fails in the test suite '2011-08-04' , '2011-09-30' , '04. 08. 2011.' @@ -874,7 +874,7 @@ describe('Validators', function () { , new Date() , 'Mon Aug 17 2015 00:24:56 GMT-0500 (CDT)' , '2/22/23 23:24:26' - //valid ISO 8601 dates below + // valid ISO 8601 dates below , '2009-12T12:34' , '2009' , '2009-05-19' @@ -895,6 +895,25 @@ describe('Validators', function () { , '2009-' , '2009-05-19 14:' , '200912-01' + // RFC 2882 tests below borrowed from the timerep package in Hackage: + // https://hackage.haskell.org/package/timerep-1.0.3/docs/src/Data-Time-RFC2822.html + , 'Fri, 21 Nov 1997 09:55:06 -0600' + , 'Tue, 15 Nov 1994 12:45:26 GMT' + , 'Tue, 1 Jul 2003 10:52:37 +0200' + , 'Thu, 13 Feb 1969 23:32:54 -0330' + , 'Mon, 24 Nov 1997 14:22:01 -0800' + , 'Thu, 13\n Feb\n 1969\n 23:32\n -0330' + , 'Thu, 13\n Feb\n 1969\n 23:32\n -0330 (Newfoundland Time)' + ,'24 Nov 1997 14:22:01 -0800' + // slight variations of the above with end-of-month + , 'Thu, 29\n Feb\n 1968\n 23:32\n -0330' + , 'Fri, 30 Nov 1997 09:55:06 -0600' + // more RFC 2882 tests borrowed from libgit2: + // https://github.com/libgit2/libgit2/blob/master/tests/date/rfc2822.c + , 'Wed, 10 Apr 2014 08:21:03 +0000' + , 'Wed, 9 Apr 2014 10:21:03 +0200' + , 'Wed, 9 Apr 2014 06:21:03 -0200' + , 'Wed, 9 Apr 2014 08:21:03 +0000' ] , invalid: [ 'foo' @@ -927,6 +946,9 @@ describe('Validators', function () { , '2010-02-18T16,25:23:48,444' , '2009-02-30 14:' , '200912-32' + // hackage RFC2822 variants with invalid end-of-month + , 'Thu, 29\n Feb\n 1969\n 23:32\n -0330' + , 'Fri, 31 Nov 1997 09:55:06 -0600' ] }); }); diff --git a/validator.js b/validator.js index ac2c3f5dd..4f61a3e14 100644 --- a/validator.js +++ b/validator.js @@ -481,7 +481,7 @@ //check for valid double digits that could be late days //check for all matches since a string like '12/23' is a valid date //ignore everything with nearby colons - dayOrYearMatches = str.match(/(^|[^:])[23]\d([^:\d]|$)/g); + dayOrYearMatches = str.match(/(^|[^:\d])[23]\d([^:\d]|$)/g); if (!dayOrYearMatches) { return true; } From ae32dfc5fe19786518b935aa03241bf63c36ed5b Mon Sep 17 00:00:00 2001 From: ravestack Date: Mon, 5 Oct 2015 03:01:16 -0400 Subject: [PATCH 5/6] remove string check --- validator.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/validator.js b/validator.js index 4f61a3e14..47aa336c9 100644 --- a/validator.js +++ b/validator.js @@ -475,9 +475,6 @@ if (isNaN(Date.parse(normalizedDate))) { return false; } - if (typeof str !== 'string') { - return true; //if Date.parse() passes, it's the current time - } //check for valid double digits that could be late days //check for all matches since a string like '12/23' is a valid date //ignore everything with nearby colons From eddbd0f952626357176c4904849c81eecfad3fd4 Mon Sep 17 00:00:00 2001 From: ravestack Date: Mon, 5 Oct 2015 09:14:29 +0200 Subject: [PATCH 6/6] change test to always have a valid date regardless of timezone, remove extraneous comment --- test/validators.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/test/validators.js b/test/validators.js index 8f352534d..cf6c6b007 100644 --- a/test/validators.js +++ b/test/validators.js @@ -854,7 +854,6 @@ describe('Validators', function () { test({ validator: 'isDate' , valid: [ - // NOTE: null passes as well in the regular function, but fails in the test suite '2011-08-04' , '2011-09-30' , '04. 08. 2011.' @@ -906,7 +905,7 @@ describe('Validators', function () { , 'Thu, 13\n Feb\n 1969\n 23:32\n -0330 (Newfoundland Time)' ,'24 Nov 1997 14:22:01 -0800' // slight variations of the above with end-of-month - , 'Thu, 29\n Feb\n 1968\n 23:32\n -0330' + , 'Thu, 29\n Feb\n 1968\n 13:32\n -0330' , 'Fri, 30 Nov 1997 09:55:06 -0600' // more RFC 2882 tests borrowed from libgit2: // https://github.com/libgit2/libgit2/blob/master/tests/date/rfc2822.c @@ -947,7 +946,7 @@ describe('Validators', function () { , '2009-02-30 14:' , '200912-32' // hackage RFC2822 variants with invalid end-of-month - , 'Thu, 29\n Feb\n 1969\n 23:32\n -0330' + , 'Thu, 29\n Feb\n 1969\n 13:32\n -0330' , 'Fri, 31 Nov 1997 09:55:06 -0600' ] });