Skip to content

Commit d7058d3

Browse files
committed
Merge pull request #447 from chriso/chriso/rfc2822-timezones
Handle RFC 2822 timezones in isDate()
2 parents 6bde552 + c1cd6ae commit d7058d3

File tree

3 files changed

+52
-31
lines changed

3 files changed

+52
-31
lines changed

test/validators.js

+5
Original file line numberDiff line numberDiff line change
@@ -907,6 +907,11 @@ describe('Validators', function () {
907907
, 'Tue, 1 Jul 2003 10:52:37 +0200'
908908
, 'Thu, 13 Feb 1969 23:32:54 -0330'
909909
, 'Mon, 24 Nov 1997 14:22:01 -0800'
910+
, 'Mon Sep 28 1964 00:05:49 GMT+1100 (AEDST)'
911+
, 'Mon Sep 28 1964 00:05:49 +1100 (AEDST)'
912+
, 'Mon Sep 28 1964 00:05:49 +1100'
913+
, 'Mon Sep 28 1964 00:05:49 \nGMT\n+1100\n'
914+
, 'Mon Sep 28 1964 00:05:49 \nGMT\n+1100\n(AEDST)'
910915
, 'Thu, 13\n Feb\n 1969\n 23:32\n -0330'
911916
, 'Thu, 13\n Feb\n 1969\n 23:32\n -0330 (Newfoundland Time)'
912917
,'24 Nov 1997 14:22:01 -0800'

validator.js

+46-30
Original file line numberDiff line numberDiff line change
@@ -471,40 +471,60 @@
471471
};
472472

473473
function getTimezoneOffset(str) {
474-
var iso8601Parts = str.match(iso8601);
474+
var iso8601Parts = str.match(iso8601)
475+
, timezone, sign, hours, minutes;
475476
if (!iso8601Parts) {
476-
return new Date().getTimezoneOffset();
477-
}
478-
var timezone = iso8601Parts[21];
479-
if (!timezone || timezone === 'z' || timezone === 'Z') {
480-
return 0;
481-
}
482-
var sign = iso8601Parts[22], hours, minutes;
483-
if (timezone.indexOf(':') !== -1) {
484-
hours = parseInt(iso8601Parts[23]);
485-
minutes = parseInt(iso8601Parts[24]);
477+
str = str.toLowerCase();
478+
timezone = str.match(/(?:\s|gmt\s*)(-|\+)(\d{1,4})(\s|$)/);
479+
if (!timezone) {
480+
return str.indexOf('gmt') !== -1 ? 0 : null;
481+
}
482+
sign = timezone[1];
483+
var offset = timezone[2];
484+
if (offset.length === 3) {
485+
offset = '0' + offset;
486+
}
487+
if (offset.length <= 2) {
488+
hours = 0;
489+
minutes = parseInt(offset);
490+
} else {
491+
hours = parseInt(offset.slice(0, 2));
492+
minutes = parseInt(offset.slice(2, 4));
493+
}
486494
} else {
487-
hours = 0;
488-
minutes = parseInt(iso8601Parts[23]);
495+
timezone = iso8601Parts[21];
496+
if (!timezone || timezone === 'z' || timezone === 'Z') {
497+
return 0;
498+
}
499+
sign = iso8601Parts[22];
500+
if (timezone.indexOf(':') !== -1) {
501+
hours = parseInt(iso8601Parts[23]);
502+
minutes = parseInt(iso8601Parts[24]);
503+
} else {
504+
hours = 0;
505+
minutes = parseInt(iso8601Parts[23]);
506+
}
489507
}
490508
return (hours * 60 + minutes) * (sign === '-' ? 1 : -1);
491509
}
492510

493511
validator.isDate = function (str) {
494-
var normalizedDate = new Date((new Date(str)).toUTCString());
495-
var utcDay = String(normalizedDate.getUTCDate());
512+
var normalizedDate = new Date(Date.parse(str));
513+
if (isNaN(normalizedDate)) {
514+
return false;
515+
}
496516
// normalizedDate is in the user's timezone. Apply the input
497517
// timezone offset to the date so that the year and day match
498518
// the input
499-
var timezoneDifference = normalizedDate.getTimezoneOffset() -
500-
getTimezoneOffset(str);
501-
normalizedDate = new Date(normalizedDate.getTime() +
502-
60000 * timezoneDifference);
503-
var regularDay = String(normalizedDate.getDate());
519+
var timezoneOffset = getTimezoneOffset(str);
520+
if (timezoneOffset !== null) {
521+
var timezoneDifference = normalizedDate.getTimezoneOffset() -
522+
timezoneOffset;
523+
normalizedDate = new Date(normalizedDate.getTime() +
524+
60000 * timezoneDifference);
525+
}
526+
var day = String(normalizedDate.getDate());
504527
var dayOrYear, dayOrYearMatches, year;
505-
if (isNaN(Date.parse(normalizedDate))) {
506-
return false;
507-
}
508528
//check for valid double digits that could be late days
509529
//check for all matches since a string like '12/23' is a valid date
510530
//ignore everything with nearby colons
@@ -516,16 +536,12 @@
516536
return digitString.match(/\d+/g)[0];
517537
}).join('/');
518538
year = String(normalizedDate.getFullYear()).slice(-2);
519-
//local date and UTC date can differ, but both are valid, so check agains both
520-
if (dayOrYear === regularDay || dayOrYear === utcDay || dayOrYear === year) {
539+
if (dayOrYear === day || dayOrYear === year) {
521540
return true;
522-
} else if ((dayOrYear === (regularDay + '/' + year)) || (dayOrYear === (year + '/' + regularDay))) {
541+
} else if ((dayOrYear === (day + '/' + year)) || (dayOrYear === (year + '/' + day))) {
523542
return true;
524-
} else if ((dayOrYear === (utcDay + '/' + year)) || (dayOrYear === (year + '/' + utcDay))) {
525-
return true;
526-
} else {
527-
return false;
528543
}
544+
return false;
529545
};
530546

531547
validator.isAfter = function (str, date) {

0 commit comments

Comments
 (0)