Skip to content

Commit

Permalink
Merge pull request #447 from chriso/chriso/rfc2822-timezones
Browse files Browse the repository at this point in the history
Handle RFC 2822 timezones in isDate()
  • Loading branch information
chriso committed Oct 27, 2015
2 parents 6bde552 + c1cd6ae commit d7058d3
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 31 deletions.
5 changes: 5 additions & 0 deletions test/validators.js
Original file line number Diff line number Diff line change
Expand Up @@ -907,6 +907,11 @@ describe('Validators', function () {
, 'Tue, 1 Jul 2003 10:52:37 +0200'
, 'Thu, 13 Feb 1969 23:32:54 -0330'
, 'Mon, 24 Nov 1997 14:22:01 -0800'
, 'Mon Sep 28 1964 00:05:49 GMT+1100 (AEDST)'
, 'Mon Sep 28 1964 00:05:49 +1100 (AEDST)'
, 'Mon Sep 28 1964 00:05:49 +1100'
, 'Mon Sep 28 1964 00:05:49 \nGMT\n+1100\n'
, 'Mon Sep 28 1964 00:05:49 \nGMT\n+1100\n(AEDST)'
, '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'
Expand Down
76 changes: 46 additions & 30 deletions validator.js
Original file line number Diff line number Diff line change
Expand Up @@ -471,40 +471,60 @@
};

function getTimezoneOffset(str) {
var iso8601Parts = str.match(iso8601);
var iso8601Parts = str.match(iso8601)
, timezone, sign, hours, minutes;
if (!iso8601Parts) {
return new Date().getTimezoneOffset();
}
var timezone = iso8601Parts[21];
if (!timezone || timezone === 'z' || timezone === 'Z') {
return 0;
}
var sign = iso8601Parts[22], hours, minutes;
if (timezone.indexOf(':') !== -1) {
hours = parseInt(iso8601Parts[23]);
minutes = parseInt(iso8601Parts[24]);
str = str.toLowerCase();
timezone = str.match(/(?:\s|gmt\s*)(-|\+)(\d{1,4})(\s|$)/);
if (!timezone) {
return str.indexOf('gmt') !== -1 ? 0 : null;
}
sign = timezone[1];
var offset = timezone[2];
if (offset.length === 3) {
offset = '0' + offset;
}
if (offset.length <= 2) {
hours = 0;
minutes = parseInt(offset);
} else {
hours = parseInt(offset.slice(0, 2));
minutes = parseInt(offset.slice(2, 4));
}
} else {
hours = 0;
minutes = parseInt(iso8601Parts[23]);
timezone = iso8601Parts[21];
if (!timezone || timezone === 'z' || timezone === 'Z') {
return 0;
}
sign = iso8601Parts[22];
if (timezone.indexOf(':') !== -1) {
hours = parseInt(iso8601Parts[23]);
minutes = parseInt(iso8601Parts[24]);
} else {
hours = 0;
minutes = parseInt(iso8601Parts[23]);
}
}
return (hours * 60 + minutes) * (sign === '-' ? 1 : -1);
}

validator.isDate = function (str) {
var normalizedDate = new Date((new Date(str)).toUTCString());
var utcDay = String(normalizedDate.getUTCDate());
var normalizedDate = new Date(Date.parse(str));
if (isNaN(normalizedDate)) {
return false;
}
// normalizedDate is in the user's timezone. Apply the input
// timezone offset to the date so that the year and day match
// the input
var timezoneDifference = normalizedDate.getTimezoneOffset() -
getTimezoneOffset(str);
normalizedDate = new Date(normalizedDate.getTime() +
60000 * timezoneDifference);
var regularDay = String(normalizedDate.getDate());
var timezoneOffset = getTimezoneOffset(str);
if (timezoneOffset !== null) {
var timezoneDifference = normalizedDate.getTimezoneOffset() -
timezoneOffset;
normalizedDate = new Date(normalizedDate.getTime() +
60000 * timezoneDifference);
}
var day = String(normalizedDate.getDate());
var dayOrYear, dayOrYearMatches, year;
if (isNaN(Date.parse(normalizedDate))) {
return false;
}
//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
Expand All @@ -516,16 +536,12 @@
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) {
if (dayOrYear === day || dayOrYear === year) {
return true;
} else if ((dayOrYear === (regularDay + '/' + year)) || (dayOrYear === (year + '/' + regularDay))) {
} else if ((dayOrYear === (day + '/' + year)) || (dayOrYear === (year + '/' + day))) {
return true;
} else if ((dayOrYear === (utcDay + '/' + year)) || (dayOrYear === (year + '/' + utcDay))) {
return true;
} else {
return false;
}
return false;
};

validator.isAfter = function (str, date) {
Expand Down
Loading

0 comments on commit d7058d3

Please sign in to comment.