Skip to content

Commit e6f565d

Browse files
ptomatogibson042
andcommitted
Editorial: Improve ParseMonthCode with small month code grammar
Co-Authored-By: Richard Gibson <[email protected]>
1 parent f860ac6 commit e6f565d

File tree

3 files changed

+19
-21
lines changed

3 files changed

+19
-21
lines changed

polyfill/lib/monthcode.mjs

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,24 @@ import {
22
String as StringCtor,
33
RangeError as RangeErrorCtor,
44
TypeError as TypeErrorCtor,
5-
StringPrototypeIndexOf,
65
StringPrototypePadStart,
7-
StringPrototypeSlice
6+
RegExpPrototypeExec
87
} from './primordials.mjs';
98

109
import Call from 'es-abstract/2024/Call.js';
1110
import ToPrimitive from 'es-abstract/2024/ToPrimitive.js';
1211

12+
import { monthCode as MONTH_CODE_REGEX } from './regex.mjs';
13+
1314
export function ParseMonthCode(argument) {
1415
const value = ToPrimitive(argument, StringCtor);
1516
if (typeof value !== 'string') throw new TypeErrorCtor('month code must be a string');
16-
if (
17-
value.length < 3 ||
18-
value.length > 4 ||
19-
value[0] !== 'M' ||
20-
Call(StringPrototypeIndexOf, '0123456789', [value[1]]) === -1 ||
21-
Call(StringPrototypeIndexOf, '0123456789', [value[2]]) === -1 ||
22-
(value[1] + value[2] === '00' && value[3] !== 'L') ||
23-
(value[3] !== 'L' && value[3] !== undefined)
24-
) {
25-
throw new RangeErrorCtor(`bad month code ${value}; must match M01-M99 or M00L-M99L`);
26-
}
27-
const isLeapMonth = value.length === 4;
28-
const monthNumber = +Call(StringPrototypeSlice, value, [1, 3]);
29-
return { monthNumber, isLeapMonth };
17+
const match = Call(RegExpPrototypeExec, MONTH_CODE_REGEX, [value]);
18+
if (!match) throw new RangeErrorCtor(`bad month code ${value}; must match M01-M99 or M00L-M99L`);
19+
return {
20+
monthNumber: +(match[1] ?? match[3] ?? match[5]),
21+
isLeapMonth: (match[2] ?? match[4] ?? match[6]) === 'L'
22+
};
3023
}
3124

3225
export function CreateMonthCode(monthNumber, isLeapMonth) {

polyfill/lib/regex.mjs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,3 +69,5 @@ const fraction = /(\d+)(?:[.,](\d{1,9}))?/;
6969
const durationDate = /(?:(\d+)Y)?(?:(\d+)M)?(?:(\d+)W)?(?:(\d+)D)?/;
7070
const durationTime = new RegExpCtor(`(?:${fraction.source}H)?(?:${fraction.source}M)?(?:${fraction.source}S)?`);
7171
export const duration = new RegExpCtor(`^([+-])?P${durationDate.source}(?:T(?!$)${durationTime.source})?$`, 'i');
72+
73+
export const monthCode = /^M(?:(00)(L)|(0[1-9])(L)?|([1-9][0-9])(L)?)$/;

spec/calendar.html

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -82,19 +82,22 @@ <h1>
8282
<emu-alg>
8383
1. Let _monthCode_ be ? ToPrimitive(_argument_, ~string~).
8484
1. If _monthCode_ is not a String, throw a *TypeError* exception.
85-
1. If the length of _monthCode_ is not 3 or 4, throw a *RangeError* exception.
86-
1. If the first code unit of _monthCode_ is not 0x004D (LATIN CAPITAL LETTER M), throw a *RangeError* exception.
87-
1. If the second code unit of _monthCode_ is not in the inclusive interval from 0x0030 (DIGIT ZERO) to 0x0039 (DIGIT NINE), throw a *RangeError* exception.
88-
1. If the third code unit of _monthCode_ is not in the inclusive interval from 0x0030 (DIGIT ZERO) to 0x0039 (DIGIT NINE), throw a *RangeError* exception.
85+
1. If ParseText(StringToCodePoints(_monthCode_), |MonthCode|) is a List of errors, throw a *RangeError* exception.
8986
1. Let _isLeapMonth_ be *false*.
9087
1. If the length of _monthCode_ is 4, then
91-
1. If the fourth code unit of _monthCode_ is not 0x004C (LATIN CAPITAL LETTER L), throw a *RangeError* exception.
88+
1. Assert: The fourth code unit of _monthCode_ is 0x004C (LATIN CAPITAL LETTER L).
9289
1. Set _isLeapMonth_ to *true*.
9390
1. Let _monthCodeDigits_ be the substring of _monthCode_ from 1 to 3.
9491
1. Let _monthNumber_ be ℝ(StringToNumber(_monthCodeDigits_)).
9592
1. If _monthNumber_ is 0 and _isLeapMonth_ is *false*, throw a *RangeError* exception.
9693
1. Return the Record { [[MonthNumber]]: _monthNumber_, [[IsLeapMonth]]: _isLeapMonth_ }.
9794
</emu-alg>
95+
<emu-grammar type="definition">
96+
MonthCode :::
97+
`M00L`
98+
`M0` NonZeroDigit `L`?
99+
`M` NonZeroDigit DecimalDigit `L`?
100+
</emu-grammar>
98101
</emu-clause>
99102

100103
<emu-clause id="sec-temporal-createmonthcode" type="abstract operation">

0 commit comments

Comments
 (0)