Should `(ZonedDateTime|PlainDateTime|PlainDate|PlainYearMonth).from` throw for object representing non-existent date?
lionel-rowe opened this issue · 2 comments
February 2020 has 29 days, so February 31 doesn't exist.
When parsing from a string, this throws as expected:
Temporal.ZonedDateTime.from('2020-02-31T00:00:00+00:00[UTC]')
// Uncaught RangeError: value out of range: 1 <= 31 <= 29
But when constructing the same date from a plain object, the polyfill simply "best-guesses" it to Feb 29, without throwing:
Temporal.ZonedDateTime.from({ year: 2020, month: 2, day: 31, hour: 0, minute: 0, second: 0, timeZone: 'UTC' })
// Temporal.ZonedDateTime <2020-02-29T00:00:00+00:00[UTC]>
The same issue also applies to PlainDate
, PlainDateTime
, and PlainYearMonth
.
Is this correct?
This is handled by the overflow
option in the from
methods:
overflow
(string): How to deal with out-of-range values if thing is an object. Allowed values are'constrain'
and'reject'
. The default is'constrain'
.
Temporal.ZonedDateTime.from(
{ year: 2020, month: 2, day: 31, hour: 0, minute: 0, second: 0, timeZone: 'UTC' }
);
// Temporal.ZonedDateTime <2020-02-29T00:00:00+00:00[UTC]>
Temporal.ZonedDateTime.from(
{ year: 2020, month: 2, day: 31, hour: 0, minute: 0, second: 0, timeZone: 'UTC' },
{ overflow: 'reject' }
);
// Uncaught RangeError: value out of range: 1 <= 31 <= 29
There's an issue in the tc39/proposal-temporal repo which I can't find at the moment, which discusses this — I admit it's slightly inconsistent that objects and strings are treated differently here. The thinking goes, "2020-02-31" is a syntactically invalid string according to ISO 8601, and will never be generated by any other application that outputs valid ISO 8601 strings, so it's always rejected. A property bag { year: 2020, month: 2, day: 31 }
is not intrinsically invalid, so it can be subject to this sort of preprocessing given by the overflow
option.