Skip to content

Commit 2dd49c6

Browse files
andrew-colemanmattbaileyuk
authored andcommitted
Improve regex generation for DateTime parser
If there are two adjacent integer definitions for date/time fields in the picture string without any extra markup between them, then the generated regex must precisely define the number of digits in the first field. Signed-off-by: Andrew Coleman <[email protected]>
1 parent 2ed0395 commit 2dd49c6

File tree

2 files changed

+18
-13
lines changed

2 files changed

+18
-13
lines changed

src/datetime.js

+12-13
Original file line numberDiff line numberDiff line change
@@ -612,7 +612,7 @@ const dateTime = (function () {
612612
def.integerFormat.mandatoryDigits = def.width.min;
613613
}
614614
}
615-
if ('YMD'.indexOf(def.component) !== -1) {
615+
if (def.component === 'Y') {
616616
// §9.8.4.4
617617
def.n = -1;
618618
if (def.width && def.width.max !== undefined) {
@@ -625,6 +625,11 @@ const dateTime = (function () {
625625
}
626626
}
627627
}
628+
// if the previous part is also an integer with no intervening markup, then its width for parsing must be precisely defined
629+
const previousPart = spec[spec.length - 1];
630+
if (previousPart && previousPart.integerFormat) {
631+
previousPart.integerFormat.parseWidth = previousPart.integerFormat.mandatoryDigits;
632+
}
628633
}
629634
if (def.component === 'Z' || def.component === 'z') {
630635
def.integerFormat = analyseIntegerPicture(def.presentation1);
@@ -990,7 +995,6 @@ const dateTime = (function () {
990995
return offsetHours * 60 + offsetMinutes;
991996
};
992997
} else if (part.integerFormat) {
993-
part.integerFormat.n = part.n;
994998
res = generateRegex(part.integerFormat);
995999
} else {
9961000
// must be a month or day name
@@ -1035,16 +1039,6 @@ const dateTime = (function () {
10351039
} else { // type === 'integer'
10361040
matcher.type = 'integer';
10371041
const isUpper = formatSpec.case === tcase.UPPER;
1038-
let occurrences;
1039-
if(formatSpec.n && formatSpec.n > 0){
1040-
if(formatSpec.optionalDigits === 0){
1041-
occurrences = `{${formatSpec.n}}`;
1042-
} else {
1043-
occurrences = `{${formatSpec.n - formatSpec.optionalDigits},${formatSpec.n}}`;
1044-
}
1045-
} else {
1046-
occurrences = '+';
1047-
}
10481042

10491043
switch (formatSpec.primary) {
10501044
case formats.LETTERS:
@@ -1066,7 +1060,12 @@ const dateTime = (function () {
10661060
};
10671061
break;
10681062
case formats.DECIMAL:
1069-
matcher.regex = `[0-9]${occurrences}`;
1063+
matcher.regex = '[0-9]';
1064+
if (formatSpec.parseWidth) {
1065+
matcher.regex += `{${formatSpec.parseWidth}}`;
1066+
} else {
1067+
matcher.regex += '+';
1068+
}
10701069
if (formatSpec.ordinal) {
10711070
// ordinals
10721071
matcher.regex += '(?:th|st|nd|rd)';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"expr": "$toMillis('2024-01-01T12:38:49Z') = $toMillis('20240101123849', '[Y0000][M00][D00][H00][m00][s00]')",
3+
"data": null,
4+
"bindings": {},
5+
"result": true
6+
}

0 commit comments

Comments
 (0)