diff --git a/polyfill/lib/calendar.mjs b/polyfill/lib/calendar.mjs index c5cfe9195..f8e639675 100644 --- a/polyfill/lib/calendar.mjs +++ b/polyfill/lib/calendar.mjs @@ -243,12 +243,12 @@ function resolveNonLunisolarMonth(calendarDate, overflow = undefined, monthsPerY monthCode = buildMonthCode(month); } else { const numberPart = monthCodeNumberPart(monthCode); - if (month !== undefined && month !== numberPart) { - throw new RangeError(`monthCode ${monthCode} and month ${month} must match if both are present`); - } if (monthCode !== buildMonthCode(numberPart)) { throw new RangeError(`Invalid month code: ${monthCode}`); } + if (month !== undefined && month !== numberPart) { + throw new RangeError(`monthCode ${monthCode} and month ${month} must match if both are present`); + } month = numberPart; if (month < 1 || month > monthsPerYear) throw new RangeError(`Invalid monthCode: ${monthCode}`); } @@ -858,12 +858,11 @@ const nonIsoHelperBase = { // Override if calendar uses eras hasEra: false, monthDayFromFields(fields, overflow, cache) { - let { monthCode, day } = fields; - if (monthCode === undefined) { - let { year, era, eraYear } = fields; - if (year === undefined && (era === undefined || eraYear === undefined)) { - throw new TypeError('when `monthCode` is omitted, `year` (or `era` and `eraYear`) and `month` are required'); - } + let { era, eraYear, year, month, monthCode, day } = fields; + if (month !== undefined && year === undefined && (!this.hasEra || era === undefined || eraYear === undefined)) { + throw new TypeError('when month is present, year (or era and eraYear) are required'); + } + if (monthCode === undefined || year !== undefined || (this.hasEra && eraYear !== undefined)) { // Apply overflow behaviour to year/month/day, to get correct monthCode/day ({ monthCode, day } = this.isoToCalendarDate(this.calendarToIsoDate(fields, overflow, cache), cache)); } @@ -1785,8 +1784,6 @@ const nonIsoGeneralImpl = { 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); // result.year is a reference year where this month/day exists in this calendar cache.setObject(result); diff --git a/spec/calendar.html b/spec/calendar.html index 26bc8e7e7..d0802c1ec 100644 --- a/spec/calendar.html +++ b/spec/calendar.html @@ -1224,7 +1224,7 @@

The reference year is almost always 1972 (the first ISO 8601 leap year after the epoch), with exceptions for calendars where some dates (e.g. leap days or days in leap months) didn't occur during that ISO 8601 year. For example, Hebrew calendar leap month Adar I occurred in calendar years 5730 and 5733 (respectively overlapping ISO 8601 February/March 1970 and February/March 1973), but did not occur between them, so the reference year for for days of that month is 1970.

- Like RegulateISODate, the operation throws a *RangeError* exception if _overflow_ is *"reject"* and the month and day described by _fields_ does not exist. + Like RegulateISODate, the operation throws a *RangeError* exception if _overflow_ is *"reject"* and the month and day described by _fields_ does not exist (or does not exist within the year described by _fields_ when there is such a year). For example, when _calendar_ is *"gregory"* and _overflow_ is *"reject"*, _fields_ values of { [[MonthCode]]: *"M01"*, [[Day]]: 32 } and { [[Year]]: 2001, [[Month]]: 2, [[Day]]: 29 } would both cause a *RangeError* to be thrown. In the latter case, even though February 29 is a date in leap years of the Gregorian calendar, 2001 was not a leap year and a month code cannot be determined from the nonexistent date 2001-02-29 with the specified month index.

@@ -1381,16 +1381,16 @@