@@ -161,7 +161,7 @@ impl['iso8601'] = {
161161 if ( ( type === 'date' || type === 'month-day' ) && fields . day === undefined ) {
162162 throw new TypeErrorCtor ( 'day is required' ) ;
163163 }
164- ObjectAssign ( fields , resolveNonLunisolarMonth ( fields ) ) ;
164+ ObjectAssign ( fields , resolveNonLunisolarMonth ( fields , 'iso8601' ) ) ;
165165 } ,
166166 dateToISO ( fields , overflow ) {
167167 return ES . RegulateISODate ( fields . year , fields . month , fields . day , overflow ) ;
@@ -287,34 +287,60 @@ impl['iso8601'] = {
287287 }
288288} ;
289289
290+ const monthCodeInfo = {
291+ chinese : {
292+ additionalMonths : [ 'M01L' , 'M02L' , 'M03L' , 'M04L' , 'M05L' , 'M06L' , 'M07L' , 'M08L' , 'M09L' , 'M10L' , 'M11L' , 'M12L' ]
293+ } ,
294+ coptic : {
295+ additionalMonths : [ 'M13' ]
296+ } ,
297+ dangi : {
298+ additionalMonths : [ 'M01L' , 'M02L' , 'M03L' , 'M04L' , 'M05L' , 'M06L' , 'M07L' , 'M08L' , 'M09L' , 'M10L' , 'M11L' , 'M12L' ]
299+ } ,
300+ ethioaa : {
301+ additionalMonths : [ 'M13' ]
302+ } ,
303+ ethiopic : {
304+ additionalMonths : [ 'M13' ]
305+ } ,
306+ hebrew : {
307+ additionalMonths : [ 'M05L' ]
308+ }
309+ } ;
310+
311+ function IsValidMonthCodeForCalendar ( calendar , monthCode ) {
312+ const { monthNumber, isLeapMonth } = ParseMonthCode ( monthCode ) ;
313+ if ( ! isLeapMonth && monthNumber >= 1 && monthNumber <= 12 ) return true ;
314+ if ( ! ObjectHasOwn ( monthCodeInfo , calendar ) ) return false ;
315+ return Call ( ArrayPrototypeIncludes , monthCodeInfo [ calendar ] . additionalMonths , [ monthCode ] ) ;
316+ }
317+
290318/**
291319 * Safely merge a month, monthCode pair into an integer month.
292320 * If both are present, make sure they match.
293321 * This logic doesn't work for lunisolar calendars!
294322 * */
295- function resolveNonLunisolarMonth ( calendarDate , overflow = undefined , monthsPerYear = 12 ) {
323+ function resolveNonLunisolarMonth ( calendarDate , calendar , overflow = undefined ) {
296324 let { month, monthCode } = calendarDate ;
297325 if ( monthCode === undefined ) {
298326 if ( month === undefined ) throw new TypeErrorCtor ( 'Either month or monthCode are required' ) ;
299327 // The ISO calendar uses the default (undefined) value because it does
300328 // constrain/reject after this method returns. Non-ISO calendars, however,
301329 // rely on this function to constrain/reject out-of-range `month` values.
330+ const monthsPerYear =
331+ 12 + ( ObjectHasOwn ( monthCodeInfo , calendar ) ? monthCodeInfo [ calendar ] . additionalMonths . length : 0 ) ;
302332 if ( overflow === 'reject' ) ES . RejectToRange ( month , 1 , monthsPerYear ) ;
303333 if ( overflow === 'constrain' ) month = ES . ConstrainToRange ( month , 1 , monthsPerYear ) ;
304334 monthCode = CreateMonthCode ( month , false ) ;
305335 } else {
306- const { monthNumber, isLeapMonth } = ParseMonthCode ( monthCode ) ;
307- if ( isLeapMonth ) {
308- throw new RangeErrorCtor ( `Invalid monthCode: ${ monthCode } . Leap months do not exist in this calendar` ) ;
309- }
310- if ( monthCode !== CreateMonthCode ( monthNumber , false ) ) {
311- throw new RangeErrorCtor ( `Invalid month code: ${ monthCode } ` ) ;
336+ if ( ! IsValidMonthCodeForCalendar ( calendar , monthCode ) ) {
337+ throw new RangeErrorCtor ( `Invalid monthCode: ${ monthCode } does not exist in calendar ${ calendar } ` ) ;
312338 }
339+ const { monthNumber } = ParseMonthCode ( monthCode ) ;
313340 if ( month !== undefined && month !== monthNumber ) {
314341 throw new RangeErrorCtor ( `monthCode ${ monthCode } and month ${ month } must match if both are present` ) ;
315342 }
316343 month = monthNumber ;
317- if ( month < 1 || month > monthsPerYear ) throw new RangeErrorCtor ( `Invalid monthCode: ${ monthCode } ` ) ;
318344 }
319345 return { ...calendarDate , month, monthCode } ;
320346}
@@ -752,9 +778,8 @@ const nonIsoHelperBase = {
752778 adjustCalendarDate ( calendarDate , cache , overflow /*, fromLegacyDate = false */ ) {
753779 if ( this . calendarType === 'lunisolar' ) throw new RangeErrorCtor ( 'Override required for lunisolar calendars' ) ;
754780 this . validateCalendarDate ( calendarDate ) ;
755- const largestMonth = this . monthsInYear ( calendarDate , cache ) ;
756781 let { month, monthCode } = calendarDate ;
757- ( { month, monthCode } = resolveNonLunisolarMonth ( calendarDate , overflow , largestMonth ) ) ;
782+ ( { month, monthCode } = resolveNonLunisolarMonth ( calendarDate , this . id , overflow ) ) ;
758783 calendarDate = { ...calendarDate , month, monthCode } ;
759784 if ( CalendarSupportsEra ( this . id ) ) calendarDate = this . completeEraYear ( calendarDate ) ;
760785 return calendarDate ;
@@ -1994,9 +2019,7 @@ const nonIsoGeneralImpl = {
19942019 } ,
19952020 resolveFields ( fields /* , type */ ) {
19962021 if ( this . helper . calendarType !== 'lunisolar' ) {
1997- const cache = new OneObjectCache ( ) ;
1998- const largestMonth = this . helper . monthsInYear ( fields , cache ) ;
1999- resolveNonLunisolarMonth ( fields , undefined , largestMonth ) ;
2022+ resolveNonLunisolarMonth ( fields , this . helper . id ) ;
20002023 }
20012024 } ,
20022025 dateToISO ( fields , overflow ) {
0 commit comments