Skip to content

Commit 6616a89

Browse files
sffcgibson042ptomato
authored
Editorial: Add and use additional MonthCode AOs, including in DateToISO (#73)
Co-authored-by: Richard Gibson <[email protected]> Co-authored-by: Philip Chimento <[email protected]>
1 parent e349341 commit 6616a89

File tree

2 files changed

+131
-14
lines changed

2 files changed

+131
-14
lines changed

biblio.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,16 @@
121121
"type": "op",
122122
"aoid": "ZeroDateDuration",
123123
"id": "sec-temporal-zerodateduration"
124+
},
125+
{
126+
"type": "op",
127+
"aoid": "ParseMonthCode",
128+
"id": "sec-temporal-parsemonthcode"
129+
},
130+
{
131+
"type": "op",
132+
"aoid": "CreateMonthCode",
133+
"id": "sec-temporal-createmonthcode"
124134
}
125135
]
126136
}

spec.emu

Lines changed: 121 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -533,36 +533,135 @@ contributors: Google, Ecma International
533533
<tr>
534534
<th>Calendar</th>
535535
<th>Additional Month Codes</th>
536+
<th>Leap to Common Month Transformation</th>
536537
</tr>
537538
</thead>
538539
<tr>
539540
<td>*"chinese"*</td>
540541
<td>*"M01L"*, *"M02L"*, *"M03L"*, *"M04L"*, *"M05L"*, *"M06L"*, *"M07L"*, *"M08L"*, *"M09L"*, *"M10L"*, *"M11L"*, *"M12L"*</td>
542+
<td>~skip-backward~</td>
541543
</tr>
542544
<tr>
543545
<td>*"coptic"*</td>
544546
<td>*"M13"*</td>
547+
<td></td>
545548
</tr>
546549
<tr>
547550
<td>*"dangi"*</td>
548551
<td>*"M01L"*, *"M02L"*, *"M03L"*, *"M04L"*, *"M05L"*, *"M06L"*, *"M07L"*, *"M08L"*, *"M09L"*, *"M10L"*, *"M11L"*, *"M12L"*</td>
552+
<td>~skip-backward~</td>
549553
</tr>
550554
<tr>
551555
<td>*"ethioaa"*</td>
552556
<td>*"M13"*</td>
557+
<td></td>
553558
</tr>
554559
<tr>
555560
<td>*"ethiopic"*</td>
556561
<td>*"M13"*</td>
562+
<td></td>
557563
</tr>
558564
<tr>
559565
<td>*"hebrew"*</td>
560566
<td>*"M05L"*</td>
567+
<td>~skip-forward~</td>
561568
</tr>
562569
</table>
563570
</emu-table>
564571
</emu-clause>
565572

573+
<emu-clause id="sec-temporal-yearcontainsmonthcode" type="implementation-defined abstract operation">
574+
<h1>
575+
YearContainsMonthCode (
576+
_calendar_: a calendar type that is not *"iso8601"*,
577+
_arithmeticYear_: an integer,
578+
_monthCode_: a month code,
579+
): a Boolean
580+
</h1>
581+
<dl class="header">
582+
<dt>description</dt>
583+
<dd>
584+
It returns whether the given _monthCode_ exists in _arithmeticYear_ of _calendar_.
585+
</dd>
586+
</dl>
587+
<p>It performs the following steps when called:</p>
588+
<emu-alg>
589+
1. Assert: IsValidMonthCodeForCalendar(_calendar_, _monthCode_) is *true*.
590+
1. If ! ParseMonthCode(_monthCode_).[[IsLeap]] is *false*, return *true*.
591+
1. Return whether the leap month indicated by _monthCode_ exists in the year _arithmeticYear_ in _calendar_, using calendar-dependent behaviour.
592+
</emu-alg>
593+
</emu-clause>
594+
595+
<emu-clause id="sec-temporal-constrainmonthcode" type="abstract operation">
596+
<h1>
597+
ConstrainMonthCode (
598+
_calendar_: a calendar type that is not *"iso8601"*,
599+
_arithmeticYear_: an integer,
600+
_monthCode_: a month code,
601+
_overflow_: ~constrain~ or ~reject~,
602+
): either a normal completion containing a month code or a throw completion
603+
</h1>
604+
<dl class="header">
605+
<dt>description</dt>
606+
<dd>
607+
It returns the month code in _arithmeticYear_ of _calendar_ that best matches the given _monthCode_. If _monthCode_ does not exist in _arithmeticYear_, it is constrained to the best common month if _overflow_ is ~constrain~, or an error is thrown if _overflow_ is ~reject~.
608+
</dd>
609+
</dl>
610+
<p>It performs the following steps when called:</p>
611+
<emu-alg>
612+
1. Assert: IsValidMonthCodeForCalendar(_calendar_, _monthCode_) is *true*.
613+
1. If YearContainsMonthCode(_calendar_, _arithmeticYear_, _monthCode_) is *true*, return _monthCode_.
614+
1. If _overflow_ is ~reject~, throw a *RangeError* exception.
615+
1. Assert: _calendar_ is listed in the Calendar column of <emu-xref href="#table-additional-month-codes"></emu-xref>.
616+
1. Let _r_ be the row in <emu-xref href="#table-additional-month-codes"></emu-xref> which the _calendar_ is in the Calendar column.
617+
1. Let _shiftType_ be the value given in the *"Leap to Common Month Transformation"* column of _r_.
618+
1. If _shiftType_ is ~skip-backward~, then
619+
1. Return CreateMonthCode(! ParseMonthCode(_monthCode_).[[MonthNumber]], *false*).
620+
1. Else,
621+
1. Assert: _monthCode_ is *"M05L"*.
622+
1. Return *"M06"*.
623+
</emu-alg>
624+
</emu-clause>
625+
626+
<emu-clause id="sec-temporal-monthcodetoordinal" type="abstract operation">
627+
<h1>
628+
MonthCodeToOrdinal (
629+
_calendar_: a calendar type that is not *"iso8601"*,
630+
_arithmeticYear_: an integer,
631+
_monthCode_: a month code,
632+
): an integer
633+
</h1>
634+
<dl class="header">
635+
<dt>description</dt>
636+
<dd>
637+
It returns the ordinal month number for _monthCode_ in _arithmeticYear_ of _calendar_. The given _monthCode_ must exist in the given year.
638+
</dd>
639+
</dl>
640+
<p>It performs the following steps when called:</p>
641+
<emu-alg>
642+
1. Assert: YearContainsMonthCode(_calendar_, _arithmeticYear_, _monthCode_) is *true*.
643+
1. Let _monthsBefore_ be 0.
644+
1. Let _number_ be 1.
645+
1. Let _isLeap_ be *false*.
646+
1. Let _r_ be the row in <emu-xref href="#table-additional-month-codes"></emu-xref> which the _calendar_ is in the Calendar column.
647+
1. If the *"Leap to Common Month Transformation"* column of _r_ is empty, then
648+
1. Return ! ParseMonthCode(_monthCode_).[[MonthNumber]].
649+
1. Assert: The *"Additional Month Codes"* column of _r_ does not contain *"M00L"* or *"M13"*.
650+
1. Assert: The following loop will terminate.
651+
1. Repeat, while _number_ &le; 12,
652+
1. Let _currentMonthCode_ be CreateMonthCode(_number_, _isLeap_).
653+
1. If YearContainsMonthCode(_calendar_, _arithmeticYear_, _currentMonthCode_), then
654+
1. Set _monthsBefore_ to _monthsBefore_ + 1.
655+
1. If _currentMonthCode_ is _monthCode_, then
656+
1. Return _monthsBefore_.
657+
1. If _isLeap_ is *false*, then
658+
1. Set _isLeap_ to *true*.
659+
1. Else,
660+
1. Set _isLeap_ to *false*.
661+
1. Set _number_ to _number_ + 1.
662+
</emu-alg>
663+
</emu-clause>
664+
566665
<emu-clause id="sec-temporal-isvaliderayearforcalendar" type="abstract operation">
567666
<h1>
568667
IsValidEraYearForCalendar (
@@ -903,10 +1002,11 @@ contributors: Google, Ecma International
9031002
<p>It performs the following steps when called:</p>
9041003
<emu-alg>
9051004
1. Let _calendarDate_ be CalendarISOToDate(_calendar_, _isoDate_).
906-
1. Add _duration_.[[Years]] to _calendarDate_.
907-
1. (This step only matters for lunisolar calendars.) If _calendarDate_.[[MonthCode]] is a leap month that doesn't exist in the year, then:
908-
1. Set _calendarDate_ to another date according to the cultural conventions of that calendar's users. Of the currently supported calendars: if _calendar_ is *"chinese"* or *"dangi"*, change _calendarDate_.[[MonthCode]] to the same month code but without the *"L"*. If _calendar_ is *"hebrew"*, change _calendarDate_.[[MonthCode]] from *"M05L"* to *"M06"*.
909-
1. Update _calendarDate_.[[Month]] accordingly.
1005+
1. Add _duration_.[[Years]] to _calendarDate_ without changing any less-significant fields.
1006+
1. If YearContainsMonthCode(_calendar_, _calendarDate_.[[Year]], _calendarDate_.[[MonthCode]]) is *false*, then
1007+
1. NOTE: This only happens in lunisolar calendars.
1008+
1. Set _calendarDate_.[[MonthCode]] to ! ConstrainMonthCode(_calendar_, _calendarDate_.[[Year]], _calendarDate_.[[MonthCode]], ~constrain~).
1009+
1. Set _calendarDate_.[[Month]] to MonthCodeToOrdinal(_calendar_, _calendarDate_.[[Year]], _calendarDate_.[[MonthCode]]).
9101010
1. Add _duration_.[[Months]] to _calendarDate_, balancing _calendarDate_ if it goes over a year boundary.
9111011
1. If the date described by _calendarDate_ does not exist, then
9121012
1. If _overflow_ is ~reject~, throw a *RangeError* exception.
@@ -972,16 +1072,23 @@ contributors: Google, Ecma International
9721072
<p>This definition supersedes the definition provided in <emu-xref href="#sec-temporal-nonisocalendardatetoiso"></emu-xref>.</p>
9731073
<p>It performs the following steps when called:</p>
9741074
<emu-alg>
975-
1. If _fields_.[[Era]] and _fields_.[[EraYear]] are not ~unset~ and IsValidEraYearForCalendar(_calendar_, _fields_.[[Era]], _fields_.[[EraYear]]) is *false*, throw a *RangeError* exception.
976-
1. If _fields_.[[MonthCode]] is not ~unset~ and IsValidMonthCodeForCalendar(_calendar_, _fields_.[[MonthCode]]) is *false*, throw a *RangeError* exception.
977-
1. If _fields_ describes an existing date in _calendar_, return an implementation-defined ISO Date Record that corresponds to the date described by _fields_.
978-
1. If _overflow_ is ~reject~, throw a *RangeError* exception.
979-
1. (This step only matters for lunisolar calendars.) If _fields_.[[MonthCode]] is a leap month that doesn't exist in the year, then:
980-
1. Set _fields_ to another date according to the cultural conventions of that calendar's users. Of the currently supported calendars: if _calendar_ is *"chinese"* or *"dangi"*, change _fields_.[[MonthCode]] to the same month code but without the *"L"*. If _calendar_ is *"hebrew"*, change _fields_.[[MonthCode]] from *"M05L"* to *"M06"*.
981-
1. Update _fields_.[[Month]] accordingly.
982-
1. If _fields_.[[MonthCode]] is a valid month code for _fields_.[[Year]], but the date described by _fields_ does not exist, set _fields_.[[Day]] to the closest day in the same month. If there are two equally-close dates in the same month, pick the later one.
983-
1. (This step does not apply to any currently supported calendars.) If the date described by _fields_ still does not exist, set _fields_ to the closest date in the same year. If there are two equally-close dates in that year, pick the later one.
984-
1. Return an implementation-defined ISO Date Record that corresponds to the date described by _fields_.
1075+
1. If _fields_.[[Era]] and _fields_.[[EraYear]] are not ~unset~, then
1076+
1. If IsValidEraYearForCalendar(_calendar_, _fields_.[[Era]], _fields_.[[EraYear]]) is *false*, throw a *RangeError* exception.
1077+
1. Let _arithmeticYear_ be CalendarDateArithmeticYearForEraYear(_calendar_, _fields_.[[Era]], _fields_.[[EraYear]]).
1078+
1. Else,
1079+
1. Assert: _fields_.[[Year]] is not ~unset~.
1080+
1. Let _arithmeticYear_ be _fields_.[[Year]].
1081+
1. If _fields_.[[MonthCode]] is not ~unset~, then
1082+
1. If IsValidMonthCodeForCalendar(_calendar_, _fields_.[[MonthCode]]) is *false*, throw a *RangeError* exception.
1083+
1. Let _constrainedMonthCode_ be ? ConstrainMonthCode(_calendar_, _arithmeticYear_, _fields_.[[MonthCode]], _overflow_).
1084+
1. Let _ordinalMonth_ be MonthCodeToOrdinal(_calendar_, _arithmeticYear_, _constrainedMonthCode_).
1085+
1. Else,
1086+
1. Assert: _fields_.[[Month]] is not ~unset~.
1087+
1. Let _ordinalMonth_ be _fields_.[[Month]].
1088+
1. Let _day_ be _fields_.[[Day]].
1089+
1. Assert: _day_ is not ~unset~.
1090+
1. If the date described by _calendar_, _arithmeticYear_, _ordinalMonth_, and _day_ does not exist, set _day_ to the closest day in the same month. If there are two equally-close dates in the same month, pick the later one.
1091+
1. Return an implementation-defined ISO Date Record that corresponds to the date described by _calendar_, _arithmeticYear_, _ordinalMonth_, and _day_.
9851092
</emu-alg>
9861093
</emu-clause>
9871094

0 commit comments

Comments
 (0)