Skip to content

Commit 375a4ad

Browse files
ptomato12wrigja
authored andcommitted
Accommodate calendar-specific fields in non-ISO ...FromFields() 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". UPSTREAM_COMMIT=e938a3ef41ff602878eb430d0612b3de61179615
1 parent cdeec0c commit 375a4ad

File tree

3 files changed

+26
-24
lines changed

3 files changed

+26
-24
lines changed

lib/calendar.ts

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,16 @@ import {
2222
SetSlot
2323
} from './slots';
2424
import type { Temporal } from '..';
25-
import type { BuiltinCalendarId, CalendarParams as Params, CalendarReturn as Return } from './internaltypes';
25+
import type {
26+
BuiltinCalendarId,
27+
CalendarParams as Params,
28+
CalendarReturn as Return,
29+
AnyTemporalKey
30+
} from './internaltypes';
2631

2732
const ArrayIncludes = Array.prototype.includes;
2833
const ArrayPrototypePush = Array.prototype.push;
34+
const ArrayPrototypeSort = Array.prototype.sort;
2935
const IntlDateTimeFormat = globalThis.Intl.DateTimeFormat;
3036
const ArraySort = Array.prototype.sort;
3137
const MathAbs = Math.abs;
@@ -2283,12 +2289,9 @@ class NonIsoCalendar implements CalendarImpl {
22832289
): Temporal.PlainDate {
22842290
const overflow = ES.ToTemporalOverflow(options);
22852291
const cache = new OneObjectCache();
2286-
// Intentionally alphabetical
2287-
const fields = ES.PrepareTemporalFields(
2288-
fieldsParam,
2289-
['day', 'era', 'eraYear', 'month', 'monthCode', 'year'],
2290-
['day']
2291-
);
2292+
const fieldNames = this.fields(['day', 'month', 'monthCode', 'year']) as readonly AnyTemporalKey[];
2293+
ArrayPrototypeSort.call(fieldNames);
2294+
const fields = ES.PrepareTemporalFields(fieldsParam, fieldNames, []);
22922295
const { year, month, day } = this.helper.calendarToIsoDate(fields, overflow, cache);
22932296
const result = ES.CreateTemporalDate(year, month, day, calendar);
22942297
cache.setObject(result);
@@ -2301,8 +2304,9 @@ class NonIsoCalendar implements CalendarImpl {
23012304
): Temporal.PlainYearMonth {
23022305
const overflow = ES.ToTemporalOverflow(options);
23032306
const cache = new OneObjectCache();
2304-
// Intentionally alphabetical
2305-
const fields = ES.PrepareTemporalFields(fieldsParam, ['era', 'eraYear', 'month', 'monthCode', 'year'], []);
2307+
const fieldNames = this.fields(['month', 'monthCode', 'year']) as readonly AnyTemporalKey[];
2308+
ArrayPrototypeSort.call(fieldNames);
2309+
const fields = ES.PrepareTemporalFields(fieldsParam, fieldNames, []);
23062310
const { year, month, day } = this.helper.calendarToIsoDate({ ...fields, day: 1 }, overflow, cache);
23072311
const result = ES.CreateTemporalYearMonth(year, month, calendar, /* referenceISODay = */ day);
23082312
cache.setObject(result);
@@ -2314,16 +2318,12 @@ class NonIsoCalendar implements CalendarImpl {
23142318
calendar: Temporal.Calendar
23152319
): Temporal.PlainMonthDay {
23162320
const overflow = ES.ToTemporalOverflow(options);
2317-
// All built-in calendars require `day`, but some allow other fields to be
2318-
// substituted for `month`. And for lunisolar calendars, either `monthCode`
2319-
// or `year` must be provided because `month` is ambiguous without a year or
2320-
// a code.
23212321
const cache = new OneObjectCache();
2322-
const fields = ES.PrepareTemporalFields(
2323-
fieldsParam,
2324-
['day', 'era', 'eraYear', 'month', 'monthCode', 'year'],
2325-
['day']
2326-
);
2322+
// For lunisolar calendars, either `monthCode` or `year` must be provided
2323+
// because `month` is ambiguous without a year or a code.
2324+
const fieldNames = this.fields(['day', 'month', 'monthCode', 'year']) as readonly AnyTemporalKey[];
2325+
ArrayPrototypeSort.call(fieldNames);
2326+
const fields = ES.PrepareTemporalFields(fieldsParam, fieldNames, []);
23272327
const { year, month, day } = this.helper.monthDayFromFields(fields, overflow, cache);
23282328
// `year` is a reference year where this month/day exists in this calendar
23292329
const result = ES.CreateTemporalMonthDay(month, day, calendar, /* referenceISOYear = */ year);

lib/ecmascript.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,9 @@ import type {
4040
PlainDateTimeParams,
4141
PlainYearMonthParams,
4242
PrimitiveFieldsOf,
43-
BuiltinCalendarId
43+
BuiltinCalendarId,
44+
Keys,
45+
AnyTemporalKey
4446
} from './internaltypes';
4547
import { GetIntrinsic } from './intrinsicclass';
4648
import {
@@ -1213,11 +1215,6 @@ interface FieldPrepareOptions {
12131215
emptySourceErrorMessage: string;
12141216
}
12151217

1216-
type AnyTemporalKey = Exclude<Keys<AnyTemporalLikeType>, symbol>;
1217-
1218-
// Keys is a conditionally-mapped version of keyof
1219-
type Keys<T> = T extends Record<string, unknown> ? keyof T : never;
1220-
12211218
// Returns all potential owners from all Temporal Like-types for a given union
12221219
// of keys in K.
12231220
// e.g.

lib/internaltypes.d.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,11 @@ type AllTemporalLikeTypes = [
6161
];
6262
export type AnyTemporalLikeType = AllTemporalLikeTypes[number];
6363

64+
// Keys is a conditionally-mapped version of keyof
65+
export type Keys<T> = T extends Record<string, unknown> ? keyof T : never;
66+
67+
export type AnyTemporalKey = Exclude<Keys<AnyTemporalLikeType>, symbol>;
68+
6469
// The properties below are all the names of Temporal properties that can be set with `with`.
6570
// `timeZone` and `calendar` are not on the list because they have special methods to set them.
6671

0 commit comments

Comments
 (0)