Skip to content

Commit

Permalink
fix*isISO8601): add strictSeparator option (#1486)
Browse files Browse the repository at this point in the history
  • Loading branch information
joestone51 committed Nov 24, 2020
1 parent 13c0129 commit 55ca773
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 14 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ Validator | Description
**isIPRange(str)** | check if the string is an IP Range(version 4 only).
**isISBN(str [, version])** | check if the string is an ISBN (version 10 or 13).
**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; for additional checks for valid dates, e.g. invalidates dates like `2009-02-29`, pass `options` object as a second parameter with `options.strict = true`.
**isISO8601(str)** | check if the string is a valid [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) date. <br/>`options` is an object which defaults to `{ strict: false, strictSeparator: false }`. If `strict` is true, date strings with invalid dates like `2009-02-29` will be invalid. If `strictSeparator` is true, date strings with date and time separated by anything other than a T will be invalid.
**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.
**isISRC(str)** | check if the string is a [ISRC](https://en.wikipedia.org/wiki/International_Standard_Recording_Code).
Expand Down
7 changes: 4 additions & 3 deletions src/lib/isISO8601.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ 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-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)?)?)?)?$/;
// same as above, except with a strict 'T' separator between date and time
const iso8601StrictSeparator = /^([\+-]?\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]((([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
Expand Down Expand Up @@ -34,10 +36,9 @@ const isValidDate = (str) => {
return true;
};

export default function isISO8601(str, options) {
export default function isISO8601(str, options = {}) {
assertString(str);
const check = iso8601.test(str);
if (!options) return check;
const check = options.strictSeparator ? iso8601StrictSeparator.test(str) : iso8601.test(str);
if (check && options.strict) return isValidDate(str);
return check;
}
107 changes: 107 additions & 0 deletions test/validators.js
Original file line number Diff line number Diff line change
Expand Up @@ -8542,6 +8542,113 @@ describe('Validators', () => {
});
});

it('should validate ISO 8601 dates, with strictSeparator = true', () => {
test({
validator: 'isISO8601',
args: [
{ strictSeparator: true },
],
valid: [
'2009-12T12:34',
'2009',
'2009-05-19',
'2009-05-19',
'20090519',
'2009123',
'2009-05',
'2009-123',
'2009-222',
'2009-001',
'2009-W01-1',
'2009-W51-1',
'2009-W511',
'2009-W33',
'2009W511',
'2009-05-19',
'2009-05-19T14:39Z',
'2009-W21-2',
'2009-W21-2T01:22',
'2009-139',
'20090621T0545Z',
'2007-04-06T00:00',
'2007-04-05T24:00',
'2010-02-18T16:23:48.5',
'2010-02-18T16:23:48,444',
'2010-02-18T16:23:48,3-06:00',
'2010-02-18T16:23.4',
'2010-02-18T16:23,25',
'2010-02-18T16:23.33+0600',
'2010-02-18T16.23334444',
'2010-02-18T16,2283',
'2009-10-10',
'2020-366',
'2000-366',
],
invalid: [
'200905',
'2009367',
'2009-',
'2007-04-05T24:50',
'2009-000',
'2009-M511',
'2009M511',
'2009-05-19T14a39r',
'2009-05-19T14:3924',
'2009-0519',
'2009-05-1914:39',
'2009-05-19 14:',
'2009-05-19r14:39',
'2009-05-19 14a39a22',
'200912-01',
'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',
'2010-13-1',
'2009-05-19 00:00',
// Previously valid cases
'2009-05-19 14',
'2009-05-19 14:31',
'2009-05-19 14:39:22',
'2009-05-19 14:39:22-06:00',
'2009-05-19 14:39:22+0600',
'2009-05-19 14:39:22-01',
],
});
});

it('should validate ISO 8601 dates, with strict = true and strictSeparator = true (regression)', () => {
test({
validator: 'isISO8601',
args: [
{ strict: true, strictSeparator: true },
],
valid: [
'2000-02-29',
'2009-123',
'2009-222',
'2020-366',
'2400-366',
],
invalid: [
'2010-02-30',
'2009-02-29',
'2009-366',
'2019-02-31',
'2009-05-19 14',
'2009-05-19 14:31',
'2009-05-19 14:39:22',
'2009-05-19 14:39:22-06:00',
'2009-05-19 14:39:22+0600',
'2009-05-19 14:39:22-01',
],
});
});

it('should validate RFC 3339 dates', () => {
test({
validator: 'isRFC3339',
Expand Down
20 changes: 11 additions & 9 deletions validator.js
Original file line number Diff line number Diff line change
Expand Up @@ -457,11 +457,7 @@ function isFQDN(str, options) {
return false; // reject numeric TLDs
}

if (options.allow_underscores) {
part = part.replace(/_/g, '');
}

if (!/^[a-z\u00a1-\uffff0-9-]+$/i.test(part)) {
if (!/^[a-z_\u00a1-\uffff0-9-]+$/i.test(part)) {
return false;
} // disallow full-width chars

Expand All @@ -473,6 +469,10 @@ function isFQDN(str, options) {
if (part[0] === '-' || part[part.length - 1] === '-') {
return false;
}

if (!options.allow_underscores && /_/.test(part)) {
return false;
}
}

return true;
Expand Down Expand Up @@ -2598,7 +2598,9 @@ function isBtcAddress(str) {
/* 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-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)?)?)?)?$/;
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)?)?)?)?$/; // same as above, except with a strict 'T' separator between date and time

var iso8601StrictSeparator = /^([\+-]?\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]((([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) {
Expand Down Expand Up @@ -2632,10 +2634,10 @@ var isValidDate = function isValidDate(str) {
return true;
};

function isISO8601(str, options) {
function isISO8601(str) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
assertString(str);
var check = iso8601.test(str);
if (!options) return check;
var check = options.strictSeparator ? iso8601StrictSeparator.test(str) : iso8601.test(str);
if (check && options.strict) return isValidDate(str);
return check;
}
Expand Down
2 changes: 1 addition & 1 deletion validator.min.js

Large diffs are not rendered by default.

0 comments on commit 55ca773

Please sign in to comment.