chrono-node 2.6.5 → 2.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/calculation/mergingCalculation.js +2 -0
- package/dist/cjs/calculation/mergingCalculation.js.map +1 -1
- package/dist/cjs/common/casualReferences.js +13 -3
- package/dist/cjs/common/casualReferences.js.map +1 -1
- package/dist/cjs/common/parsers/AbstractTimeExpressionParser.js +2 -2
- package/dist/cjs/common/parsers/AbstractTimeExpressionParser.js.map +1 -1
- package/dist/cjs/index.d.ts +2 -2
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/locales/en/parsers/ENCasualDateParser.js +12 -6
- package/dist/cjs/locales/en/parsers/ENCasualDateParser.js.map +1 -1
- package/dist/cjs/locales/en/parsers/ENCasualTimeParser.d.ts +1 -1
- package/dist/cjs/locales/en/parsers/ENCasualTimeParser.js +15 -6
- package/dist/cjs/locales/en/parsers/ENCasualTimeParser.js.map +1 -1
- package/dist/cjs/locales/en/parsers/ENTimeExpressionParser.js +23 -22
- package/dist/cjs/locales/en/parsers/ENTimeExpressionParser.js.map +1 -1
- package/dist/cjs/locales/en/parsers/ENTimeUnitWithinFormatParser.js +3 -2
- package/dist/cjs/locales/en/parsers/ENTimeUnitWithinFormatParser.js.map +1 -1
- package/dist/cjs/locales/fr/refiners/FRMergeDateRangeRefiner.js +1 -1
- package/dist/cjs/locales/fr/refiners/FRMergeDateRangeRefiner.js.map +1 -1
- package/dist/cjs/locales/fr/refiners/FRMergeDateTimeRefiner.js +1 -1
- package/dist/cjs/locales/fr/refiners/FRMergeDateTimeRefiner.js.map +1 -1
- package/dist/cjs/results.d.ts +5 -0
- package/dist/cjs/results.js +30 -2
- package/dist/cjs/results.js.map +1 -1
- package/dist/cjs/types.d.ts +2 -0
- package/dist/cjs/types.js.map +1 -1
- package/dist/esm/calculation/mergingCalculation.js +2 -0
- package/dist/esm/calculation/mergingCalculation.js.map +1 -1
- package/dist/esm/common/casualReferences.js +13 -3
- package/dist/esm/common/casualReferences.js.map +1 -1
- package/dist/esm/common/parsers/AbstractTimeExpressionParser.js +2 -2
- package/dist/esm/common/parsers/AbstractTimeExpressionParser.js.map +1 -1
- package/dist/esm/index.d.ts +2 -2
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/locales/en/parsers/ENCasualDateParser.js +12 -6
- package/dist/esm/locales/en/parsers/ENCasualDateParser.js.map +1 -1
- package/dist/esm/locales/en/parsers/ENCasualTimeParser.d.ts +1 -1
- package/dist/esm/locales/en/parsers/ENCasualTimeParser.js +15 -6
- package/dist/esm/locales/en/parsers/ENCasualTimeParser.js.map +1 -1
- package/dist/esm/locales/en/parsers/ENTimeExpressionParser.js +23 -22
- package/dist/esm/locales/en/parsers/ENTimeExpressionParser.js.map +1 -1
- package/dist/esm/locales/en/parsers/ENTimeUnitWithinFormatParser.js +3 -2
- package/dist/esm/locales/en/parsers/ENTimeUnitWithinFormatParser.js.map +1 -1
- package/dist/esm/locales/fr/refiners/FRMergeDateRangeRefiner.js +1 -1
- package/dist/esm/locales/fr/refiners/FRMergeDateRangeRefiner.js.map +1 -1
- package/dist/esm/locales/fr/refiners/FRMergeDateTimeRefiner.js +1 -1
- package/dist/esm/locales/fr/refiners/FRMergeDateTimeRefiner.js.map +1 -1
- package/dist/esm/results.d.ts +5 -0
- package/dist/esm/results.js +30 -2
- package/dist/esm/results.js.map +1 -1
- package/dist/esm/types.d.ts +2 -0
- package/dist/esm/types.js.map +1 -1
- package/package.json +1 -1
- package/src/calculation/mergingCalculation.ts +2 -0
- package/src/common/casualReferences.ts +13 -3
- package/src/common/parsers/AbstractTimeExpressionParser.ts +2 -2
- package/src/index.ts +2 -2
- package/src/locales/en/parsers/ENCasualDateParser.ts +12 -7
- package/src/locales/en/parsers/ENCasualTimeParser.ts +15 -6
- package/src/locales/en/parsers/ENTimeExpressionParser.ts +24 -22
- package/src/locales/en/parsers/ENTimeUnitWithinFormatParser.ts +4 -3
- package/src/locales/fr/refiners/FRMergeDateRangeRefiner.ts +1 -1
- package/src/locales/fr/refiners/FRMergeDateTimeRefiner.ts +1 -1
- package/src/results.ts +34 -4
- package/src/types.ts +11 -1
- package/test/en/en_slash.test.ts +34 -0
- package/test/en/en_time_exp.test.ts +11 -0
- package/test/en/en_time_units_within.test.ts +22 -1
- package/test/fr/fr_casual.test.ts +10 -0
- package/test/result.test.ts +36 -3
- package/test/system.test.ts +37 -0
package/package.json
CHANGED
|
@@ -17,6 +17,7 @@ export function now(reference: ReferenceWithTimezone): ParsingComponents {
|
|
|
17
17
|
if (reference.timezoneOffset !== null) {
|
|
18
18
|
component.assign("timezoneOffset", targetDate.utcOffset());
|
|
19
19
|
}
|
|
20
|
+
component.addTag("casualReference/now");
|
|
20
21
|
return component;
|
|
21
22
|
}
|
|
22
23
|
|
|
@@ -25,6 +26,7 @@ export function today(reference: ReferenceWithTimezone): ParsingComponents {
|
|
|
25
26
|
const component = new ParsingComponents(reference, {});
|
|
26
27
|
assignSimilarDate(component, targetDate);
|
|
27
28
|
implySimilarTime(component, targetDate);
|
|
29
|
+
component.addTag("casualReference/today");
|
|
28
30
|
return component;
|
|
29
31
|
}
|
|
30
32
|
|
|
@@ -32,7 +34,7 @@ export function today(reference: ReferenceWithTimezone): ParsingComponents {
|
|
|
32
34
|
* The previous day. Imply the same time.
|
|
33
35
|
*/
|
|
34
36
|
export function yesterday(reference: ReferenceWithTimezone): ParsingComponents {
|
|
35
|
-
return theDayBefore(reference, 1);
|
|
37
|
+
return theDayBefore(reference, 1).addTag("casualReference/yesterday");
|
|
36
38
|
}
|
|
37
39
|
|
|
38
40
|
export function theDayBefore(reference: ReferenceWithTimezone, numDay: number): ParsingComponents {
|
|
@@ -43,7 +45,7 @@ export function theDayBefore(reference: ReferenceWithTimezone, numDay: number):
|
|
|
43
45
|
* The following day with dayjs.assignTheNextDay()
|
|
44
46
|
*/
|
|
45
47
|
export function tomorrow(reference: ReferenceWithTimezone): ParsingComponents {
|
|
46
|
-
return theDayAfter(reference, 1);
|
|
48
|
+
return theDayAfter(reference, 1).addTag("casualReference/tomorrow");
|
|
47
49
|
}
|
|
48
50
|
|
|
49
51
|
export function theDayAfter(reference: ReferenceWithTimezone, nDays: number): ParsingComponents {
|
|
@@ -58,9 +60,10 @@ export function theDayAfter(reference: ReferenceWithTimezone, nDays: number): Pa
|
|
|
58
60
|
export function tonight(reference: ReferenceWithTimezone, implyHour = 22): ParsingComponents {
|
|
59
61
|
const targetDate = dayjs(reference.instant);
|
|
60
62
|
const component = new ParsingComponents(reference, {});
|
|
63
|
+
assignSimilarDate(component, targetDate);
|
|
61
64
|
component.imply("hour", implyHour);
|
|
62
65
|
component.imply("meridiem", Meridiem.PM);
|
|
63
|
-
|
|
66
|
+
component.addTag("casualReference/tonight");
|
|
64
67
|
return component;
|
|
65
68
|
}
|
|
66
69
|
|
|
@@ -79,6 +82,7 @@ export function evening(reference: ReferenceWithTimezone, implyHour = 20): Parsi
|
|
|
79
82
|
const component = new ParsingComponents(reference, {});
|
|
80
83
|
component.imply("meridiem", Meridiem.PM);
|
|
81
84
|
component.imply("hour", implyHour);
|
|
85
|
+
component.addTag("casualReference/evening");
|
|
82
86
|
return component;
|
|
83
87
|
}
|
|
84
88
|
|
|
@@ -89,6 +93,8 @@ export function yesterdayEvening(reference: ReferenceWithTimezone, implyHour = 2
|
|
|
89
93
|
assignSimilarDate(component, targetDate);
|
|
90
94
|
component.imply("hour", implyHour);
|
|
91
95
|
component.imply("meridiem", Meridiem.PM);
|
|
96
|
+
component.addTag("casualReference/yesterday");
|
|
97
|
+
component.addTag("casualReference/evening");
|
|
92
98
|
return component;
|
|
93
99
|
}
|
|
94
100
|
|
|
@@ -104,6 +110,7 @@ export function midnight(reference: ReferenceWithTimezone): ParsingComponents {
|
|
|
104
110
|
component.imply("minute", 0);
|
|
105
111
|
component.imply("second", 0);
|
|
106
112
|
component.imply("millisecond", 0);
|
|
113
|
+
component.addTag("casualReference/midnight");
|
|
107
114
|
return component;
|
|
108
115
|
}
|
|
109
116
|
|
|
@@ -114,6 +121,7 @@ export function morning(reference: ReferenceWithTimezone, implyHour = 6): Parsin
|
|
|
114
121
|
component.imply("minute", 0);
|
|
115
122
|
component.imply("second", 0);
|
|
116
123
|
component.imply("millisecond", 0);
|
|
124
|
+
component.addTag("casualReference/morning");
|
|
117
125
|
return component;
|
|
118
126
|
}
|
|
119
127
|
|
|
@@ -124,6 +132,7 @@ export function afternoon(reference: ReferenceWithTimezone, implyHour = 15): Par
|
|
|
124
132
|
component.imply("minute", 0);
|
|
125
133
|
component.imply("second", 0);
|
|
126
134
|
component.imply("millisecond", 0);
|
|
135
|
+
component.addTag("casualReference/afternoon");
|
|
127
136
|
return component;
|
|
128
137
|
}
|
|
129
138
|
|
|
@@ -134,5 +143,6 @@ export function noon(reference: ReferenceWithTimezone): ParsingComponents {
|
|
|
134
143
|
component.imply("minute", 0);
|
|
135
144
|
component.imply("second", 0);
|
|
136
145
|
component.imply("millisecond", 0);
|
|
146
|
+
component.addTag("casualReference/noon");
|
|
137
147
|
return component;
|
|
138
148
|
}
|
|
@@ -66,11 +66,11 @@ export abstract class AbstractTimeExpressionParser implements Parser {
|
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
primarySuffix(): string {
|
|
69
|
-
return `(?=\\W|$)`;
|
|
69
|
+
return `(?!/)(?=\\W|$)`;
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
followingSuffix(): string {
|
|
73
|
-
return `(?=\\W|$)`;
|
|
73
|
+
return `(?!/)(?=\\W|$)`;
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
pattern(context: ParsingContext): RegExp {
|
package/src/index.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import * as en from "./locales/en";
|
|
2
2
|
import { Chrono, Parser, Refiner } from "./chrono";
|
|
3
3
|
import { ParsingResult, ParsingComponents, ReferenceWithTimezone } from "./results";
|
|
4
|
-
import { Component, ParsedResult, ParsingOption, ParsingReference, Meridiem, Weekday } from "./types";
|
|
4
|
+
import { Component, ParsedComponents, ParsedResult, ParsingOption, ParsingReference, Meridiem, Weekday } from "./types";
|
|
5
5
|
|
|
6
6
|
export { en, Chrono, Parser, Refiner, ParsingResult, ParsingComponents, ReferenceWithTimezone };
|
|
7
|
-
export { Component, ParsedResult, ParsingOption, ParsingReference, Meridiem, Weekday };
|
|
7
|
+
export { Component, ParsedComponents, ParsedResult, ParsingOption, ParsingReference, Meridiem, Weekday };
|
|
8
8
|
|
|
9
9
|
// Export all locales
|
|
10
10
|
import * as de from "./locales/de";
|
|
@@ -15,25 +15,30 @@ export default class ENCasualDateParser extends AbstractParserWithWordBoundaryCh
|
|
|
15
15
|
innerExtract(context: ParsingContext, match: RegExpMatchArray): ParsingComponents | ParsingResult {
|
|
16
16
|
let targetDate = dayjs(context.refDate);
|
|
17
17
|
const lowerText = match[0].toLowerCase();
|
|
18
|
-
|
|
18
|
+
let component = context.createParsingComponents();
|
|
19
19
|
|
|
20
20
|
switch (lowerText) {
|
|
21
21
|
case "now":
|
|
22
|
-
|
|
22
|
+
component = references.now(context.reference);
|
|
23
|
+
break;
|
|
23
24
|
|
|
24
25
|
case "today":
|
|
25
|
-
|
|
26
|
+
component = references.today(context.reference);
|
|
27
|
+
break;
|
|
26
28
|
|
|
27
29
|
case "yesterday":
|
|
28
|
-
|
|
30
|
+
component = references.yesterday(context.reference);
|
|
31
|
+
break;
|
|
29
32
|
|
|
30
33
|
case "tomorrow":
|
|
31
34
|
case "tmr":
|
|
32
35
|
case "tmrw":
|
|
33
|
-
|
|
36
|
+
component = references.tomorrow(context.reference);
|
|
37
|
+
break;
|
|
34
38
|
|
|
35
39
|
case "tonight":
|
|
36
|
-
|
|
40
|
+
component = references.tonight(context.reference);
|
|
41
|
+
break;
|
|
37
42
|
|
|
38
43
|
default:
|
|
39
44
|
if (lowerText.match(/last\s*night/)) {
|
|
@@ -46,7 +51,7 @@ export default class ENCasualDateParser extends AbstractParserWithWordBoundaryCh
|
|
|
46
51
|
}
|
|
47
52
|
break;
|
|
48
53
|
}
|
|
49
|
-
|
|
54
|
+
component.addTag("parser/ENCasualDateParser");
|
|
50
55
|
return component;
|
|
51
56
|
}
|
|
52
57
|
}
|
|
@@ -9,20 +9,29 @@ export default class ENCasualTimeParser extends AbstractParserWithWordBoundaryCh
|
|
|
9
9
|
return PATTERN;
|
|
10
10
|
}
|
|
11
11
|
innerExtract(context: ParsingContext, match: RegExpMatchArray) {
|
|
12
|
+
let component = null;
|
|
12
13
|
switch (match[1].toLowerCase()) {
|
|
13
14
|
case "afternoon":
|
|
14
|
-
|
|
15
|
+
component = casualReferences.afternoon(context.reference);
|
|
16
|
+
break;
|
|
15
17
|
case "evening":
|
|
16
18
|
case "night":
|
|
17
|
-
|
|
19
|
+
component = casualReferences.evening(context.reference);
|
|
20
|
+
break;
|
|
18
21
|
case "midnight":
|
|
19
|
-
|
|
22
|
+
component = casualReferences.midnight(context.reference);
|
|
23
|
+
break;
|
|
20
24
|
case "morning":
|
|
21
|
-
|
|
25
|
+
component = casualReferences.morning(context.reference);
|
|
26
|
+
break;
|
|
22
27
|
case "noon":
|
|
23
28
|
case "midday":
|
|
24
|
-
|
|
29
|
+
component = casualReferences.noon(context.reference);
|
|
30
|
+
break;
|
|
25
31
|
}
|
|
26
|
-
|
|
32
|
+
if (component) {
|
|
33
|
+
component.addTag("parser/ENCasualTimeParser");
|
|
34
|
+
}
|
|
35
|
+
return component;
|
|
27
36
|
}
|
|
28
37
|
}
|
|
@@ -22,34 +22,36 @@ export default class ENTimeExpressionParser extends AbstractTimeExpressionParser
|
|
|
22
22
|
|
|
23
23
|
extractPrimaryTimeComponents(context: ParsingContext, match: RegExpMatchArray): null | ParsingComponents {
|
|
24
24
|
const components = super.extractPrimaryTimeComponents(context, match);
|
|
25
|
-
if (components) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
if (hour >= 6 && hour < 12) {
|
|
29
|
-
components.assign("hour", components.get("hour") + 12);
|
|
30
|
-
components.assign("meridiem", Meridiem.PM);
|
|
31
|
-
} else if (hour < 6) {
|
|
32
|
-
components.assign("meridiem", Meridiem.AM);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
25
|
+
if (!components) {
|
|
26
|
+
return components;
|
|
27
|
+
}
|
|
35
28
|
|
|
36
|
-
|
|
29
|
+
if (match[0].endsWith("night")) {
|
|
30
|
+
const hour = components.get("hour");
|
|
31
|
+
if (hour >= 6 && hour < 12) {
|
|
32
|
+
components.assign("hour", components.get("hour") + 12);
|
|
37
33
|
components.assign("meridiem", Meridiem.PM);
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
34
|
+
} else if (hour < 6) {
|
|
35
|
+
components.assign("meridiem", Meridiem.AM);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (match[0].endsWith("afternoon")) {
|
|
40
|
+
components.assign("meridiem", Meridiem.PM);
|
|
41
|
+
const hour = components.get("hour");
|
|
42
|
+
if (hour >= 0 && hour <= 6) {
|
|
43
|
+
components.assign("hour", components.get("hour") + 12);
|
|
42
44
|
}
|
|
45
|
+
}
|
|
43
46
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}
|
|
47
|
+
if (match[0].endsWith("morning")) {
|
|
48
|
+
components.assign("meridiem", Meridiem.AM);
|
|
49
|
+
const hour = components.get("hour");
|
|
50
|
+
if (hour < 12) {
|
|
51
|
+
components.assign("hour", components.get("hour"));
|
|
50
52
|
}
|
|
51
53
|
}
|
|
52
54
|
|
|
53
|
-
return components;
|
|
55
|
+
return components.addTag("parser/ENTimeExpressionParser");
|
|
54
56
|
}
|
|
55
57
|
}
|
|
@@ -3,8 +3,9 @@ import { ParsingContext } from "../../../chrono";
|
|
|
3
3
|
import { ParsingComponents } from "../../../results";
|
|
4
4
|
import { AbstractParserWithWordBoundaryChecking } from "../../../common/parsers/AbstractParserWithWordBoundary";
|
|
5
5
|
|
|
6
|
-
const
|
|
7
|
-
`(?:(?:
|
|
6
|
+
const PATTERN_WITH_OPTIONAL_PREFIX = new RegExp(
|
|
7
|
+
`(?:(?:within|in|for)\\s*)?` +
|
|
8
|
+
`(?:(?:about|around|roughly|approximately|just)\\s*(?:~\\s*)?)?(${TIME_UNITS_PATTERN})(?=\\W|$)`,
|
|
8
9
|
"i"
|
|
9
10
|
);
|
|
10
11
|
|
|
@@ -29,7 +30,7 @@ export default class ENTimeUnitWithinFormatParser extends AbstractParserWithWord
|
|
|
29
30
|
if (this.strictMode) {
|
|
30
31
|
return PATTERN_WITH_PREFIX_STRICT;
|
|
31
32
|
}
|
|
32
|
-
return context.option.forwardDate ?
|
|
33
|
+
return context.option.forwardDate ? PATTERN_WITH_OPTIONAL_PREFIX : PATTERN_WITH_PREFIX;
|
|
33
34
|
}
|
|
34
35
|
|
|
35
36
|
innerExtract(context: ParsingContext, match: RegExpMatchArray): ParsingComponents {
|
|
@@ -10,6 +10,6 @@ import AbstractMergeDateRangeRefiner from "../../../common/refiners/AbstractMerg
|
|
|
10
10
|
*/
|
|
11
11
|
export default class FRMergeDateRangeRefiner extends AbstractMergeDateRangeRefiner {
|
|
12
12
|
patternBetween(): RegExp {
|
|
13
|
-
return /^\s*(à|a|-)\s*$/i;
|
|
13
|
+
return /^\s*(à|a|au|-)\s*$/i;
|
|
14
14
|
}
|
|
15
15
|
}
|
|
@@ -5,6 +5,6 @@ import AbstractMergeDateTimeRefiner from "../../../common/refiners/AbstractMerge
|
|
|
5
5
|
*/
|
|
6
6
|
export default class FRMergeDateTimeRefiner extends AbstractMergeDateTimeRefiner {
|
|
7
7
|
patternBetween(): RegExp {
|
|
8
|
-
return new RegExp("^\\s*(T|à|a|vers|de|,|-)?\\s*$");
|
|
8
|
+
return new RegExp("^\\s*(T|à|a|au|vers|de|,|-)?\\s*$");
|
|
9
9
|
}
|
|
10
10
|
}
|
package/src/results.ts
CHANGED
|
@@ -50,6 +50,7 @@ export class ParsingComponents implements ParsedComponents {
|
|
|
50
50
|
private knownValues: { [c in Component]?: number };
|
|
51
51
|
private impliedValues: { [c in Component]?: number };
|
|
52
52
|
private reference: ReferenceWithTimezone;
|
|
53
|
+
private _tags = new Set<string>();
|
|
53
54
|
|
|
54
55
|
constructor(reference: ReferenceWithTimezone, knownComponents?: { [c in Component]?: number }) {
|
|
55
56
|
this.reference = reference;
|
|
@@ -155,9 +156,11 @@ export class ParsingComponents implements ParsedComponents {
|
|
|
155
156
|
}
|
|
156
157
|
|
|
157
158
|
toString() {
|
|
158
|
-
return `[ParsingComponents {
|
|
159
|
-
this.
|
|
160
|
-
|
|
159
|
+
return `[ParsingComponents {
|
|
160
|
+
tags: ${JSON.stringify(Array.from(this._tags).sort())},
|
|
161
|
+
knownValues: ${JSON.stringify(this.knownValues)},
|
|
162
|
+
impliedValues: ${JSON.stringify(this.impliedValues)}},
|
|
163
|
+
reference: ${JSON.stringify(this.reference)}]`;
|
|
161
164
|
}
|
|
162
165
|
|
|
163
166
|
dayjs() {
|
|
@@ -170,6 +173,22 @@ export class ParsingComponents implements ParsedComponents {
|
|
|
170
173
|
return new Date(date.getTime() + timezoneAdjustment * 60000);
|
|
171
174
|
}
|
|
172
175
|
|
|
176
|
+
addTag(tag: string): ParsingComponents {
|
|
177
|
+
this._tags.add(tag);
|
|
178
|
+
return this;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
addTags(tags: string[] | Set<string>): ParsingComponents {
|
|
182
|
+
for (const tag of tags) {
|
|
183
|
+
this._tags.add(tag);
|
|
184
|
+
}
|
|
185
|
+
return this;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
tags(): Set<string> {
|
|
189
|
+
return new Set(this._tags);
|
|
190
|
+
}
|
|
191
|
+
|
|
173
192
|
private dateWithoutTimezoneAdjustment() {
|
|
174
193
|
const date = new Date(
|
|
175
194
|
this.get("year"),
|
|
@@ -271,7 +290,18 @@ export class ParsingResult implements ParsedResult {
|
|
|
271
290
|
return this.start.date();
|
|
272
291
|
}
|
|
273
292
|
|
|
293
|
+
tags(): Set<string> {
|
|
294
|
+
const combinedTags: Set<string> = new Set(this.start.tags());
|
|
295
|
+
if (this.end) {
|
|
296
|
+
for (const tag of this.end.tags()) {
|
|
297
|
+
combinedTags.add(tag);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
return combinedTags;
|
|
301
|
+
}
|
|
302
|
+
|
|
274
303
|
toString() {
|
|
275
|
-
|
|
304
|
+
const tags = Array.from(this.tags()).sort();
|
|
305
|
+
return `[ParsingResult {index: ${this.index}, text: '${this.text}', tags: ${JSON.stringify(tags)} ...}]`;
|
|
276
306
|
}
|
|
277
307
|
}
|
package/src/types.ts
CHANGED
|
@@ -77,9 +77,14 @@ export interface ParsedResult {
|
|
|
77
77
|
readonly end?: ParsedComponents;
|
|
78
78
|
|
|
79
79
|
/**
|
|
80
|
-
*
|
|
80
|
+
* @return a javascript date object created from the `result.start`.
|
|
81
81
|
*/
|
|
82
82
|
date(): Date;
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* @return debugging tags combined of the `result.start` and `result.end`.
|
|
86
|
+
*/
|
|
87
|
+
tags(): Set<string>;
|
|
83
88
|
}
|
|
84
89
|
|
|
85
90
|
/**
|
|
@@ -105,6 +110,11 @@ export interface ParsedComponents {
|
|
|
105
110
|
* @return a javascript date object.
|
|
106
111
|
*/
|
|
107
112
|
date(): Date;
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* @return debugging tags of the parsed component.
|
|
116
|
+
*/
|
|
117
|
+
tags(): Set<string>;
|
|
108
118
|
}
|
|
109
119
|
|
|
110
120
|
export type Component =
|
package/test/en/en_slash.test.ts
CHANGED
|
@@ -159,6 +159,40 @@ test("Test - Range Expression", function () {
|
|
|
159
159
|
});
|
|
160
160
|
});
|
|
161
161
|
|
|
162
|
+
test("Test - Range Expressions with Time", function () {
|
|
163
|
+
testSingleCase(chrono.en, "from 01/21/2021 10:00 to 01/01/2023 07:00", new Date(2012, 7, 10), (result) => {
|
|
164
|
+
expect(result.start).not.toBeNull();
|
|
165
|
+
expect(result.start.get("year")).toBe(2021);
|
|
166
|
+
expect(result.start.get("month")).toBe(1);
|
|
167
|
+
expect(result.start.get("day")).toBe(21);
|
|
168
|
+
expect(result.start.get("hour")).toBe(10);
|
|
169
|
+
expect(result.start.get("minute")).toBe(0);
|
|
170
|
+
|
|
171
|
+
expect(result.end).not.toBeNull();
|
|
172
|
+
expect(result.end.get("year")).toBe(2023);
|
|
173
|
+
expect(result.end.get("month")).toBe(1);
|
|
174
|
+
expect(result.end.get("day")).toBe(1);
|
|
175
|
+
expect(result.end.get("hour")).toBe(7);
|
|
176
|
+
expect(result.end.get("minute")).toBe(0);
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
testSingleCase(chrono.en, "08/08/2023, 09:15 AM to 08/29/2023, 09:15 AM", new Date(2012, 7, 10), (result) => {
|
|
180
|
+
expect(result.start).not.toBeNull();
|
|
181
|
+
expect(result.start.get("year")).toBe(2023);
|
|
182
|
+
expect(result.start.get("month")).toBe(8);
|
|
183
|
+
expect(result.start.get("day")).toBe(8);
|
|
184
|
+
expect(result.start.get("hour")).toBe(9);
|
|
185
|
+
expect(result.start.get("minute")).toBe(15);
|
|
186
|
+
|
|
187
|
+
expect(result.end).not.toBeNull();
|
|
188
|
+
expect(result.end.get("year")).toBe(2023);
|
|
189
|
+
expect(result.end.get("month")).toBe(8);
|
|
190
|
+
expect(result.end.get("day")).toBe(29);
|
|
191
|
+
expect(result.end.get("hour")).toBe(9);
|
|
192
|
+
expect(result.end.get("minute")).toBe(15);
|
|
193
|
+
});
|
|
194
|
+
});
|
|
195
|
+
|
|
162
196
|
test("Test - Splitter variances patterns", function () {
|
|
163
197
|
const expectDate = new Date(2015, 5 - 1, 25, 12, 0);
|
|
164
198
|
|
|
@@ -82,6 +82,17 @@ test("Test - Time range expression", function () {
|
|
|
82
82
|
});
|
|
83
83
|
});
|
|
84
84
|
|
|
85
|
+
test("Test - Time non-range expression", function () {
|
|
86
|
+
testSingleCase(chrono, "10:00:00 - 15/15", new Date(2016, 10 - 1, 1, 8), (result, text) => {
|
|
87
|
+
expect(result.text).toBe("10:00:00");
|
|
88
|
+
|
|
89
|
+
expect(result.start.get("hour")).toBe(10);
|
|
90
|
+
expect(result.start.get("minute")).toBe(0);
|
|
91
|
+
expect(result.start.get("second")).toBe(0);
|
|
92
|
+
expect(result.start.get("meridiem")).toBe(Meridiem.AM);
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
|
|
85
96
|
test("Test - Casual time number expression", function () {
|
|
86
97
|
testSingleCase(chrono, "11 at night", new Date(2016, 10 - 1, 1, 8), (result, text) => {
|
|
87
98
|
expect(result.text).toBe(text);
|
|
@@ -336,7 +336,7 @@ test("Test - Time units' certainty", () => {
|
|
|
336
336
|
});
|
|
337
337
|
});
|
|
338
338
|
|
|
339
|
-
test("Test - Strict mode",
|
|
339
|
+
test("Test - Strict mode", () => {
|
|
340
340
|
testSingleCase(chrono, "in 2hour", new Date(2016, 10 - 1, 1, 14, 52), (result, text) => {
|
|
341
341
|
expect(result.start.get("hour")).toBe(16);
|
|
342
342
|
expect(result.start.get("minute")).toBe(52);
|
|
@@ -345,3 +345,24 @@ test("Test - Strict mode", function () {
|
|
|
345
345
|
testUnexpectedResult(chrono.strict, "in 15m");
|
|
346
346
|
testUnexpectedResult(chrono.strict, "within 5hr");
|
|
347
347
|
});
|
|
348
|
+
|
|
349
|
+
test("Test - Forward date option", () => {
|
|
350
|
+
testSingleCase(chrono, "1 hour", new Date(2012, 7, 10, 12, 14), { forwardDate: true }, (result) => {
|
|
351
|
+
expect(result.text).toBe("1 hour");
|
|
352
|
+
expect(result.start).toBeDate(new Date(2012, 7, 10, 13, 14));
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
testSingleCase(chrono, "1 month", new Date(2016, 10 - 1, 1, 14, 52), { forwardDate: true }, (result, text) => {
|
|
356
|
+
expect(result.text).toBe("1 month");
|
|
357
|
+
expect(result.start.get("year")).toBe(2016);
|
|
358
|
+
expect(result.start.get("month")).toBe(11);
|
|
359
|
+
expect(result.start.get("day")).toBe(1);
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
testSingleCase(chrono, "in 1 month", new Date(2016, 10 - 1, 1, 14, 52), { forwardDate: true }, (result, text) => {
|
|
363
|
+
expect(result.text).toBe("in 1 month");
|
|
364
|
+
expect(result.start.get("year")).toBe(2016);
|
|
365
|
+
expect(result.start.get("month")).toBe(11);
|
|
366
|
+
expect(result.start.get("day")).toBe(1);
|
|
367
|
+
});
|
|
368
|
+
});
|
|
@@ -132,6 +132,16 @@ test("Test - Single Expression", function () {
|
|
|
132
132
|
expect(result.text).toBe(text);
|
|
133
133
|
expect(result.start.get("hour")).toBe(0);
|
|
134
134
|
});
|
|
135
|
+
|
|
136
|
+
testSingleCase(chrono.fr, "Du 24 août 2023 au 26 août 2023", (result) => {
|
|
137
|
+
expect(result.text).toBe("24 août 2023 au 26 août 2023");
|
|
138
|
+
expect(result.start.get("year")).toBe(2023);
|
|
139
|
+
expect(result.start.get("month")).toBe(8);
|
|
140
|
+
expect(result.start.get("day")).toBe(24);
|
|
141
|
+
expect(result.end.get("year")).toBe(2023);
|
|
142
|
+
expect(result.end.get("month")).toBe(8);
|
|
143
|
+
expect(result.end.get("day")).toBe(26);
|
|
144
|
+
});
|
|
135
145
|
});
|
|
136
146
|
|
|
137
147
|
test("Test - Combined Expression", function () {
|
package/test/result.test.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { ParsingComponents, ReferenceWithTimezone } from "../src/results";
|
|
1
|
+
import { ParsingComponents, ParsingResult, ReferenceWithTimezone } from "../src/results";
|
|
2
2
|
|
|
3
|
-
test("Test - Create & manipulate
|
|
3
|
+
test("Test - Create & manipulate parsing components", () => {
|
|
4
4
|
const reference = new ReferenceWithTimezone(new Date());
|
|
5
5
|
const components = new ParsingComponents(reference, { year: 2014, month: 11, day: 24 });
|
|
6
6
|
|
|
@@ -8,6 +8,7 @@ test("Test - Create & manipulate date results", () => {
|
|
|
8
8
|
expect(components.get("month")).toBe(11);
|
|
9
9
|
expect(components.get("day")).toBe(24);
|
|
10
10
|
expect(components.date()).toBeDefined();
|
|
11
|
+
expect(components.tags().size).toBe(0);
|
|
11
12
|
|
|
12
13
|
// null
|
|
13
14
|
expect(components.get("weekday")).toBeNull();
|
|
@@ -23,13 +24,45 @@ test("Test - Create & manipulate date results", () => {
|
|
|
23
24
|
expect(components.get("weekday")).toBe(2);
|
|
24
25
|
expect(components.isCertain("weekday")).toBe(true);
|
|
25
26
|
|
|
26
|
-
// "imply" doesn't
|
|
27
|
+
// "imply" doesn't override "assign"
|
|
27
28
|
components.imply("year", 2013);
|
|
28
29
|
expect(components.get("year")).toBe(2014);
|
|
29
30
|
|
|
30
31
|
// "assign" overrides "assign"
|
|
31
32
|
components.assign("year", 2013);
|
|
32
33
|
expect(components.get("year")).toBe(2013);
|
|
34
|
+
|
|
35
|
+
components.addTag("custom/testing_component_tag");
|
|
36
|
+
expect(components.tags().size).toBe(1);
|
|
37
|
+
expect(components.tags()).toContain("custom/testing_component_tag");
|
|
38
|
+
expect(components.toString()).toContain("custom/testing_component_tag");
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
test("Test - Create & manipulate parsing results", () => {
|
|
42
|
+
const reference = new ReferenceWithTimezone(new Date());
|
|
43
|
+
const text = "1 - 2 hour later";
|
|
44
|
+
|
|
45
|
+
const startComponents = ParsingComponents.createRelativeFromReference(reference, { "hour": 1 }).addTag(
|
|
46
|
+
"custom/testing_start_component_tag"
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
const endComponents = ParsingComponents.createRelativeFromReference(reference, { "hour": 2 }).addTag(
|
|
50
|
+
"custom/testing_end_component_tag"
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
const result = new ParsingResult(reference, 0, text, startComponents, endComponents);
|
|
54
|
+
|
|
55
|
+
// The result's date() should be the same as the start components' date()
|
|
56
|
+
expect(result.date()).toStrictEqual(startComponents.date());
|
|
57
|
+
|
|
58
|
+
// The result's tags should include both the start and end components' tags
|
|
59
|
+
expect(result.tags()).toContain("custom/testing_start_component_tag");
|
|
60
|
+
expect(result.tags()).toContain("custom/testing_end_component_tag");
|
|
61
|
+
|
|
62
|
+
// The result's toString() should include the text and tags
|
|
63
|
+
expect(result.toString()).toContain(text);
|
|
64
|
+
expect(result.toString()).toContain("custom/testing_start_component_tag");
|
|
65
|
+
expect(result.toString()).toContain("custom/testing_end_component_tag");
|
|
33
66
|
});
|
|
34
67
|
|
|
35
68
|
test("Test - Calendar checking with implied components", () => {
|
package/test/system.test.ts
CHANGED
|
@@ -5,6 +5,7 @@ import UnlikelyFormatFilter from "../src/common/refiners/UnlikelyFormatFilter";
|
|
|
5
5
|
import SlashDateFormatParser from "../src/common/parsers/SlashDateFormatParser";
|
|
6
6
|
import ENWeekdayParser from "../src/locales/en/parsers/ENWeekdayParser";
|
|
7
7
|
import ENTimeUnitCasualRelativeFormatParser from "../src/locales/en/parsers/ENTimeUnitCasualRelativeFormatParser";
|
|
8
|
+
import { ParsingComponents } from "../src/";
|
|
8
9
|
|
|
9
10
|
//-------------------------------------
|
|
10
11
|
|
|
@@ -124,6 +125,42 @@ test("Test - Add custom refiner example", () => {
|
|
|
124
125
|
});
|
|
125
126
|
});
|
|
126
127
|
|
|
128
|
+
test("Test - Add custom parser with tags example", () => {
|
|
129
|
+
const custom = chrono.casual.clone();
|
|
130
|
+
custom.parsers.push({
|
|
131
|
+
pattern: () => {
|
|
132
|
+
return /\bChristmas\b/i;
|
|
133
|
+
},
|
|
134
|
+
extract: (context) => {
|
|
135
|
+
return context
|
|
136
|
+
.createParsingComponents({
|
|
137
|
+
day: 25,
|
|
138
|
+
month: 12,
|
|
139
|
+
})
|
|
140
|
+
.addTag("parser/ChristmasDayParser");
|
|
141
|
+
},
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
testSingleCase(custom, "Doing something tomorrow", (result) => {
|
|
145
|
+
expect(result.text).toBe("tomorrow");
|
|
146
|
+
expect(result.tags()).toContain("parser/ENCasualDateParser");
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
testSingleCase(custom, "I'll arrive at 2.30AM on Christmas", (result) => {
|
|
150
|
+
expect(result.text).toBe("at 2.30AM on Christmas");
|
|
151
|
+
expect(result.tags()).toContain("parser/ChristmasDayParser");
|
|
152
|
+
expect(result.tags()).toContain("parser/ENTimeExpressionParser");
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
testSingleCase(custom, "I'll arrive at Christmas night", (result) => {
|
|
156
|
+
expect(result.text).toBe("Christmas night");
|
|
157
|
+
expect(result.tags()).toContain("parser/ChristmasDayParser");
|
|
158
|
+
expect(result.tags()).toContain("parser/ENCasualTimeParser");
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
// TODO: Check if the merge date range combine tags correctly
|
|
162
|
+
});
|
|
163
|
+
|
|
127
164
|
test("Test - Remove a parser example", () => {
|
|
128
165
|
const custom = chrono.en.strict.clone();
|
|
129
166
|
custom.parsers = custom.parsers.filter((r) => !(r instanceof SlashDateFormatParser));
|