Skip to content

Commit

Permalink
Normative: Isolate ISO 8601 month consistency validation
Browse files Browse the repository at this point in the history
Fixes tc39#2497
  • Loading branch information
gibson042 committed Feb 19, 2023
1 parent f5420b9 commit 8a27072
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 27 deletions.
58 changes: 31 additions & 27 deletions spec/calendar.html
Original file line number Diff line number Diff line change
Expand Up @@ -714,29 +714,35 @@ <h1>
</emu-alg>
</emu-clause>

<emu-clause id="sec-temporal-resolveisomonth" aoid="ResolveISOMonth">
<h1>ResolveISOMonth ( _fields_ )</h1>
<p>
The abstract operation ResolveISOMonth merges the `month` and `monthCode` properties of the given _fields_ Object into an integer month, and validates that they match.
It returns the integer month.
</p>
<emu-clause id="sec-temporal-resolveisomonth" type="abstract operation">
<h1>
ISOResolveMonth (
_fields_: an Object,
): either a normal completion containing ~unused~ or a throw completion
</h1>
<dl class="header">
<dt>description</dt>
<dd>It validates that the *"month"* and *"monthCode"* properties of the given _fields_ are not inconsistent and merges them into a *"month"* property with an integral Number value, or throws an exception of both are *undefined*.</dd>
</dl>
<emu-alg>
1. Assert: _fields_ is an ordinary object with no more and no less than the own data properties listed in <emu-xref href="#table-temporal-field-requirements"></emu-xref>.
1. Assert: _fields_ is an ordinary Object that is not directly observable from ECMAScript code and for which the value of the [[Prototype]] internal slot is *null* and every property is a data property whose value is a primitive value.
1. Let _month_ be ! Get(_fields_, *"month"*).
1. Assert: _month_ is *undefined* or _month_ is a Number.
1. Let _monthCode_ be ! Get(_fields_, *"monthCode"*).
1. If _monthCode_ is *undefined*, then
1. If _month_ is *undefined*, throw a *TypeError* exception.
1. Return ℝ(_month_).
1. Assert: Type(_monthCode_) is String.
1. Return ~unused~.
1. Assert: _monthCode_ is a String.
1. NOTE: The ISO 8601 calendar does not include leap months.
1. If the length of _monthCode_ is not 3, throw a *RangeError* exception.
1. If the first code unit of _monthCode_ is not 0x004D (LATIN CAPITAL LETTER M), throw a *RangeError* exception.
1. Let _monthCodeDigits_ be the substring of _monthCode_ from 1.
1. If ParseText(StringToCodePoints(_monthCodeDigits_), |DateMonth|) is a List of errors, throw a *RangeError* exception.
1. Let _monthCodeNumber_ be ! ToIntegerOrInfinity(_monthCodeDigits_).
1. Assert: SameValue(_monthCode_, ISOMonthCode(_monthCodeNumber_)) is *true*.
1. If _month_ is not *undefined* and SameValue(_month_, _monthCodeNumber_) is *false*, throw a *RangeError* exception.
1. Return _monthCodeNumber_.
1. Perform ! Set(_fields_, *"month"*, 𝔽(_monthCodeNumber_), *false*).
1. Return ~unused~.
</emu-alg>
</emu-clause>

Expand All @@ -749,11 +755,10 @@ <h1>ISODateFromFields ( _fields_, _overflow_ )</h1>
1. Assert: Type(_fields_) is Object.
1. Assert: _overflow_ is either *"constrain"* or *"reject"*.
1. Let _year_ be ! Get(_fields_, *"year"*).
1. Assert: Type(_year_) is Number.
1. Let _month_ be ? ResolveISOMonth(_fields_).
1. Let _month_ be ! Get(_fields_, *"month"*).
1. Let _day_ be ! Get(_fields_, *"day"*).
1. Assert: Type(_day_) is Number.
1. Return ? RegulateISODate(ℝ(_year_), _month_, ℝ(_day_), _overflow_).
1. Assert: _year_, _month_, and _day_ are all Numbers.
1. Return ? RegulateISODate(ℝ(_year_), ℝ(_month_), ℝ(_day_), _overflow_).
</emu-alg>
</emu-clause>

Expand All @@ -767,9 +772,9 @@ <h1>ISOYearMonthFromFields ( _fields_, _overflow_ )</h1>
1. Assert: Type(_fields_) is Object.
1. Assert: _overflow_ is either *"constrain"* or *"reject"*.
1. Let _year_ be ! Get(_fields_, *"year"*).
1. Assert: Type(_year_) is Number.
1. Let _month_ be ? ResolveISOMonth(_fields_).
1. Let _result_ be ? RegulateISOYearMonth(ℝ(_year_), _month_, _overflow_).
1. Let _month_ be ! Get(_fields_, *"month"*).
1. Assert: _year_ and _month_ are Numbers.
1. Let _result_ be ? RegulateISOYearMonth(ℝ(_year_), ℝ(_month_), _overflow_).
1. Return the Record {
[[Year]]: _result_.[[Year]],
[[Month]]: _result_.[[Month]],
Expand All @@ -787,19 +792,15 @@ <h1>ISOMonthDayFromFields ( _fields_, _overflow_ )</h1>
1. Assert: Type(_fields_) is Object.
1. Assert: _overflow_ is either *"constrain"* or *"reject"*.
1. Let _month_ be ! Get(_fields_, *"month"*).
1. Let _monthCode_ be ! Get(_fields_, *"monthCode"*).
1. Let _year_ be ! Get(_fields_, *"year"*).
1. If _month_ is not *undefined*, and _monthCode_ and _year_ are both *undefined*, then
1. Throw a *TypeError* exception.
1. Set _month_ to ? ResolveISOMonth(_fields_).
1. Let _day_ be ! Get(_fields_, *"day"*).
1. Assert: Type(_day_) is Number.
1. Assert: _month_ and _day_ are Numbers.
1. Let _year_ be ! Get(_fields_, *"year"*).
1. Let _referenceISOYear_ be 1972 (the first leap year after the Unix epoch).
1. If _monthCode_ is *undefined*, then
1. Assert: Type(_year_) is Number.
1. Let _result_ be ? RegulateISODate(ℝ(_year_), _month_, ℝ(_day_), _overflow_).
1. If _year_ is *undefined*, then
1. Let _result_ be ? RegulateISODate(_referenceISOYear_, ℝ(_month_), ℝ(_day_), _overflow_).
1. Else,
1. Let _result_ be ? RegulateISODate(_referenceISOYear_, _month_, ℝ(_day_), _overflow_).
1. Assert: _year_ is a Number.
1. Let _result_ be ? RegulateISODate(ℝ(_year_), ℝ(_month_), ℝ(_day_), _overflow_).
1. Return the Record {
[[Month]]: _result_.[[Month]],
[[Day]]: _result_.[[Day]],
Expand Down Expand Up @@ -991,6 +992,7 @@ <h1>Temporal.Calendar.prototype.dateFromFields ( _fields_ [ , _options_ ] )</h1>
1. Set _options_ to ? GetOptionsObject(_options_).
1. Set _fields_ to ? PrepareTemporalFields(_fields_, « *"day"*, *"month"*, *"monthCode"*, *"year"* », « *"year"*, *"day"* »).
1. Let _overflow_ be ? ToTemporalOverflow(_options_).
1. Perform ? ISOResolveMonth(_fields_).
1. Let _result_ be ? ISODateFromFields(_fields_, _overflow_).
1. Return ? CreateTemporalDate(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]], _calendar_).
</emu-alg>
Expand All @@ -1013,6 +1015,7 @@ <h1>Temporal.Calendar.prototype.yearMonthFromFields ( _fields_ [ , _options_ ] )
1. Set _options_ to ? GetOptionsObject(_options_).
1. Set _fields_ to ? PrepareTemporalFields(_fields_, « *"month"*, *"monthCode"*, *"year"* », « *"year"* »).
1. Let _overflow_ be ? ToTemporalOverflow(_options_).
1. Perform ? ISOResolveMonth(_fields_).
1. Let _result_ be ? ISOYearMonthFromFields(_fields_, _overflow_).
1. Return ? CreateTemporalYearMonth(_result_.[[Year]], _result_.[[Month]], _calendar_, _result_.[[ReferenceISODay]]).
</emu-alg>
Expand All @@ -1035,6 +1038,7 @@ <h1>Temporal.Calendar.prototype.monthDayFromFields ( _fields_ [ , _options_ ] )<
1. Set _options_ to ? GetOptionsObject(_options_).
1. Set _fields_ to ? PrepareTemporalFields(_fields_, « *"day"*, *"month"*, *"monthCode"*, *"year"* », « *"day"* »).
1. Let _overflow_ be ? ToTemporalOverflow(_options_).
1. Perform ? ISOResolveMonth(_fields_).
1. Let _result_ be ? ISOMonthDayFromFields(_fields_, _overflow_).
1. Return ? CreateTemporalMonthDay(_result_.[[Month]], _result_.[[Day]], _calendar_, _result_.[[ReferenceISOYear]]).
</emu-alg>
Expand Down
3 changes: 3 additions & 0 deletions spec/intl.html
Original file line number Diff line number Diff line change
Expand Up @@ -1820,6 +1820,7 @@ <h1>Temporal.Calendar.prototype.dateFromFields ( _fields_ [ , _options_ ] )</h1>
1. Set _fields_ to ? PrepareTemporalFields(_fields_, _fieldNames_, « »).
1. Let _overflow_ be ? ToTemporalOverflow(_options_).
1. If _calendar_.[[Identifier]] is *"iso8601"*, then
1. Perform ? ISOResolveMonth(_fields_).
1. Let _result_ be ? ISODateFromFields(_fields_, _overflow_).
1. Else,
1. Perform ? CalendarResolveFields(_calendar_.[[Identifier]], _fields_, ~date~).
Expand Down Expand Up @@ -1849,6 +1850,7 @@ <h1>Temporal.Calendar.prototype.yearMonthFromFields ( _fields_ [ , _options_ ] )
1. Perform ! CreateDataPropertyOrThrow(_fields_, *"day"*, 𝔽(_firstDayIndex_)).
1. Let _overflow_ be ? ToTemporalOverflow(_options_).
1. If _calendar_.[[Identifier]] is *"iso8601"*, then
1. Perform ? ISOResolveMonth(_fields_).
1. Let _result_ be ? ISOYearMonthFromFields(_fields_, _overflow_).
1. Else,
1. Perform ? CalendarResolveFields(_calendar_.[[Identifier]], _fields_, ~year-month~).
Expand Down Expand Up @@ -1877,6 +1879,7 @@ <h1>Temporal.Calendar.prototype.monthDayFromFields ( _fields_ [ , _options_ ] )<
1. Set _fields_ to ? PrepareTemporalFields(_fields_, _fieldNames_, « »).
1. Let _overflow_ be ? ToTemporalOverflow(_options_).
1. If _calendar_.[[Identifier]] is *"iso8601"*, then
1. Perform ? ISOResolveMonth(_fields_).
1. Let _result_ be ? ISOMonthDayFromFields(_fields_, _overflow_).
1. Else,
1. Perform ? CalendarResolveFields(_calendar_.[[Identifier]], _fields_, ~month-day~).
Expand Down

0 comments on commit 8a27072

Please sign in to comment.