Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: extra validation for dates #910

Merged
merged 2 commits into from
Oct 15, 2018
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ Validator | Description
**isISBN(str [, version])** | check if the string is an ISBN (version 10 or 13).
**isISSN(str [, options])** | check if the string is an [ISSN](https://en.wikipedia.org/wiki/International_Standard_Serial_Number).<br/><br/>`options` is an object which defaults to `{ case_sensitive: false, require_hyphen: false }`. If `case_sensitive` is true, ISSNs with a lowercase `'x'` as the check digit are rejected.
**isISIN(str)** | check if the string is an [ISIN][ISIN] (stock/security identifier).
**isISO8601(str)** | check if the string is a valid [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) date.
**isISO8601(str)** | check if the string is a valid [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) date; with additional checks for valid dates, e.g. invalidates dates like `2009-02-29`.
**isRFC3339(str)** | check if the string is a valid [RFC 3339](https://tools.ietf.org/html/rfc3339) date.
**isISO31661Alpha2(str)** | check if the string is a valid [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) officially assigned country code.
**isISO31661Alpha3(str)** | check if the string is a valid [ISO 3166-1 alpha-3](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3) officially assigned country code.
Expand Down
26 changes: 24 additions & 2 deletions lib/isISO8601.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,33 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de

/* eslint-disable max-len */
// from http://goo.gl/0ejHHW
var iso8601 = /^([\+-]?\d{4}(?!\d{2}\b))((-?)((0[1-9]|1[0-2])(\3([12]\d|0[1-9]|3[01]))?|W([0-4]\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\d|[12]\d{2}|3([0-5]\d|6[1-6])))([T\s]((([01]\d|2[0-3])((:?)[0-5]\d)?|24:?00)([\.,]\d+(?!:))?)?(\17[0-5]\d([\.,]\d+)?)?([zZ]|([\+-])([01]\d|2[0-3]):?([0-5]\d)?)?)?)?$/;
var iso8601 = /^([\+-]?\d{4}(?!\d{2}\b))((-?)((0[1-9]|1[0-2])(\3([12]\d|0[1-9]|3[01]))?|W([0-4]\d|5[0-3])(-?[1-7])?|(00[1-9]|0[1-9]\d|[12]\d{2}|3([0-5]\d|6[1-6])))([T\s]((([01]\d|2[0-3])((:?)[0-5]\d)?|24:?00)([\.,]\d+(?!:))?)?(\17[0-5]\d([\.,]\d+)?)?([zZ]|([\+-])([01]\d|2[0-3]):?([0-5]\d)?)?)?)?$/;
/* eslint-enable max-len */
var isValidDate = function isValidDate(str) {
// str must have passed the ISO8601 check
// this check is meant to catch invalid dates
// like 2009-02-31
// note: we choose not to validate the time part
var match = str.match(/(\d{4})-?(\d{0,2})-?(\d{0,2})/).map(Number);
var year = match[1];
var month = match[2];
var day = match[3];
// create a date object and compare
var d = new Date(year + '-' + (month || 1) + '-' + (day || 1));
if (isNaN(d.getFullYear())) return false;
if (month && day) {
return d.getFullYear() === year && d.getMonth() + 1 === month && d.getDate() === day;
}
return true;
};

function isISO8601(str) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : { strict: true };

(0, _assertString2.default)(str);
return iso8601.test(str);
var check = iso8601.test(str);
if (!options) return check;
if (check && options.strict) return isValidDate(str);
return check;
}
module.exports = exports['default'];
28 changes: 25 additions & 3 deletions src/lib/isISO8601.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,32 @@ import assertString from './util/assertString';

/* eslint-disable max-len */
// from http://goo.gl/0ejHHW
const iso8601 = /^([\+-]?\d{4}(?!\d{2}\b))((-?)((0[1-9]|1[0-2])(\3([12]\d|0[1-9]|3[01]))?|W([0-4]\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\d|[12]\d{2}|3([0-5]\d|6[1-6])))([T\s]((([01]\d|2[0-3])((:?)[0-5]\d)?|24:?00)([\.,]\d+(?!:))?)?(\17[0-5]\d([\.,]\d+)?)?([zZ]|([\+-])([01]\d|2[0-3]):?([0-5]\d)?)?)?)?$/;
const iso8601 = /^([\+-]?\d{4}(?!\d{2}\b))((-?)((0[1-9]|1[0-2])(\3([12]\d|0[1-9]|3[01]))?|W([0-4]\d|5[0-3])(-?[1-7])?|(00[1-9]|0[1-9]\d|[12]\d{2}|3([0-5]\d|6[1-6])))([T\s]((([01]\d|2[0-3])((:?)[0-5]\d)?|24:?00)([\.,]\d+(?!:))?)?(\17[0-5]\d([\.,]\d+)?)?([zZ]|([\+-])([01]\d|2[0-3]):?([0-5]\d)?)?)?)?$/;
/* eslint-enable max-len */
const isValidDate = (str) => {
// str must have passed the ISO8601 check
// this check is meant to catch invalid dates
// like 2009-02-31
// note: we choose not to validate the time part
const match = str.match(/(\d{4})-?(\d{0,2})-?(\d{0,2})/).map(Number);
const year = match[1];
const month = match[2];
const day = match[3];
// create a date object and compare
const d = new Date(`${year}-${month || 1}-${day || 1}`);
if (isNaN(d.getFullYear())) return false;
if (month && day) {
return d.getFullYear() === year
&& (d.getMonth() + 1) === month
&& d.getDate() === day;
}
return true;
};

export default function isISO8601(str) {
export default function isISO8601(str, options = { strict: true }) {
assertString(str);
return iso8601.test(str);
const check = iso8601.test(str);
if (!options) return check;
if (check && options.strict) return isValidDate(str);
return check;
}
7 changes: 5 additions & 2 deletions test/validators.js
Original file line number Diff line number Diff line change
Expand Up @@ -5513,7 +5513,7 @@ describe('Validators', () => {
'2009123',
'2009-05',
'2009-123',
'2009-222',
// '2009-222', // invalid test-case, implies 2009-22-2
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@chriso - I also found 2 invalid test cases in the cause of raising this PR, which I commented out. Let me know if this looks okay with you.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a valid ordinal date. The 222 indicates that it's 222 days into the year.

'2009-001',
'2009-W01-1',
'2009-W51-1',
Expand All @@ -5528,7 +5528,7 @@ describe('Validators', () => {
'2009-05-19T14:39Z',
'2009-W21-2',
'2009-W21-2T01:22',
'2009-139',
// '2009-139', // invalid test-case, implies 2009-13-9
'2009-05-19 14:39:22-06:00',
'2009-05-19 14:39:22+0600',
'2009-05-19 14:39:22-01',
Expand Down Expand Up @@ -5570,6 +5570,9 @@ describe('Validators', () => {
'2009-05-19 14.5.44',
'2010-02-18T16:23.33.600',
'2010-02-18T16,25:23:48,444',
'2010-13-1',
'2010-02-30',
'2009-02-29',
],
});
});
Expand Down
26 changes: 24 additions & 2 deletions validator.js
Original file line number Diff line number Diff line change
Expand Up @@ -1305,12 +1305,34 @@ function isCurrency(str, options) {

/* eslint-disable max-len */
// from http://goo.gl/0ejHHW
var iso8601 = /^([\+-]?\d{4}(?!\d{2}\b))((-?)((0[1-9]|1[0-2])(\3([12]\d|0[1-9]|3[01]))?|W([0-4]\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\d|[12]\d{2}|3([0-5]\d|6[1-6])))([T\s]((([01]\d|2[0-3])((:?)[0-5]\d)?|24:?00)([\.,]\d+(?!:))?)?(\17[0-5]\d([\.,]\d+)?)?([zZ]|([\+-])([01]\d|2[0-3]):?([0-5]\d)?)?)?)?$/;
var iso8601 = /^([\+-]?\d{4}(?!\d{2}\b))((-?)((0[1-9]|1[0-2])(\3([12]\d|0[1-9]|3[01]))?|W([0-4]\d|5[0-3])(-?[1-7])?|(00[1-9]|0[1-9]\d|[12]\d{2}|3([0-5]\d|6[1-6])))([T\s]((([01]\d|2[0-3])((:?)[0-5]\d)?|24:?00)([\.,]\d+(?!:))?)?(\17[0-5]\d([\.,]\d+)?)?([zZ]|([\+-])([01]\d|2[0-3]):?([0-5]\d)?)?)?)?$/;
/* eslint-enable max-len */
var isValidDate = function isValidDate(str) {
// str must have passed the ISO8601 check
// this check is meant to catch invalid dates
// like 2009-02-31
// note: we choose not to validate the time part
var match = str.match(/(\d{4})-?(\d{0,2})-?(\d{0,2})/).map(Number);
var year = match[1];
var month = match[2];
var day = match[3];
// create a date object and compare
var d = new Date(year + '-' + (month || 1) + '-' + (day || 1));
if (isNaN(d.getFullYear())) return false;
if (month && day) {
return d.getFullYear() === year && d.getMonth() + 1 === month && d.getDate() === day;
}
return true;
};

function isISO8601(str) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : { strict: true };

assertString(str);
return iso8601.test(str);
var check = iso8601.test(str);
if (!options) return check;
if (check && options.strict) return isValidDate(str);
return check;
}

/* Based on https://tools.ietf.org/html/rfc3339#section-5.6 */
Expand Down
2 changes: 1 addition & 1 deletion validator.min.js

Large diffs are not rendered by default.