Skip to content

Commit 053cc8f

Browse files
author
Wanasit Tanakitrungruang
committedApr 4, 2021
Fix: negative time range parsing
1 parent 534bb4a commit 053cc8f

File tree

5 files changed

+115
-57
lines changed

5 files changed

+115
-57
lines changed
 

‎src/common/parsers/AbstractTimeExpressionParser.ts

+43-15
Original file line numberDiff line numberDiff line change
@@ -72,35 +72,32 @@ export abstract class AbstractTimeExpressionParser implements Parser {
7272
extract(context: ParsingContext, match: RegExpMatchArray): ParsingResult {
7373
const startComponents = this.extractPrimaryTimeComponents(context, match);
7474
if (!startComponents) {
75-
match.index += match[0].length;
75+
match.index += match[0].length; // Skip over potential overlapping pattern
7676
return null;
7777
}
7878

79-
const result = context.createParsingResult(
80-
match.index + match[1].length,
81-
match[0].substring(match[1].length),
82-
startComponents
83-
);
79+
const index = match.index + match[1].length;
80+
const text = match[0].substring(match[1].length);
81+
const result = context.createParsingResult(index, text, startComponents);
82+
match.index += match[0].length; // Skip over potential overlapping pattern
8483

85-
const remainingText = context.text.substring(match.index + match[0].length);
84+
const remainingText = context.text.substring(match.index);
8685
const followingPattern = this.getFollowingTimePatternThroughCache();
87-
match = followingPattern.exec(remainingText);
86+
const followingMatch = followingPattern.exec(remainingText);
8887
if (
89-
!match ||
88+
!followingMatch ||
9089
// Pattern "YY.YY -XXXX" is more like timezone offset
91-
match[0].match(/^\s*([+-])\s*\d{3,4}$/)
90+
followingMatch[0].match(/^\s*([+-])\s*\d{3,4}$/)
9291
) {
9392
return this.checkAndReturnWithoutFollowingPattern(result);
9493
}
9594

96-
result.end = this.extractFollowingTimeComponents(context, match, result);
95+
result.end = this.extractFollowingTimeComponents(context, followingMatch, result);
9796
if (result.end) {
98-
if (result.end) {
99-
result.text += match[0];
100-
}
97+
result.text += followingMatch[0];
10198
}
10299

103-
return result;
100+
return this.checkAndReturnWithFollowingPattern(result);
104101
}
105102

106103
extractPrimaryTimeComponents(
@@ -334,6 +331,37 @@ export abstract class AbstractTimeExpressionParser implements Parser {
334331
return result;
335332
}
336333

334+
private checkAndReturnWithFollowingPattern(result) {
335+
if (result.text.match(/^\d+-\d+$/)) {
336+
return null;
337+
}
338+
339+
// If it ends only with numbers or dots
340+
const endingWithNumbers = result.text.match(/[^\d:.](\d[\d.]+)\s*-\s*(\d[\d.]+)$/);
341+
if (endingWithNumbers) {
342+
// In strict mode (e.g. "at 1-3" or "at 1.2 - 2.3"), this should not be accepted
343+
if (this.strictMode) {
344+
return null;
345+
}
346+
347+
const startingNumbers: string = endingWithNumbers[1];
348+
const endingNumbers: string = endingWithNumbers[2];
349+
// If it ends only with dot single digit, e.g. "at 1.2"
350+
if (endingNumbers.includes(".") && !endingNumbers.match(/\d(\.\d{2})+$/)) {
351+
return null;
352+
}
353+
354+
// If it ends only with numbers above 24, e.g. "at 25"
355+
const endingNumberVal = parseInt(endingNumbers);
356+
const startingNumberVal = parseInt(startingNumbers);
357+
if (endingNumberVal > 24 || startingNumberVal > 24) {
358+
return null;
359+
}
360+
}
361+
362+
return result;
363+
}
364+
337365
private cachedPrimaryPrefix = null;
338366
private cachedPrimarySuffix = null;
339367
private cachedPrimaryTimePattern = null;

‎test/en/en.test.ts

-28
Original file line numberDiff line numberDiff line change
@@ -97,34 +97,6 @@ test("Test - Random text", function () {
9797
});
9898
});
9999

100-
test("Test - Random non-date patterns", function () {
101-
testUnexpectedResult(chrono, " 3");
102-
103-
testUnexpectedResult(chrono, " 1");
104-
105-
testUnexpectedResult(chrono, " 11 ");
106-
107-
testUnexpectedResult(chrono, " 0.5 ");
108-
109-
testUnexpectedResult(chrono, " 35.49 ");
110-
111-
testUnexpectedResult(chrono, "12.53%");
112-
113-
testUnexpectedResult(chrono, "6358fe2310> *5.0* / 5 Outstanding");
114-
115-
testUnexpectedResult(chrono, "6358fe2310> *1.5* / 5 Outstanding");
116-
117-
testUnexpectedResult(chrono, "Total: $1,194.09 [image: View Reservation");
118-
119-
testUnexpectedResult(chrono, "Version: 1.1.3");
120-
121-
testUnexpectedResult(chrono, "Version: 1.1.30");
122-
123-
testUnexpectedResult(chrono, "Version: 1.10.30");
124-
125-
testUnexpectedResult(chrono, "at 6.5 kilograms");
126-
});
127-
128100
test("Test - Wikipedia Texts", function () {
129101
const text =
130102
"October 7, 2011, of which details were not revealed out of respect to Jobs's family.[239] " +

‎test/en/en_time_exp.test.ts

+16
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,12 @@ test("Test - Parsing negative cases : 'at [some numbers]'", function () {
260260
testUnexpectedResult(chrono, "I'm at 10.1");
261261
});
262262

263+
test("Test - Parsing negative cases : 'at [some numbers] - [some numbers]'", function () {
264+
testUnexpectedResult(chrono, "I'm at 10.1 - 10.12");
265+
266+
testUnexpectedResult(chrono, "I'm at 10 - 10.1");
267+
});
268+
263269
test("Test - Parsing negative cases (Strict)", function () {
264270
testUnexpectedResult(chrono.strict, "I'm at 101,194 points!");
265271

@@ -271,3 +277,13 @@ test("Test - Parsing negative cases (Strict)", function () {
271277

272278
testUnexpectedResult(chrono.strict, "2020");
273279
});
280+
281+
test("Test - Parsing negative cases : 'at [some numbers] - [some numbers]' (Strict)", function () {
282+
testUnexpectedResult(chrono.strict, "I'm at 10.1 - 10.12");
283+
284+
testUnexpectedResult(chrono.strict, "I'm at 10 - 10.1");
285+
286+
testUnexpectedResult(chrono.strict, "I'm at 10 - 20");
287+
288+
testUnexpectedResult(chrono.strict, "7-730");
289+
});

‎test/en/negative_cases.test.ts

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import { testSingleCase, testUnexpectedResult } from "../test_util";
2+
import * as chrono from "../../src";
3+
4+
test("Test - Skip random non-date patterns", function () {
5+
testUnexpectedResult(chrono, " 3");
6+
7+
testUnexpectedResult(chrono, " 1");
8+
9+
testUnexpectedResult(chrono, " 11 ");
10+
11+
testUnexpectedResult(chrono, " 0.5 ");
12+
13+
testUnexpectedResult(chrono, " 35.49 ");
14+
15+
testUnexpectedResult(chrono, "12.53%");
16+
17+
testUnexpectedResult(chrono, "6358fe2310> *5.0* / 5 Outstanding");
18+
19+
testUnexpectedResult(chrono, "6358fe2310> *1.5* / 5 Outstanding");
20+
21+
testUnexpectedResult(chrono, "Total: $1,194.09 [image: View Reservation");
22+
23+
testUnexpectedResult(chrono, "at 6.5 kilograms");
24+
});
25+
26+
test("Test - Skip hyphenated numbers pattern", () => {
27+
testUnexpectedResult(chrono, "1-2");
28+
29+
testUnexpectedResult(chrono, "1-2-3");
30+
31+
testUnexpectedResult(chrono, "4-5-6");
32+
33+
testUnexpectedResult(chrono, "20-30-12");
34+
});
35+
36+
test("Test - Skip version number pattern", () => {
37+
testUnexpectedResult(chrono, "Version: 1.1.3");
38+
39+
testUnexpectedResult(chrono, "Version: 1.1.30");
40+
41+
testUnexpectedResult(chrono, "Version: 1.10.30");
42+
});
43+
44+
test("Test - Date with version number pattern", () => {
45+
testSingleCase(chrono.en, "1.5.3 - 2015-09-24", (result) => {
46+
expect(result.text).toBe("2015-09-24");
47+
});
48+
49+
testSingleCase(chrono.en, "1.5.30 - 2015-09-24", (result) => {
50+
expect(result.text).toBe("2015-09-24");
51+
});
52+
53+
testSingleCase(chrono.en, "1.50.30 - 2015-09-24", (result) => {
54+
expect(result.text).toBe("2015-09-24");
55+
});
56+
});

‎test/system.test.ts

-14
Original file line numberDiff line numberDiff line change
@@ -169,17 +169,3 @@ test("Test - Compare with native js", () => {
169169

170170
testByCompareWithNative("2014-12-14T18:22:14.759Z");
171171
});
172-
173-
test("Test - Skip version-number-like pattern", () => {
174-
testSingleCase(chrono, "1.5.3 - 2015-09-24", (result) => {
175-
expect(result.text).toBe("2015-09-24");
176-
});
177-
178-
testSingleCase(chrono, "1.5.30 - 2015-09-24", (result) => {
179-
expect(result.text).toBe("2015-09-24");
180-
});
181-
182-
testSingleCase(chrono, "1.50.30 - 2015-09-24", (result) => {
183-
expect(result.text).toBe("2015-09-24");
184-
});
185-
});

0 commit comments

Comments
 (0)
Please sign in to comment.