Skip to content

Commit

Permalink
Editorial: Accommodate calendar-specific fields in non-ISO ...FromFie…
Browse files Browse the repository at this point in the history
…lds() methods

Previously, the spec hardcoded "era" and "eraYear" as extra fields that
should be accessed on the property bags passed to the dateFromFields(),
yearMonthFromFields(), and monthDayFromFields() methods of
Temporal.Calendar.

Instead, the extra fields should be obtained by consulting the calendar's
fields() method. (But not observably; we call CalendarDateFields which is
an implementation-defined AO.) This accommodates calendars that require
additional extra fields, beyond "era" and "eraYear".

Closes: #1789
  • Loading branch information
ptomato committed Aug 24, 2022
1 parent 33b62a3 commit e938a3e
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 13 deletions.
21 changes: 12 additions & 9 deletions polyfill/lib/calendar.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {

const ArrayIncludes = Array.prototype.includes;
const ArrayPrototypePush = Array.prototype.push;
const ArrayPrototypeSort = Array.prototype.sort;
const IntlDateTimeFormat = globalThis.Intl.DateTimeFormat;
const ArraySort = Array.prototype.sort;
const MathAbs = Math.abs;
Expand Down Expand Up @@ -1875,8 +1876,9 @@ const nonIsoGeneralImpl = {
dateFromFields(fields, options, calendar) {
const overflow = ES.ToTemporalOverflow(options);
const cache = new OneObjectCache();
// Intentionally alphabetical
fields = ES.PrepareTemporalFields(fields, ['day', 'era', 'eraYear', 'month', 'monthCode', 'year'], ['day']);
const fieldNames = this.fields(['day', 'month', 'monthCode', 'year']);
ES.Call(ArrayPrototypeSort, fieldNames, []);
fields = ES.PrepareTemporalFields(fields, fieldNames, []);
const { year, month, day } = this.helper.calendarToIsoDate(fields, overflow, cache);
const result = ES.CreateTemporalDate(year, month, day, calendar);
cache.setObject(result);
Expand All @@ -1885,21 +1887,22 @@ const nonIsoGeneralImpl = {
yearMonthFromFields(fields, options, calendar) {
const overflow = ES.ToTemporalOverflow(options);
const cache = new OneObjectCache();
// Intentionally alphabetical
fields = ES.PrepareTemporalFields(fields, ['era', 'eraYear', 'month', 'monthCode', 'year'], []);
const fieldNames = this.fields(['month', 'monthCode', 'year']);
ES.Call(ArrayPrototypeSort, fieldNames, []);
fields = ES.PrepareTemporalFields(fields, fieldNames, []);
const { year, month, day } = this.helper.calendarToIsoDate({ ...fields, day: 1 }, overflow, cache);
const result = ES.CreateTemporalYearMonth(year, month, calendar, /* referenceISODay = */ day);
cache.setObject(result);
return result;
},
monthDayFromFields(fields, options, calendar) {
const overflow = ES.ToTemporalOverflow(options);
// All built-in calendars require `day`, but some allow other fields to be
// substituted for `month`. And for lunisolar calendars, either `monthCode`
// or `year` must be provided because `month` is ambiguous without a year or
// a code.
const cache = new OneObjectCache();
fields = ES.PrepareTemporalFields(fields, ['day', 'era', 'eraYear', 'month', 'monthCode', 'year'], ['day']);
// For lunisolar calendars, either `monthCode` or `year` must be provided
// because `month` is ambiguous without a year or a code.
const fieldNames = this.fields(['day', 'month', 'monthCode', 'year']);
ES.Call(ArrayPrototypeSort, fieldNames, []);
fields = ES.PrepareTemporalFields(fields, fieldNames, []);
const { year, month, day } = this.helper.monthDayFromFields(fields, overflow, cache);
// `year` is a reference year where this month/day exists in this calendar
const result = ES.CreateTemporalMonthDay(month, day, calendar, /* referenceISOYear = */ year);
Expand Down
14 changes: 10 additions & 4 deletions spec/intl.html
Original file line number Diff line number Diff line change
Expand Up @@ -1357,7 +1357,7 @@ <h1>CalendarEraYear ( _calendar_, _dateLike_ )</h1>
<h1>
CalendarDateToISO (
_calendar_: a String,
_fields_: an ordinary Object with one or more of the own data properties listed in <emu-xref href="#table-temporal-field-requirements"></emu-xref>,
_fields_: an ordinary Object with one or more own data properties,
_overflow_: a String,
): either a normal completion containing an ISO Date Record, or an abrupt completion
</h1>
Expand Down Expand Up @@ -1650,7 +1650,9 @@ <h1>Temporal.Calendar.prototype.dateFromFields ( _fields_ [ , _options_ ] )</h1>
1. Let _result_ be ? ISODateFromFields(_fields_, _options_).
1. Else,
1. Let _overflow_ be ? ToTemporalOverflow(_options_).
1. Set _fields_ to ? PrepareTemporalFields(_fields_, « *"day"*, *"era"*, *"eraYear"*, *"month"*, *"monthCode"*, *"year"* », « *"day"* »).
1. Let _fieldNames_ be CalendarDateFields(_calendar_.[[Identifier]], « *"day"*, *"month"*, *"monthCode"*, *"year"* »).
1. Sort _fieldNames_ into the same order as if an Array of the same values had been sorted using %Array.prototype.sort% with *undefined* as _comparefn_.
1. Set _fields_ to ? PrepareTemporalFields(_fields_, _fieldNames_, « »).
1. Let _result_ be ? CalendarDateToISO(_calendar_.[[Identifier]], _fields_, _overflow_).
1. Return ? CreateTemporalDate(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]], _calendar_).
</emu-alg>
Expand All @@ -1671,7 +1673,9 @@ <h1>Temporal.Calendar.prototype.yearMonthFromFields ( _fields_ [ , _options_ ] )
1. Let _result_ be ? ISOYearMonthFromFields(_fields_, _options_).
1. Else,
1. Let _overflow_ be ? ToTemporalOverflow(_options_).
1. Set _fields_ to ? PrepareTemporalFields(_fields_, « *"era"*, *"eraYear"*, *"month"*, *"monthCode"*, *"year"* », « »).
1. Let _fieldNames_ be CalendarDateFields(_calendar_.[[Identifier]], « *"month"*, *"monthCode"*, *"year"* »).
1. Sort _fieldNames_ into the same order as if an Array of the same values had been sorted using %Array.prototype.sort% with *undefined* as _comparefn_.
1. Set _fields_ to ? PrepareTemporalFields(_fields_, _fieldNames_, « »).
1. Let _result_ be ? CalendarDateToISO(_calendar_.[[Identifier]], _fields_, _overflow_).
1. Set _result_.[[ReferenceISODay]] to _result_.[[Day]].
1. Return ? CreateTemporalYearMonth(_result_.[[Year]], _result_.[[Month]], _calendar_, _result_.[[ReferenceISODay]]).
Expand All @@ -1692,7 +1696,9 @@ <h1>Temporal.Calendar.prototype.monthDayFromFields ( _fields_ [ , _options_ ] )<
1. If _calendar_.[[Identifier]] is *"iso8601"*, then
1. Let _result_ be ? ISOMonthDayFromFields(_fields_, _options_).
1. Else,
1. Set _fields_ to ? PrepareTemporalFields(_fields_, « *"day"*, *"era"*, *"eraYear"*, *"month"*, *"monthCode"*, *"year"* », « *"day"* »).
1. Let _fieldNames_ be CalendarDateFields(_calendar_.[[Identifier]], « *"day"*, *"month"*, *"monthCode"*, *"year"* »).
1. Sort _fieldNames_ into the same order as if an Array of the same values had been sorted using %Array.prototype.sort% with *undefined* as _comparefn_.
1. Set _fields_ to ? PrepareTemporalFields(_fields_, _fieldNames_, « »).
1. Let _overflow_ be ? ToTemporalOverflow(_options_).
1. Let _result_ be ? CalendarDateToISO(_calendar_.[[Identifier]], _fields_, _overflow_).
1. Set _result_.[[ReferenceISOYear]] to _result_.[[Year]].
Expand Down

0 comments on commit e938a3e

Please sign in to comment.