Skip to content

Commit

Permalink
EN: Accept multiple time units connected by "and"
Browse files Browse the repository at this point in the history
  • Loading branch information
Wanasit Tanakitrungruang committed Jan 20, 2024
1 parent 9aeb1c3 commit d1a71c9
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 8 deletions.
11 changes: 9 additions & 2 deletions src/locales/en/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -264,10 +264,17 @@ const SINGLE_TIME_UNIT_NO_ABBR_PATTERN = `(${NUMBER_PATTERN})\\s{0,3}(${matchAny
TIME_UNIT_DICTIONARY_NO_ABBR
)})`;

export const TIME_UNITS_PATTERN = repeatedTimeunitPattern(`(?:(?:about|around)\\s{0,3})?`, SINGLE_TIME_UNIT_PATTERN);
const TIME_UNIT_CONNECTOR_PATTERN = `\\s{0,5},?(?:\\s*and)?\\s{0,5}`;

export const TIME_UNITS_PATTERN = repeatedTimeunitPattern(
`(?:(?:about|around)\\s{0,3})?`,
SINGLE_TIME_UNIT_PATTERN,
TIME_UNIT_CONNECTOR_PATTERN
);
export const TIME_UNITS_NO_ABBR_PATTERN = repeatedTimeunitPattern(
`(?:(?:about|around)\\s{0,3})?`,
SINGLE_TIME_UNIT_NO_ABBR_PATTERN
SINGLE_TIME_UNIT_NO_ABBR_PATTERN,
TIME_UNIT_CONNECTOR_PATTERN
);

export function parseTimeUnits(timeunitText): TimeUnits {
Expand Down
5 changes: 1 addition & 4 deletions src/locales/en/parsers/ENTimeUnitLaterFormatParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,7 @@ const PATTERN = new RegExp(
"i"
);

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

export default class ENTimeUnitLaterFormatParser extends AbstractParserWithWordBoundaryChecking {
Expand Down
8 changes: 6 additions & 2 deletions src/utils/pattern.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
type DictionaryLike = string[] | { [word: string]: unknown } | Map<string, unknown>;

export function repeatedTimeunitPattern(prefix: string, singleTimeunitPattern: string): string {
export function repeatedTimeunitPattern(
prefix: string,
singleTimeunitPattern: string,
connectorPattern = "\\s{0,5},?\\s{0,5}"
): string {
const singleTimeunitPatternNoCapture = singleTimeunitPattern.replace(/\((?!\?)/g, "(?:");
return `${prefix}${singleTimeunitPatternNoCapture}\\s{0,5}(?:,?\\s{0,5}${singleTimeunitPatternNoCapture}){0,10}`;
return `${prefix}${singleTimeunitPatternNoCapture}(?:${connectorPattern}${singleTimeunitPatternNoCapture}){0,10}`;
}

export function extractTerms(dictionary: DictionaryLike): string[] {
Expand Down
12 changes: 12 additions & 0 deletions test/en/en_time_units_later.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,9 @@ test("Test - From now Expression", () => {

expect(result.start).toBeDate(new Date(2012, 7, 10, 14, 10));
});
});

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

expect(result.start).toBeDate(new Date(2012, 7, 11, 14, 45));
});

testSingleCase(chrono, "in 1d, 2hr, and 5min", new Date(2012, 7, 10, 12, 40), (result) => {
expect(result.index).toBe(0);
expect(result.text).toBe("in 1d, 2hr, and 5min");
expect(result.start.get("day")).toBe(11);
expect(result.start.get("hour")).toBe(14);
expect(result.start.get("minute")).toBe(45);

expect(result.start).toBeDate(new Date(2012, 7, 11, 14, 45));
});
});

test("Test - Strict mode", function () {
Expand Down
42 changes: 42 additions & 0 deletions test/en/en_time_units_within.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,48 @@ test("Test - The normal within expression", () => {
});
});

test("Test - The within expression with multiple time units", function () {
testSingleCase(chrono, "set a timer for 5 minutes 30 seconds", new Date(2012, 7, 10, 12, 14), (result) => {
expect(result.index).toBe(12);
expect(result.text).toBe("for 5 minutes 30 seconds");

expect(result.start).toBeDate(new Date(2012, 7, 10, 12, 19, 30));
});

testSingleCase(chrono, "set a timer for 5 minutes, 30 seconds", new Date(2012, 7, 10, 12, 14), (result) => {
expect(result.index).toBe(12);
expect(result.text).toBe("for 5 minutes, 30 seconds");

expect(result.start).toBeDate(new Date(2012, 7, 10, 12, 19, 30));
});

testSingleCase(chrono, "set a timer for 1 hour, 5 minutes, 30 seconds", new Date(2012, 7, 10, 12, 14), (result) => {
expect(result.index).toBe(12);
expect(result.text).toBe("for 1 hour, 5 minutes, 30 seconds");

expect(result.start).toBeDate(new Date(2012, 7, 10, 13, 19, 30));
});

testSingleCase(chrono, "set a timer for 5 minutes and 30 seconds", new Date(2012, 7, 10, 12, 14), (result) => {
expect(result.index).toBe(12);
expect(result.text).toBe("for 5 minutes and 30 seconds");

expect(result.start).toBeDate(new Date(2012, 7, 10, 12, 19, 30));
});

testSingleCase(
chrono,
"set a timer for 1 hour, 5 minutes, and 30 seconds",
new Date(2012, 7, 10, 12, 14),
(result) => {
expect(result.index).toBe(12);
expect(result.text).toBe("for 1 hour, 5 minutes, and 30 seconds");

expect(result.start).toBeDate(new Date(2012, 7, 10, 13, 19, 30));
}
);
});

test("Test - The within expression with certain keywords", () => {
testSingleCase(chrono, "In about 5 hours", new Date(2012, 8 - 1, 10, 12, 49), (result, text) => {
expect(result.text).toBe(text);
Expand Down

0 comments on commit d1a71c9

Please sign in to comment.