summaryrefslogtreecommitdiff
path: root/date-fns/src/parseISO
diff options
context:
space:
mode:
authorSebastian <sebasjm@gmail.com>2021-08-23 16:46:06 -0300
committerSebastian <sebasjm@gmail.com>2021-08-23 16:48:30 -0300
commit38acabfa6089ab8ac469c12b5f55022fb96935e5 (patch)
tree453dbf70000cc5e338b06201af1eaca8343f8f73 /date-fns/src/parseISO
parentf26125e039143b92dc0d84e7775f508ab0cdcaa8 (diff)
downloadnode-vendor-master.tar.gz
node-vendor-master.tar.bz2
node-vendor-master.zip
added web vendorsHEADmaster
Diffstat (limited to 'date-fns/src/parseISO')
-rw-r--r--date-fns/src/parseISO/benchmark.js16
-rw-r--r--date-fns/src/parseISO/index.d.ts4
-rw-r--r--date-fns/src/parseISO/index.js343
-rw-r--r--date-fns/src/parseISO/index.js.flow57
-rw-r--r--date-fns/src/parseISO/test.js452
5 files changed, 872 insertions, 0 deletions
diff --git a/date-fns/src/parseISO/benchmark.js b/date-fns/src/parseISO/benchmark.js
new file mode 100644
index 0000000..19405ed
--- /dev/null
+++ b/date-fns/src/parseISO/benchmark.js
@@ -0,0 +1,16 @@
+// @flow
+/* eslint-env mocha */
+/* global suite, benchmark */
+
+import parseISO from '.'
+import moment from 'moment'
+
+suite('toDate', function() {
+ benchmark('date-fns', function() {
+ return parseISO('2014-10-25T13:46:20+07:00')
+ })
+
+ benchmark('Moment.js', function() {
+ return moment('2014-10-25T13:46:20+07:00')
+ })
+})
diff --git a/date-fns/src/parseISO/index.d.ts b/date-fns/src/parseISO/index.d.ts
new file mode 100644
index 0000000..ee06fe6
--- /dev/null
+++ b/date-fns/src/parseISO/index.d.ts
@@ -0,0 +1,4 @@
+// This file is generated automatically by `scripts/build/typings.js`. Please, don't change it.
+
+import { parseISO } from 'date-fns'
+export default parseISO
diff --git a/date-fns/src/parseISO/index.js b/date-fns/src/parseISO/index.js
new file mode 100644
index 0000000..4d4a0af
--- /dev/null
+++ b/date-fns/src/parseISO/index.js
@@ -0,0 +1,343 @@
+import toInteger from '../_lib/toInteger/index'
+import requiredArgs from '../_lib/requiredArgs/index'
+
+var MILLISECONDS_IN_HOUR = 3600000
+var MILLISECONDS_IN_MINUTE = 60000
+var DEFAULT_ADDITIONAL_DIGITS = 2
+
+var patterns = {
+ dateTimeDelimiter: /[T ]/,
+ timeZoneDelimiter: /[Z ]/i,
+ timezone: /([Z+-].*)$/,
+}
+
+var dateRegex = /^-?(?:(\d{3})|(\d{2})(?:-?(\d{2}))?|W(\d{2})(?:-?(\d{1}))?|)$/
+var timeRegex = /^(\d{2}(?:[.,]\d*)?)(?::?(\d{2}(?:[.,]\d*)?))?(?::?(\d{2}(?:[.,]\d*)?))?$/
+var timezoneRegex = /^([+-])(\d{2})(?::?(\d{2}))?$/
+
+/**
+ * @name parseISO
+ * @category Common Helpers
+ * @summary Parse ISO string
+ *
+ * @description
+ * Parse the given string in ISO 8601 format and return an instance of Date.
+ *
+ * Function accepts complete ISO 8601 formats as well as partial implementations.
+ * ISO 8601: http://en.wikipedia.org/wiki/ISO_8601
+ *
+ * If the argument isn't a string, the function cannot parse the string or
+ * the values are invalid, it returns Invalid Date.
+ *
+ * ### v2.0.0 breaking changes:
+ *
+ * - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
+ *
+ * - The previous `parse` implementation was renamed to `parseISO`.
+ *
+ * ```javascript
+ * // Before v2.0.0
+ * parse('2016-01-01')
+ *
+ * // v2.0.0 onward
+ * parseISO('2016-01-01')
+ * ```
+ *
+ * - `parseISO` now validates separate date and time values in ISO-8601 strings
+ * and returns `Invalid Date` if the date is invalid.
+ *
+ * ```javascript
+ * parseISO('2018-13-32')
+ * //=> Invalid Date
+ * ```
+ *
+ * - `parseISO` now doesn't fall back to `new Date` constructor
+ * if it fails to parse a string argument. Instead, it returns `Invalid Date`.
+ *
+ * @param {String} argument - the value to convert
+ * @param {Object} [options] - an object with options.
+ * @param {0|1|2} [options.additionalDigits=2] - the additional number of digits in the extended year format
+ * @returns {Date} the parsed date in the local time zone
+ * @throws {TypeError} 1 argument required
+ * @throws {RangeError} `options.additionalDigits` must be 0, 1 or 2
+ *
+ * @example
+ * // Convert string '2014-02-11T11:30:30' to date:
+ * var result = parseISO('2014-02-11T11:30:30')
+ * //=> Tue Feb 11 2014 11:30:30
+ *
+ * @example
+ * // Convert string '+02014101' to date,
+ * // if the additional number of digits in the extended year format is 1:
+ * var result = parseISO('+02014101', { additionalDigits: 1 })
+ * //=> Fri Apr 11 2014 00:00:00
+ */
+export default function parseISO(argument, dirtyOptions) {
+ requiredArgs(1, arguments)
+
+ var options = dirtyOptions || {}
+
+ var additionalDigits =
+ options.additionalDigits == null
+ ? DEFAULT_ADDITIONAL_DIGITS
+ : toInteger(options.additionalDigits)
+ if (
+ additionalDigits !== 2 &&
+ additionalDigits !== 1 &&
+ additionalDigits !== 0
+ ) {
+ throw new RangeError('additionalDigits must be 0, 1 or 2')
+ }
+
+ if (
+ !(
+ typeof argument === 'string' ||
+ Object.prototype.toString.call(argument) === '[object String]'
+ )
+ ) {
+ return new Date(NaN)
+ }
+
+ var dateStrings = splitDateString(argument)
+
+ var date
+ if (dateStrings.date) {
+ var parseYearResult = parseYear(dateStrings.date, additionalDigits)
+ date = parseDate(parseYearResult.restDateString, parseYearResult.year)
+ }
+
+ if (isNaN(date) || !date) {
+ return new Date(NaN)
+ }
+
+ var timestamp = date.getTime()
+ var time = 0
+ var offset
+
+ if (dateStrings.time) {
+ time = parseTime(dateStrings.time)
+ if (isNaN(time) || time === null) {
+ return new Date(NaN)
+ }
+ }
+
+ if (dateStrings.timezone) {
+ offset = parseTimezone(dateStrings.timezone)
+ if (isNaN(offset)) {
+ return new Date(NaN)
+ }
+ } else {
+ var dirtyDate = new Date(timestamp + time)
+ // js parsed string assuming it's in UTC timezone
+ // but we need it to be parsed in our timezone
+ // so we use utc values to build date in our timezone.
+ // Year values from 0 to 99 map to the years 1900 to 1999
+ // so set year explicitly with setFullYear.
+ var result = new Date(0)
+ result.setFullYear(
+ dirtyDate.getUTCFullYear(),
+ dirtyDate.getUTCMonth(),
+ dirtyDate.getUTCDate()
+ )
+ result.setHours(
+ dirtyDate.getUTCHours(),
+ dirtyDate.getUTCMinutes(),
+ dirtyDate.getUTCSeconds(),
+ dirtyDate.getUTCMilliseconds()
+ )
+ return result
+ }
+
+ return new Date(timestamp + time + offset)
+}
+
+function splitDateString(dateString) {
+ var dateStrings = {}
+ var array = dateString.split(patterns.dateTimeDelimiter)
+ var timeString
+
+ // The regex match should only return at maximum two array elements.
+ // [date], [time], or [date, time].
+ if (array.length > 2) {
+ return dateStrings
+ }
+
+ if (/:/.test(array[0])) {
+ dateStrings.date = null
+ timeString = array[0]
+ } else {
+ dateStrings.date = array[0]
+ timeString = array[1]
+ if (patterns.timeZoneDelimiter.test(dateStrings.date)) {
+ dateStrings.date = dateString.split(patterns.timeZoneDelimiter)[0]
+ timeString = dateString.substr(dateStrings.date.length, dateString.length)
+ }
+ }
+
+ if (timeString) {
+ var token = patterns.timezone.exec(timeString)
+ if (token) {
+ dateStrings.time = timeString.replace(token[1], '')
+ dateStrings.timezone = token[1]
+ } else {
+ dateStrings.time = timeString
+ }
+ }
+
+ return dateStrings
+}
+
+function parseYear(dateString, additionalDigits) {
+ var regex = new RegExp(
+ '^(?:(\\d{4}|[+-]\\d{' +
+ (4 + additionalDigits) +
+ '})|(\\d{2}|[+-]\\d{' +
+ (2 + additionalDigits) +
+ '})$)'
+ )
+
+ var captures = dateString.match(regex)
+ // Invalid ISO-formatted year
+ if (!captures) return { year: null }
+
+ var year = captures[1] && parseInt(captures[1])
+ var century = captures[2] && parseInt(captures[2])
+
+ return {
+ year: century == null ? year : century * 100,
+ restDateString: dateString.slice((captures[1] || captures[2]).length),
+ }
+}
+
+function parseDate(dateString, year) {
+ // Invalid ISO-formatted year
+ if (year === null) return null
+
+ var captures = dateString.match(dateRegex)
+ // Invalid ISO-formatted string
+ if (!captures) return null
+
+ var isWeekDate = !!captures[4]
+ var dayOfYear = parseDateUnit(captures[1])
+ var month = parseDateUnit(captures[2]) - 1
+ var day = parseDateUnit(captures[3])
+ var week = parseDateUnit(captures[4])
+ var dayOfWeek = parseDateUnit(captures[5]) - 1
+
+ if (isWeekDate) {
+ if (!validateWeekDate(year, week, dayOfWeek)) {
+ return new Date(NaN)
+ }
+ return dayOfISOWeekYear(year, week, dayOfWeek)
+ } else {
+ var date = new Date(0)
+ if (
+ !validateDate(year, month, day) ||
+ !validateDayOfYearDate(year, dayOfYear)
+ ) {
+ return new Date(NaN)
+ }
+ date.setUTCFullYear(year, month, Math.max(dayOfYear, day))
+ return date
+ }
+}
+
+function parseDateUnit(value) {
+ return value ? parseInt(value) : 1
+}
+
+function parseTime(timeString) {
+ var captures = timeString.match(timeRegex)
+ if (!captures) return null // Invalid ISO-formatted time
+
+ var hours = parseTimeUnit(captures[1])
+ var minutes = parseTimeUnit(captures[2])
+ var seconds = parseTimeUnit(captures[3])
+
+ if (!validateTime(hours, minutes, seconds)) {
+ return NaN
+ }
+
+ return (
+ hours * MILLISECONDS_IN_HOUR +
+ minutes * MILLISECONDS_IN_MINUTE +
+ seconds * 1000
+ )
+}
+
+function parseTimeUnit(value) {
+ return (value && parseFloat(value.replace(',', '.'))) || 0
+}
+
+function parseTimezone(timezoneString) {
+ if (timezoneString === 'Z') return 0
+
+ var captures = timezoneString.match(timezoneRegex)
+ if (!captures) return 0
+
+ var sign = captures[1] === '+' ? -1 : 1
+ var hours = parseInt(captures[2])
+ var minutes = (captures[3] && parseInt(captures[3])) || 0
+
+ if (!validateTimezone(hours, minutes)) {
+ return NaN
+ }
+
+ return (
+ sign * (hours * MILLISECONDS_IN_HOUR + minutes * MILLISECONDS_IN_MINUTE)
+ )
+}
+
+function dayOfISOWeekYear(isoWeekYear, week, day) {
+ var date = new Date(0)
+ date.setUTCFullYear(isoWeekYear, 0, 4)
+ var fourthOfJanuaryDay = date.getUTCDay() || 7
+ var diff = (week - 1) * 7 + day + 1 - fourthOfJanuaryDay
+ date.setUTCDate(date.getUTCDate() + diff)
+ return date
+}
+
+// Validation functions
+
+// February is null to handle the leap year (using ||)
+var daysInMonths = [31, null, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
+
+function isLeapYearIndex(year) {
+ return year % 400 === 0 || (year % 4 === 0 && year % 100)
+}
+
+function validateDate(year, month, date) {
+ return (
+ month >= 0 &&
+ month <= 11 &&
+ date >= 1 &&
+ date <= (daysInMonths[month] || (isLeapYearIndex(year) ? 29 : 28))
+ )
+}
+
+function validateDayOfYearDate(year, dayOfYear) {
+ return dayOfYear >= 1 && dayOfYear <= (isLeapYearIndex(year) ? 366 : 365)
+}
+
+function validateWeekDate(_year, week, day) {
+ return week >= 1 && week <= 53 && day >= 0 && day <= 6
+}
+
+function validateTime(hours, minutes, seconds) {
+ if (hours === 24) {
+ return minutes === 0 && seconds === 0
+ }
+
+ return (
+ seconds >= 0 &&
+ seconds < 60 &&
+ minutes >= 0 &&
+ minutes < 60 &&
+ hours >= 0 &&
+ hours < 25
+ )
+}
+
+function validateTimezone(_hours, minutes) {
+ return minutes >= 0 && minutes <= 59
+}
diff --git a/date-fns/src/parseISO/index.js.flow b/date-fns/src/parseISO/index.js.flow
new file mode 100644
index 0000000..951a222
--- /dev/null
+++ b/date-fns/src/parseISO/index.js.flow
@@ -0,0 +1,57 @@
+// @flow
+// This file is generated automatically by `scripts/build/typings.js`. Please, don't change it.
+
+export type Interval = {
+ start: Date | number,
+ end: Date | number,
+}
+
+export type Locale = {
+ code?: string,
+ formatDistance?: (...args: Array<any>) => any,
+ formatRelative?: (...args: Array<any>) => any,
+ localize?: {
+ ordinalNumber: (...args: Array<any>) => any,
+ era: (...args: Array<any>) => any,
+ quarter: (...args: Array<any>) => any,
+ month: (...args: Array<any>) => any,
+ day: (...args: Array<any>) => any,
+ dayPeriod: (...args: Array<any>) => any,
+ },
+ formatLong?: {
+ date: (...args: Array<any>) => any,
+ time: (...args: Array<any>) => any,
+ dateTime: (...args: Array<any>) => any,
+ },
+ match?: {
+ ordinalNumber: (...args: Array<any>) => any,
+ era: (...args: Array<any>) => any,
+ quarter: (...args: Array<any>) => any,
+ month: (...args: Array<any>) => any,
+ day: (...args: Array<any>) => any,
+ dayPeriod: (...args: Array<any>) => any,
+ },
+ options?: {
+ weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6,
+ firstWeekContainsDate?: 1 | 2 | 3 | 4 | 5 | 6 | 7,
+ },
+}
+
+export type Duration = {
+ years?: number,
+ months?: number,
+ weeks?: number,
+ days?: number,
+ hours?: number,
+ minutes?: number,
+ seconds?: number,
+}
+
+export type Day = 0 | 1 | 2 | 3 | 4 | 5 | 6
+
+declare module.exports: (
+ argument: string,
+ options?: {
+ additionalDigits?: 0 | 1 | 2,
+ }
+) => Date
diff --git a/date-fns/src/parseISO/test.js b/date-fns/src/parseISO/test.js
new file mode 100644
index 0000000..36a8a90
--- /dev/null
+++ b/date-fns/src/parseISO/test.js
@@ -0,0 +1,452 @@
+// @flow
+/* eslint-env mocha */
+
+import assert from 'power-assert'
+import parseISO from '.'
+
+describe('parseISO', () => {
+ describe('string argument', () => {
+ describe('centuries', () => {
+ it('parses YY', () => {
+ const result = parseISO('20')
+ assert.deepEqual(result, new Date(2000, 0 /* Jan */, 1))
+ })
+ })
+
+ describe('years', () => {
+ it('parses YYYY', () => {
+ const result = parseISO('2014')
+ assert.deepEqual(result, new Date(2014, 0 /* Jan */, 1))
+ })
+ })
+
+ describe('months', () => {
+ it('parses YYYY-MM', () => {
+ const result = parseISO('2014-02')
+ assert.deepEqual(result, new Date(2014, 1 /* Feb */, 1))
+ })
+ })
+
+ describe('weeks', () => {
+ it('parses YYYY-Www', () => {
+ const result = parseISO('2014-W02')
+ assert.deepEqual(result, new Date(2014, 0 /* Jan */, 6))
+ })
+
+ it('parses YYYYWww', () => {
+ const result = parseISO('2014W02')
+ assert.deepEqual(result, new Date(2014, 0 /* Jan */, 6))
+ })
+ })
+
+ describe('calendar dates', () => {
+ it('parses YYYY-MM-DD', () => {
+ const result = parseISO('2014-02-11')
+ assert.deepEqual(result, new Date(2014, 1, /* Feb */ 11))
+ })
+
+ it('parses YYYYMMDD', () => {
+ const result = parseISO('20140211')
+ assert.deepEqual(result, new Date(2014, 1 /* Feb */, 11))
+ })
+ })
+
+ describe('week dates', () => {
+ it('parses YYYY-Www-D', () => {
+ const result = parseISO('2014-W02-7')
+ assert.deepEqual(result, new Date(2014, 0 /* Jan */, 12))
+ })
+
+ it('parses YYYYWwwD', () => {
+ const result = parseISO('2014W027')
+ assert.deepEqual(result, new Date(2014, 0 /* Jan */, 12))
+ })
+
+ it('correctly handles years in which 4 January is Sunday', () => {
+ const result = parseISO('2009-W01-1')
+ assert.deepEqual(result, new Date(2008, 11 /* Dec */, 29))
+ })
+ })
+
+ describe('ordinal dates', () => {
+ it('parses YYYY-DDD', () => {
+ const result = parseISO('2014-026')
+ assert.deepEqual(result, new Date(2014, 0 /* Jan */, 26))
+ })
+
+ it('parses YYYYDDD', () => {
+ const result = parseISO('2014026')
+ assert.deepEqual(result, new Date(2014, 0 /* Jan */, 26))
+ })
+ })
+
+ describe('date and time combined', () => {
+ it('parses YYYY-MM-DDThh:mm', () => {
+ const result = parseISO('2014-02-11T11:30')
+ assert.deepEqual(result, new Date(2014, 1 /* Feb */, 11, 11, 30))
+ })
+
+ it('parses YYYY-MM-DDThhmm', () => {
+ const result = parseISO('2014-02-11T1130')
+ assert.deepEqual(result, new Date(2014, 1 /* Feb */, 11, 11, 30))
+ })
+ })
+
+ describe('extended century representation', () => {
+ it('parses century 101 BC - 2 BC', () => {
+ const result = parseISO('-0001')
+ const date = new Date(0)
+ date.setFullYear(-100, 0 /* Jan */, 1)
+ date.setHours(0, 0, 0, 0)
+ assert.deepEqual(result, date)
+ })
+
+ it('parses century 1 BC - 99 AD', () => {
+ const result = parseISO('00')
+ const date = new Date(0)
+ date.setFullYear(0, 0 /* Jan */, 1)
+ date.setHours(0, 0, 0, 0)
+ assert.deepEqual(result, date)
+ })
+
+ it('parses centuries after 9999 AD', () => {
+ const result = parseISO('+0123')
+ assert.deepEqual(result, new Date(12300, 0 /* Jan */, 1))
+ })
+
+ it('allows to specify the number of additional digits', () => {
+ const result = parseISO('-20', { additionalDigits: 0 })
+ const date = new Date(0)
+ date.setFullYear(-2000, 0 /* Jan */, 1)
+ date.setHours(0, 0, 0, 0)
+ assert.deepEqual(result, date)
+ })
+ })
+
+ describe('extended year representation', () => {
+ it('correctly parses years from 1 AD to 99 AD', () => {
+ const result = parseISO('0095-07-02')
+ const date = new Date(0)
+ date.setFullYear(95, 6 /* Jul */, 2)
+ date.setHours(0, 0, 0, 0)
+ assert.deepEqual(result, date)
+ })
+
+ it('parses years after 9999 AD', () => {
+ const result = parseISO('+012345-07-02')
+ assert.deepEqual(result, new Date(12345, 6 /* Jul */, 2))
+ })
+
+ it('allows to specify the number of additional digits', () => {
+ const result = parseISO('+12340702', { additionalDigits: 0 })
+ assert.deepEqual(result, new Date(1234, 6 /* Jul */, 2))
+ })
+
+ it('parses year 1 BC', () => {
+ const result = parseISO('0000-07-02')
+ const date = new Date(0)
+ date.setFullYear(0, 6 /* Jul */, 2)
+ date.setHours(0, 0, 0, 0)
+ assert.deepEqual(result, date)
+ })
+
+ it('parses years less than 1 BC', () => {
+ const result = parseISO('-000001-07-02')
+ const date = new Date(0)
+ date.setFullYear(-1, 6 /* Jul */, 2)
+ date.setHours(0, 0, 0, 0)
+ assert.deepEqual(result, date)
+ })
+ })
+
+ describe('float time', () => {
+ it('parses float hours', () => {
+ const result = parseISO('2014-02-11T11.5')
+ assert.deepEqual(result, new Date(2014, 1 /* Feb */, 11, 11, 30))
+ })
+
+ it('parses float minutes', () => {
+ const result = parseISO('2014-02-11T11:30.5')
+ assert.deepEqual(result, new Date(2014, 1 /* Feb */, 11, 11, 30, 30))
+ })
+
+ it('parses float seconds', () => {
+ const result = parseISO('2014-02-11T11:30:30.768')
+ assert.deepEqual(
+ result,
+ new Date(2014, 1 /* Feb */, 11, 11, 30, 30, 768)
+ )
+ })
+
+ it('parses , as decimal mark', () => {
+ const result = parseISO('2014-02-11T11,5')
+ assert.deepEqual(result, new Date(2014, 1 /* Feb */, 11, 11, 30))
+ })
+ })
+
+ describe('timezones', () => {
+ describe('when the date and the time are specified', () => {
+ it('parses Z', () => {
+ const result = parseISO('2014-10-25T06:46:20Z')
+ assert.deepEqual(result, new Date('2014-10-25T13:46:20+07:00'))
+ })
+
+ it('parses ±hh:mm', () => {
+ const result = parseISO('2014-10-25T13:46:20+07:00')
+ assert.deepEqual(result, new Date('2014-10-25T13:46:20+07:00'))
+ })
+
+ it('parses ±hhmm', () => {
+ const result = parseISO('2014-10-25T03:46:20-0300')
+ assert.deepEqual(result, new Date('2014-10-25T13:46:20+07:00'))
+ })
+
+ it('parses ±hh', () => {
+ const result = parseISO('2014-10-25T13:46:20+07')
+ assert.deepEqual(result, new Date('2014-10-25T13:46:20+07:00'))
+ })
+ })
+ describe('when the year and the month are specified', () => {
+ it('sets timezone correctly on yyyy-MMZ format', () => {
+ const result = parseISO('2012-01Z')
+ assert.deepEqual(result, new Date('2012-01-01T00:00:00+00:00'))
+ })
+ })
+ })
+
+ describe('failure', () => {
+ it('returns `Invalid Date` if the string is not an ISO formatted date', () => {
+ const result = parseISO(new Date(2014, 8 /* Sep */, 1, 11).toString())
+ assert(result instanceof Date)
+ assert(isNaN(result))
+ })
+ })
+ })
+
+ describe('validation', () => {
+ describe('months', () => {
+ it('returns `Invalid Date` for invalid month', () => {
+ const result = parseISO('2014-00')
+ assert(result instanceof Date)
+ assert(isNaN(result))
+ })
+ })
+
+ describe('weeks', () => {
+ it('returns `Invalid Date` for invalid week', () => {
+ const result = parseISO('2014-W00')
+ assert(result instanceof Date)
+ assert(isNaN(result))
+ })
+
+ it('returns `Invalid Date` for 54th week', () => {
+ const result = parseISO('2014-W54')
+ assert(result instanceof Date)
+ assert(isNaN(result))
+ })
+ })
+
+ describe('calendar dates', () => {
+ it('returns `Invalid Date` for invalid day of the month', () => {
+ const result = parseISO('2012-02-30')
+ assert(result instanceof Date)
+ assert(isNaN(result))
+ })
+
+ it('returns `Invalid Date` for 29th of February of non-leap year', () => {
+ const result = parseISO('2014-02-29')
+ assert(result instanceof Date)
+ assert(isNaN(result))
+ })
+
+ it('parses 29th of February of leap year', () => {
+ const result = parseISO('2012-02-29')
+ assert.deepEqual(result, new Date(2012, 1, /* Feb */ 29))
+ })
+ })
+
+ describe('week dates', () => {
+ it('returns `Invalid Date` for invalid day of the week', () => {
+ const result = parseISO('2014-W02-0')
+ assert(result instanceof Date)
+ assert(isNaN(result))
+ })
+ })
+
+ describe('ordinal dates', () => {
+ it('returns `Invalid Date` for invalid day of the year', () => {
+ const result = parseISO('2012-000')
+ assert(result instanceof Date)
+ assert(isNaN(result))
+ })
+
+ it('returns `Invalid Date` for 366th day of non-leap year', () => {
+ const result = parseISO('2014-366')
+ assert(result instanceof Date)
+ assert(isNaN(result))
+ })
+
+ it('parses 366th day of leap year', () => {
+ const result = parseISO('2012-366')
+ assert.deepEqual(result, new Date(2012, 11, /* Dec */ 31))
+ })
+ })
+
+ describe('date', () => {
+ it('returns `Invalid Date` when it contains spaces after the date', () => {
+ const result = parseISO('2014-02-11 basketball')
+ assert(result instanceof Date)
+ assert(isNaN(result))
+ })
+ })
+
+ describe('time', () => {
+ it('parses 24:00 as midnight of the next day', () => {
+ const result = parseISO('2014-02-11T24:00')
+ assert.deepEqual(result, new Date(2014, 1 /* Feb */, 12, 0, 0))
+ })
+
+ it('returns `Invalid Date` for anything after 24:00', () => {
+ const result = parseISO('2014-02-11T24:01')
+ assert(result instanceof Date)
+ assert(isNaN(result))
+ })
+
+ it('returns `Invalid Date` for invalid hours', () => {
+ const result = parseISO('2014-02-11T25')
+ assert(result instanceof Date)
+ assert(isNaN(result))
+ })
+
+ it('returns `Invalid Date` for invalid minutes', () => {
+ const result = parseISO('2014-02-11T21:60')
+ assert(result instanceof Date)
+ assert(isNaN(result))
+ })
+
+ it('returns `Invalid Date` for invalid seconds', () => {
+ const result = parseISO('2014-02-11T21:59:60')
+ assert(result instanceof Date)
+ assert(isNaN(result))
+ })
+
+ it('returns `Invalid Date` for invalid time', () => {
+ const result = parseISO('2014-02-11T21:basketball')
+ assert(result instanceof Date)
+ assert(isNaN(result))
+ })
+
+ it('returns `Invalid Date` when it contains spaces after the time', () => {
+ const result = parseISO('2014-02-11T21:59:00 basketball')
+ assert(result instanceof Date)
+ assert(isNaN(result))
+ })
+ })
+
+ describe('timezones', () => {
+ it('returns `Invalid Date` for invalid timezone minutes', () => {
+ const result = parseISO('2014-02-11T21:35:45+04:60')
+ assert(result instanceof Date)
+ assert(isNaN(result))
+ })
+ })
+ })
+
+ describe('invalid argument', () => {
+ it('returns Invalid Date for date argument', () => {
+ // $ExpectedMistake
+ const date = new Date(2016, 0, 1)
+ const result = parseISO(date)
+ assert(result instanceof Date)
+ assert(isNaN(result))
+ })
+
+ it('returns Invalid Date for timestamp argument', () => {
+ const timestamp = new Date(2016, 0, 1, 23, 30, 45, 123).getTime()
+ // $ExpectedMistake
+ const result = parseISO(timestamp)
+ assert(result instanceof Date)
+ assert(isNaN(result))
+ })
+
+ it('returns Invalid Date if argument is non-date string', () => {
+ const result = parseISO('abc')
+ assert(result instanceof Date)
+ assert(isNaN(result))
+ })
+
+ it('returns Invalid Date if argument is non-date string containing a colon', () => {
+ const result = parseISO('00:00')
+ assert(result instanceof Date)
+ assert(isNaN(result))
+ })
+
+ it('returns Invalid Date if argument is NaN', () => {
+ // $ExpectedMistake
+ const result = parseISO(NaN)
+ assert(result instanceof Date)
+ assert(isNaN(result))
+ })
+
+ it('returns Invalid Date if argument is Invalid Date', () => {
+ // $ExpectedMistake
+ const result = parseISO(new Date(NaN))
+ assert(result instanceof Date)
+ assert(isNaN(result))
+ })
+
+ it('returns Invalid Date if argument is null', () => {
+ // $ExpectedMistake
+ const result = parseISO(null)
+ assert(result instanceof Date)
+ assert(isNaN(result))
+ })
+
+ it('returns Invalid Date if argument is undefined', () => {
+ // $ExpectedMistake
+ const result = parseISO(undefined)
+ assert(result instanceof Date)
+ assert(isNaN(result))
+ })
+
+ it('returns Invalid Date if argument is false', () => {
+ // $ExpectedMistake
+ const result = parseISO(false)
+ assert(result instanceof Date)
+ assert(isNaN(result))
+ })
+
+ it('returns Invalid Date if argument is true', () => {
+ // $ExpectedMistake
+ const result = parseISO(true)
+ assert(result instanceof Date)
+ assert(isNaN(result))
+ })
+ })
+
+ describe('argument conversion', () => {
+ it('implicitly converts instance of String into a string', () => {
+ // eslint-disable-next-line no-new-wrappers
+ const dateString = new String('2014-02-11')
+ // $ExpectedMistake
+ const result = parseISO(dateString)
+ assert.deepEqual(result, new Date(2014, 1, /* Feb */ 11))
+ })
+
+ it('implicitly converts options', () => {
+ // $ExpectedMistake
+ const result = parseISO('+12340702', { additionalDigits: '0' })
+ assert.deepEqual(result, new Date(1234, 6 /* Jul */, 2))
+ })
+
+ it('throws `RangeError` if `options.additionalDigits` is not convertable to 0, 1, 2 or undefined`', () => {
+ // $ExpectedMistake
+ const block = parseISO.bind(null, '+12340702', { additionalDigits: 3 })
+ assert.throws(block, RangeError)
+ })
+ })
+
+ it('throws TypeError exception if passed less than 1 argument', () => {
+ assert.throws(parseISO.bind(null), TypeError)
+ })
+})