diff --git a/src/lib/isISO8601.js b/src/lib/isISO8601.js index 1f797347d..d3eda7e13 100644 --- a/src/lib/isISO8601.js +++ b/src/lib/isISO8601.js @@ -2,9 +2,11 @@ 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)?)?)?)?$/; +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)?)?)?)?$/; +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 @@ -16,29 +18,33 @@ const isValidDate = (str) => { const oYear = Number(ordinalMatch[1]); const oDay = Number(ordinalMatch[2]); // if is leap year - if ((oYear % 4 === 0 && oYear % 100 !== 0) || oYear % 400 === 0) return oDay <= 366; + if ((oYear % 4 === 0 && oYear % 100 !== 0) || oYear % 400 === 0) { return oDay <= 366; } return oDay <= 365; } const match = str.match(/(\d{4})-?(\d{0,2})-?(\d*)/).map(Number); const year = match[1]; const month = match[2]; const day = match[3]; - const monthString = month ? `0${month}`.slice(-2) : month; - const dayString = day ? `0${day}`.slice(-2) : day; + const monthString = month ? `${month}`.padStart(2, '0') : month; + const dayString = day ? `${day}`.padStart(2, '0') : day; + const yearString = year < 100 ? `${year}`.padStart(4, '0') : year; // create a date object and compare - const d = new Date(`${year}-${monthString || '01'}-${dayString || '01'}`); + const d = new Date(`${yearString}-${monthString || '01'}-${dayString || '01'}`); if (month && day) { - return d.getUTCFullYear() === year - && (d.getUTCMonth() + 1) === month - && d.getUTCDate() === day; + return ( + d.getUTCFullYear() === year && + d.getUTCMonth() + 1 === month && + d.getUTCDate() === day + ); } return true; }; - export default function isISO8601(str, options = {}) { assertString(str); - const check = options.strictSeparator ? iso8601StrictSeparator.test(str) : iso8601.test(str); + const check = options.strictSeparator + ? iso8601StrictSeparator.test(str) + : iso8601.test(str); if (check && options.strict) return isValidDate(str); return check; } diff --git a/test/validators.test.js b/test/validators.test.js index d0908ad12..6db0690f3 100644 --- a/test/validators.test.js +++ b/test/validators.test.js @@ -11924,6 +11924,9 @@ describe('Validators', () => { '2009-10-10', '2020-366', '2000-366', + '0080-05-19', + '0008-W51-1', + '0009-05-19T14:39Z', ]; const invalidISO8601 = [ @@ -11953,6 +11956,9 @@ describe('Validators', () => { '2010-13-1', 'nonsense2021-01-01T00:00:00Z', '2021-01-01T00:00:00Znonsense', + '0010-02-18T16:23.33.600', + '0200-02-18T16,25:23:48,444', + 'nonsense0021-01-01T00:00:00Z', ]; it('should validate ISO 8601 dates', () => { @@ -11987,6 +11993,8 @@ describe('Validators', () => { '2009-222', '2020-366', '2400-366', + '0050-02-15', + '0010-05-19T14:39Z', ], invalid: [ '2010-02-30', @@ -12038,6 +12046,10 @@ describe('Validators', () => { '2009-10-10', '2020-366', '2000-366', + '0010-02-18T16:23.4', + '0010-02-18T16:23,25', + '0200-02-18T16:23.33+0600', + '0200-02-18T16.23334444', ], invalid: [ '200905', @@ -12072,6 +12084,9 @@ describe('Validators', () => { '2009-05-19 14:39:22-06:00', '2009-05-19 14:39:22+0600', '2009-05-19 14:39:22-01', + '0009-05-19 14.5.44', + '0010-02-18T16:23.33.600', + '0010-02-18T16,25:23:48,444', ], }); }); @@ -12088,6 +12103,8 @@ describe('Validators', () => { '2009-222', '2020-366', '2400-366', + '0020-366', + '0400-366', ], invalid: [ '2010-02-30', @@ -12100,6 +12117,8 @@ describe('Validators', () => { '2009-05-19 14:39:22-06:00', '2009-05-19 14:39:22+0600', '2009-05-19 14:39:22-01', + '0009-05-19 14:39:22+0600', + '0009-05-19 14:39:22-01', ], }); });