Skip to content

Commit

Permalink
Polyfill: Enforce consistency of era + eraYear vs. year and (where re…
Browse files Browse the repository at this point in the history
…levant) monthCode vs. month in non-ISO calendars

Fixes tc39#2864
  • Loading branch information
gibson042 committed Sep 18, 2024
1 parent 20124aa commit a3a01e4
Showing 1 changed file with 22 additions and 5 deletions.
27 changes: 22 additions & 5 deletions polyfill/lib/calendar.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -1399,9 +1399,13 @@ const makeHelperGregorian = (id, originalEras) => {
},
/** Fill in missing parts of the (year, era, eraYear) tuple */
completeEraYear(calendarDate) {
const checkField = (name, value) => {
const checkField = (name, value, aliases) => {
const currentValue = calendarDate[name];
if (currentValue != null && currentValue != value) {
if (
currentValue != null &&
currentValue != value &&
!ES.Call(ArrayPrototypeIncludes, aliases || [], [currentValue])
) {
throw new RangeErrorCtor(`Input ${name} ${currentValue} doesn't match calculated value ${value}`);
}
};
Expand Down Expand Up @@ -1432,13 +1436,14 @@ const makeHelperGregorian = (id, originalEras) => {
}
]);
if (!matchingEra) throw new RangeErrorCtor(`Year ${year} was not matched by any era`);
return { eraYear, era: matchingEra.name };
return { eraYear, era: matchingEra.name, eraAliases: matchingEra.aliases };
};

let { year, eraYear, era } = calendarDate;
if (year != null) {
({ eraYear, era } = eraFromYear(year));
checkField('era', era);
const matchData = eraFromYear(year);
({ eraYear, era } = matchData);
checkField('era', era, matchData?.eraAliases);
checkField('eraYear', eraYear);
} else if (eraYear != null) {
if (era === undefined) throw new RangeErrorCtor('era and eraYear must be provided together');
Expand Down Expand Up @@ -1825,18 +1830,30 @@ const nonIsoGeneralImpl = {
},
dateFromFields(fields, overflow) {
const cache = new OneObjectCache();
if (this.helper && this.helper.calendarType !== 'lunisolar') {
const largestMonth = this.helper.monthsInYear(fields, cache);
resolveNonLunisolarMonth(fields, undefined, largestMonth);
}
const result = this.helper.calendarToIsoDate(fields, overflow, cache);
cache.setObject(result);
return result;
},
yearMonthFromFields(fields, overflow) {
const cache = new OneObjectCache();
if (this.helper && this.helper.calendarType !== 'lunisolar') {
const largestMonth = this.helper.monthsInYear(fields, cache);
resolveNonLunisolarMonth(fields, undefined, largestMonth);
}
const result = this.helper.calendarToIsoDate({ ...fields, day: 1 }, overflow, cache);
cache.setObject(result);
return result;
},
monthDayFromFields(fields, overflow) {
const cache = new OneObjectCache();
if (this.helper && this.helper.calendarType !== 'lunisolar') {
const largestMonth = this.helper.monthsInYear(fields, cache);
resolveNonLunisolarMonth(fields, undefined, largestMonth);
}
// For lunisolar calendars, either `monthCode` or `year` must be provided
// because `month` is ambiguous without a year or a code.
const result = this.helper.monthDayFromFields(fields, overflow, cache);
Expand Down

0 comments on commit a3a01e4

Please sign in to comment.