Skip to content

Commit d1a71c9

Browse files
author
Wanasit Tanakitrungruang
committedJan 20, 2024
EN: Accept multiple time units connected by "and"
1 parent 9aeb1c3 commit d1a71c9

File tree

5 files changed

+70
-8
lines changed

5 files changed

+70
-8
lines changed
 

‎src/locales/en/constants.ts

+9-2
Original file line numberDiff line numberDiff line change
@@ -264,10 +264,17 @@ const SINGLE_TIME_UNIT_NO_ABBR_PATTERN = `(${NUMBER_PATTERN})\\s{0,3}(${matchAny
264264
TIME_UNIT_DICTIONARY_NO_ABBR
265265
)})`;
266266

267-
export const TIME_UNITS_PATTERN = repeatedTimeunitPattern(`(?:(?:about|around)\\s{0,3})?`, SINGLE_TIME_UNIT_PATTERN);
267+
const TIME_UNIT_CONNECTOR_PATTERN = `\\s{0,5},?(?:\\s*and)?\\s{0,5}`;
268+
269+
export const TIME_UNITS_PATTERN = repeatedTimeunitPattern(
270+
`(?:(?:about|around)\\s{0,3})?`,
271+
SINGLE_TIME_UNIT_PATTERN,
272+
TIME_UNIT_CONNECTOR_PATTERN
273+
);
268274
export const TIME_UNITS_NO_ABBR_PATTERN = repeatedTimeunitPattern(
269275
`(?:(?:about|around)\\s{0,3})?`,
270-
SINGLE_TIME_UNIT_NO_ABBR_PATTERN
276+
SINGLE_TIME_UNIT_NO_ABBR_PATTERN,
277+
TIME_UNIT_CONNECTOR_PATTERN
271278
);
272279

273280
export function parseTimeUnits(timeunitText): TimeUnits {

‎src/locales/en/parsers/ENTimeUnitLaterFormatParser.ts

+1-4
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,7 @@ const PATTERN = new RegExp(
88
"i"
99
);
1010

11-
const STRICT_PATTERN = new RegExp(
12-
"" + "(" + TIME_UNITS_NO_ABBR_PATTERN + ")" + "(later|from now)" + "(?=(?:\\W|$))",
13-
"i"
14-
);
11+
const STRICT_PATTERN = new RegExp(`(${TIME_UNITS_NO_ABBR_PATTERN})\\s{0,5}(later|after|from now)(?=\\W|$)`, "i");
1512
const GROUP_NUM_TIMEUNITS = 1;
1613

1714
export default class ENTimeUnitLaterFormatParser extends AbstractParserWithWordBoundaryChecking {

‎src/utils/pattern.ts

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
type DictionaryLike = string[] | { [word: string]: unknown } | Map<string, unknown>;
22

3-
export function repeatedTimeunitPattern(prefix: string, singleTimeunitPattern: string): string {
3+
export function repeatedTimeunitPattern(
4+
prefix: string,
5+
singleTimeunitPattern: string,
6+
connectorPattern = "\\s{0,5},?\\s{0,5}"
7+
): string {
48
const singleTimeunitPatternNoCapture = singleTimeunitPattern.replace(/\((?!\?)/g, "(?:");
5-
return `${prefix}${singleTimeunitPatternNoCapture}\\s{0,5}(?:,?\\s{0,5}${singleTimeunitPatternNoCapture}){0,10}`;
9+
return `${prefix}${singleTimeunitPatternNoCapture}(?:${connectorPattern}${singleTimeunitPatternNoCapture}){0,10}`;
610
}
711

812
export function extractTerms(dictionary: DictionaryLike): string[] {

‎test/en/en_time_units_later.test.ts

+12
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,9 @@ test("Test - From now Expression", () => {
249249

250250
expect(result.start).toBeDate(new Date(2012, 7, 10, 14, 10));
251251
});
252+
});
252253

254+
test("Test - The later expression with multiple time units", function () {
253255
testSingleCase(chrono, "in 1d 2hr 5min", new Date(2012, 7, 10, 12, 40), (result) => {
254256
expect(result.index).toBe(0);
255257
expect(result.text).toBe("in 1d 2hr 5min");
@@ -259,6 +261,16 @@ test("Test - From now Expression", () => {
259261

260262
expect(result.start).toBeDate(new Date(2012, 7, 11, 14, 45));
261263
});
264+
265+
testSingleCase(chrono, "in 1d, 2hr, and 5min", new Date(2012, 7, 10, 12, 40), (result) => {
266+
expect(result.index).toBe(0);
267+
expect(result.text).toBe("in 1d, 2hr, and 5min");
268+
expect(result.start.get("day")).toBe(11);
269+
expect(result.start.get("hour")).toBe(14);
270+
expect(result.start.get("minute")).toBe(45);
271+
272+
expect(result.start).toBeDate(new Date(2012, 7, 11, 14, 45));
273+
});
262274
});
263275

264276
test("Test - Strict mode", function () {

‎test/en/en_time_units_within.test.ts

+42
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,48 @@ test("Test - The normal within expression", () => {
174174
});
175175
});
176176

177+
test("Test - The within expression with multiple time units", function () {
178+
testSingleCase(chrono, "set a timer for 5 minutes 30 seconds", new Date(2012, 7, 10, 12, 14), (result) => {
179+
expect(result.index).toBe(12);
180+
expect(result.text).toBe("for 5 minutes 30 seconds");
181+
182+
expect(result.start).toBeDate(new Date(2012, 7, 10, 12, 19, 30));
183+
});
184+
185+
testSingleCase(chrono, "set a timer for 5 minutes, 30 seconds", new Date(2012, 7, 10, 12, 14), (result) => {
186+
expect(result.index).toBe(12);
187+
expect(result.text).toBe("for 5 minutes, 30 seconds");
188+
189+
expect(result.start).toBeDate(new Date(2012, 7, 10, 12, 19, 30));
190+
});
191+
192+
testSingleCase(chrono, "set a timer for 1 hour, 5 minutes, 30 seconds", new Date(2012, 7, 10, 12, 14), (result) => {
193+
expect(result.index).toBe(12);
194+
expect(result.text).toBe("for 1 hour, 5 minutes, 30 seconds");
195+
196+
expect(result.start).toBeDate(new Date(2012, 7, 10, 13, 19, 30));
197+
});
198+
199+
testSingleCase(chrono, "set a timer for 5 minutes and 30 seconds", new Date(2012, 7, 10, 12, 14), (result) => {
200+
expect(result.index).toBe(12);
201+
expect(result.text).toBe("for 5 minutes and 30 seconds");
202+
203+
expect(result.start).toBeDate(new Date(2012, 7, 10, 12, 19, 30));
204+
});
205+
206+
testSingleCase(
207+
chrono,
208+
"set a timer for 1 hour, 5 minutes, and 30 seconds",
209+
new Date(2012, 7, 10, 12, 14),
210+
(result) => {
211+
expect(result.index).toBe(12);
212+
expect(result.text).toBe("for 1 hour, 5 minutes, and 30 seconds");
213+
214+
expect(result.start).toBeDate(new Date(2012, 7, 10, 13, 19, 30));
215+
}
216+
);
217+
});
218+
177219
test("Test - The within expression with certain keywords", () => {
178220
testSingleCase(chrono, "In about 5 hours", new Date(2012, 8 - 1, 10, 12, 49), (result, text) => {
179221
expect(result.text).toBe(text);

0 commit comments

Comments
 (0)
Please sign in to comment.