chrono-node 2.2.7 → 2.3.3
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/README.md +25 -9
- package/benchmark/benchmark.js +4 -0
- package/dist/bundle.js +5047 -0
- package/dist/chrono.d.ts +7 -6
- package/dist/chrono.js +6 -5
- package/dist/common/casualReferences.d.ts +6 -6
- package/dist/common/casualReferences.js +16 -15
- package/dist/common/refiners/ForwardDateRefiner.js +1 -1
- package/dist/index.d.ts +7 -3
- package/dist/locales/de/constants.js +1 -1
- package/dist/locales/de/parsers/DECasualDateParser.js +2 -2
- package/dist/locales/en/constants.d.ts +1 -1
- package/dist/locales/en/constants.js +5 -5
- package/dist/locales/en/parsers/ENCasualDateParser.js +5 -5
- package/dist/locales/en/parsers/ENCasualTimeParser.js +1 -1
- package/dist/locales/en/parsers/ENMonthNameLittleEndianParser.js +6 -8
- package/dist/locales/en/parsers/ENRelativeDateFormatParser.js +3 -3
- package/dist/locales/en/parsers/ENTimeUnitAgoFormatParser.js +3 -3
- package/dist/locales/en/parsers/ENTimeUnitCasualRelativeFormatParser.js +1 -1
- package/dist/locales/en/parsers/ENTimeUnitLaterFormatParser.js +2 -2
- package/dist/locales/en/parsers/ENTimeUnitWithinFormatParser.js +1 -1
- package/dist/locales/fr/constants.js +1 -1
- package/dist/locales/fr/parsers/FRCasualDateParser.js +4 -4
- package/dist/locales/fr/parsers/FRTimeUnitAgoFormatParser.js +1 -1
- package/dist/locales/fr/parsers/FRTimeUnitRelativeFormatParser.js +1 -1
- package/dist/locales/fr/parsers/FRTimeUnitWithinFormatParser.js +1 -1
- package/dist/locales/ja/parsers/JPCasualDateParser.js +3 -3
- package/dist/locales/nl/constants.js +8 -5
- package/dist/locales/nl/index.js +12 -3
- package/dist/locales/nl/parsers/NLCasualDateParser.js +4 -4
- package/dist/locales/nl/parsers/NLRelativeDateFormatParser.d.ts +7 -0
- package/dist/locales/nl/parsers/NLRelativeDateFormatParser.js +57 -0
- package/dist/locales/nl/parsers/NLTimeExpressionParser.d.ts +1 -0
- package/dist/locales/nl/parsers/NLTimeExpressionParser.js +3 -0
- package/dist/locales/nl/parsers/NLTimeUnitAgoFormatParser.d.ts +9 -0
- package/dist/locales/nl/parsers/NLTimeUnitAgoFormatParser.js +23 -0
- package/dist/locales/nl/parsers/NLTimeUnitCasualRelativeFormatParser.d.ts +7 -0
- package/dist/locales/nl/parsers/NLTimeUnitCasualRelativeFormatParser.js +25 -0
- package/dist/locales/nl/parsers/NLTimeUnitLaterFormatParser.d.ts +9 -0
- package/dist/locales/nl/parsers/NLTimeUnitLaterFormatParser.js +22 -0
- package/dist/locales/nl/parsers/NLTimeUnitWithinFormatParser.js +1 -1
- package/dist/locales/pt/parsers/PTCasualDateParser.js +4 -4
- package/dist/main.js +1078 -0
- package/dist/results.d.ts +12 -5
- package/dist/results.js +40 -17
- package/dist/timezone.d.ts +194 -0
- package/dist/timezone.js +207 -0
- package/dist/utils/dayjs.js +0 -2
- package/dist/utils/pattern.js +1 -1
- package/package.json +3 -3
- package/src/chrono.ts +21 -8
- package/src/common/casualReferences.ts +17 -18
- package/src/common/refiners/ForwardDateRefiner.ts +1 -1
- package/src/index.ts +19 -3
- package/src/locales/de/constants.ts +1 -1
- package/src/locales/de/parsers/DECasualDateParser.ts +2 -2
- package/src/locales/en/constants.ts +5 -5
- package/src/locales/en/parsers/ENCasualDateParser.ts +5 -5
- package/src/locales/en/parsers/ENCasualTimeParser.ts +1 -1
- package/src/locales/en/parsers/ENMonthNameLittleEndianParser.ts +9 -10
- package/src/locales/en/parsers/ENRelativeDateFormatParser.ts +3 -3
- package/src/locales/en/parsers/ENTimeUnitAgoFormatParser.ts +3 -4
- package/src/locales/en/parsers/ENTimeUnitCasualRelativeFormatParser.ts +1 -1
- package/src/locales/en/parsers/ENTimeUnitLaterFormatParser.ts +2 -2
- package/src/locales/en/parsers/ENTimeUnitWithinFormatParser.ts +1 -1
- package/src/locales/fr/constants.ts +1 -1
- package/src/locales/fr/parsers/FRCasualDateParser.ts +4 -4
- package/src/locales/fr/parsers/FRTimeUnitAgoFormatParser.ts +1 -1
- package/src/locales/fr/parsers/FRTimeUnitRelativeFormatParser.ts +1 -1
- package/src/locales/fr/parsers/FRTimeUnitWithinFormatParser.ts +1 -1
- package/src/locales/ja/parsers/JPCasualDateParser.ts +3 -3
- package/src/locales/nl/constants.ts +11 -5
- package/src/locales/nl/index.ts +12 -3
- package/src/locales/nl/parsers/NLCasualDateParser.ts +4 -4
- package/src/locales/nl/parsers/NLRelativeDateFormatParser.ts +70 -0
- package/src/locales/nl/parsers/NLTimeExpressionParser.ts +4 -0
- package/src/locales/nl/parsers/NLTimeUnitAgoFormatParser.ts +26 -0
- package/src/locales/nl/parsers/NLTimeUnitCasualRelativeFormatParser.ts +27 -0
- package/src/locales/nl/parsers/NLTimeUnitLaterFormatParser.ts +27 -0
- package/src/locales/nl/parsers/NLTimeUnitWithinFormatParser.ts +1 -1
- package/src/locales/pt/parsers/PTCasualDateParser.ts +4 -4
- package/src/results.ts +52 -18
- package/src/timezone.ts +205 -0
- package/src/utils/dayjs.ts +0 -2
- package/src/utils/pattern.ts +1 -1
- package/test/en/en_month_name_little_endian.test.ts +10 -0
- package/test/en/en_relative.test.ts +30 -0
- package/test/en/en_slash.test.ts +11 -0
- package/test/en/en_timezone_exp.test.ts +7 -4
- package/test/en/en_weekday.test.ts +69 -25
- package/test/en/negative_cases.test.ts +2 -0
- package/test/nl/nl_relative.test.ts +212 -0
- package/test/nl/nl_time_units_ago.test.ts +243 -0
- package/test/nl/nl_time_units_casual_relative.test.ts +130 -0
- package/test/nl/nl_time_units_later.test.ts +250 -0
- package/test/result.test.ts +32 -13
- package/test/system_timezone.test.ts +100 -0
- package/test/test_util.ts +10 -7
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { TIME_UNITS_PATTERN, parseTimeUnits } from "../constants";
|
|
2
|
+
import { ParsingContext } from "../../../chrono";
|
|
3
|
+
import { ParsingComponents } from "../../../results";
|
|
4
|
+
import { AbstractParserWithWordBoundaryChecking } from "../../../common/parsers/AbstractParserWithWordBoundary";
|
|
5
|
+
import { reverseTimeUnits } from "../../../utils/timeunits";
|
|
6
|
+
|
|
7
|
+
const PATTERN = new RegExp(`(deze|vorige|afgelopen|komende|over|\\+|-)\\s*(${TIME_UNITS_PATTERN})(?=\\W|$)`, "i");
|
|
8
|
+
|
|
9
|
+
export default class NLTimeUnitCasualRelativeFormatParser extends AbstractParserWithWordBoundaryChecking {
|
|
10
|
+
innerPattern(): RegExp {
|
|
11
|
+
return PATTERN;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
innerExtract(context: ParsingContext, match: RegExpMatchArray): ParsingComponents {
|
|
15
|
+
const prefix = match[1].toLowerCase();
|
|
16
|
+
let timeUnits = parseTimeUnits(match[2]);
|
|
17
|
+
switch (prefix) {
|
|
18
|
+
case "vorige":
|
|
19
|
+
case "afgelopen":
|
|
20
|
+
case "-":
|
|
21
|
+
timeUnits = reverseTimeUnits(timeUnits);
|
|
22
|
+
break;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return ParsingComponents.createRelativeFromReference(context.reference, timeUnits);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { ParsingContext } from "../../../chrono";
|
|
2
|
+
import { parseTimeUnits, TIME_UNITS_PATTERN } from "../constants";
|
|
3
|
+
import { ParsingComponents } from "../../../results";
|
|
4
|
+
import { AbstractParserWithWordBoundaryChecking } from "../../../common/parsers/AbstractParserWithWordBoundary";
|
|
5
|
+
|
|
6
|
+
const PATTERN = new RegExp(
|
|
7
|
+
"" + "(" + TIME_UNITS_PATTERN + ")" + "(later|na|vanaf nu|voortaan|vooruit|uit)" + "(?=(?:\\W|$))",
|
|
8
|
+
"i"
|
|
9
|
+
);
|
|
10
|
+
|
|
11
|
+
const STRICT_PATTERN = new RegExp("" + "(" + TIME_UNITS_PATTERN + ")" + "(later|vanaf nu)" + "(?=(?:\\W|$))", "i");
|
|
12
|
+
const GROUP_NUM_TIMEUNITS = 1;
|
|
13
|
+
|
|
14
|
+
export default class NLTimeUnitLaterFormatParser extends AbstractParserWithWordBoundaryChecking {
|
|
15
|
+
constructor(private strictMode: boolean) {
|
|
16
|
+
super();
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
innerPattern(): RegExp {
|
|
20
|
+
return this.strictMode ? STRICT_PATTERN : PATTERN;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
innerExtract(context: ParsingContext, match: RegExpMatchArray) {
|
|
24
|
+
const fragments = parseTimeUnits(match[GROUP_NUM_TIMEUNITS]);
|
|
25
|
+
return ParsingComponents.createRelativeFromReference(context.reference, fragments);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -10,6 +10,6 @@ export default class NLTimeUnitWithinFormatParser extends AbstractParserWithWord
|
|
|
10
10
|
|
|
11
11
|
innerExtract(context: ParsingContext, match: RegExpMatchArray): ParsingComponents {
|
|
12
12
|
const timeUnits = parseTimeUnits(match[1]);
|
|
13
|
-
return ParsingComponents.
|
|
13
|
+
return ParsingComponents.createRelativeFromReference(context.reference, timeUnits);
|
|
14
14
|
}
|
|
15
15
|
}
|
|
@@ -14,17 +14,17 @@ export default class PTCasualDateParser extends AbstractParserWithWordBoundaryCh
|
|
|
14
14
|
|
|
15
15
|
switch (lowerText) {
|
|
16
16
|
case "agora":
|
|
17
|
-
return references.now(context.
|
|
17
|
+
return references.now(context.reference);
|
|
18
18
|
|
|
19
19
|
case "hoje":
|
|
20
|
-
return references.today(context.
|
|
20
|
+
return references.today(context.reference);
|
|
21
21
|
|
|
22
22
|
case "amanha":
|
|
23
23
|
case "amanhã":
|
|
24
|
-
return references.tomorrow(context.
|
|
24
|
+
return references.tomorrow(context.reference);
|
|
25
25
|
|
|
26
26
|
case "ontem":
|
|
27
|
-
return references.yesterday(context.
|
|
27
|
+
return references.yesterday(context.reference);
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
return component;
|
package/src/results.ts
CHANGED
|
@@ -1,15 +1,34 @@
|
|
|
1
|
-
import { Component, ParsedComponents, ParsedResult } from "./index";
|
|
1
|
+
import { Component, ParsedComponents, ParsedResult, ParsingReference } from "./index";
|
|
2
2
|
|
|
3
3
|
import quarterOfYear from "dayjs/plugin/quarterOfYear";
|
|
4
4
|
import dayjs, { OpUnitType, QUnitType } from "dayjs";
|
|
5
5
|
import { assignSimilarDate, assignSimilarTime, implySimilarTime } from "./utils/dayjs";
|
|
6
|
+
import { toTimezoneOffset } from "./timezone";
|
|
6
7
|
dayjs.extend(quarterOfYear);
|
|
7
8
|
|
|
9
|
+
export class ReferenceWithTimezone {
|
|
10
|
+
readonly instant: Date;
|
|
11
|
+
readonly timezoneOffset?: number;
|
|
12
|
+
|
|
13
|
+
constructor(input?: ParsingReference | Date) {
|
|
14
|
+
input = input ?? new Date();
|
|
15
|
+
if (input instanceof Date) {
|
|
16
|
+
this.instant = input;
|
|
17
|
+
this.timezoneOffset = -input.getTimezoneOffset();
|
|
18
|
+
} else {
|
|
19
|
+
this.instant = input.instant ?? new Date();
|
|
20
|
+
this.timezoneOffset = toTimezoneOffset(input.timezone);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
8
25
|
export class ParsingComponents implements ParsedComponents {
|
|
9
26
|
private knownValues: { [c in Component]?: number };
|
|
10
27
|
private impliedValues: { [c in Component]?: number };
|
|
28
|
+
private reference: ReferenceWithTimezone;
|
|
11
29
|
|
|
12
|
-
constructor(
|
|
30
|
+
constructor(reference: ReferenceWithTimezone, knownComponents?: { [c in Component]?: number }) {
|
|
31
|
+
this.reference = reference;
|
|
13
32
|
this.knownValues = {};
|
|
14
33
|
this.impliedValues = {};
|
|
15
34
|
if (knownComponents) {
|
|
@@ -18,7 +37,7 @@ export class ParsingComponents implements ParsedComponents {
|
|
|
18
37
|
}
|
|
19
38
|
}
|
|
20
39
|
|
|
21
|
-
const refDayJs = dayjs(
|
|
40
|
+
const refDayJs = dayjs(reference.instant);
|
|
22
41
|
this.imply("day", refDayJs.date());
|
|
23
42
|
this.imply("month", refDayJs.month() + 1);
|
|
24
43
|
this.imply("year", refDayJs.year());
|
|
@@ -68,7 +87,7 @@ export class ParsingComponents implements ParsedComponents {
|
|
|
68
87
|
}
|
|
69
88
|
|
|
70
89
|
clone(): ParsingComponents {
|
|
71
|
-
const component = new ParsingComponents(
|
|
90
|
+
const component = new ParsingComponents(this.reference);
|
|
72
91
|
component.knownValues = {};
|
|
73
92
|
component.impliedValues = {};
|
|
74
93
|
|
|
@@ -100,7 +119,7 @@ export class ParsingComponents implements ParsedComponents {
|
|
|
100
119
|
}
|
|
101
120
|
|
|
102
121
|
isValidDate(): boolean {
|
|
103
|
-
const date = this.
|
|
122
|
+
const date = this.dateWithoutTimezoneAdjustment();
|
|
104
123
|
|
|
105
124
|
if (date.getFullYear() !== this.get("year")) return false;
|
|
106
125
|
if (date.getMonth() !== this.get("month") - 1) return false;
|
|
@@ -123,7 +142,7 @@ export class ParsingComponents implements ParsedComponents {
|
|
|
123
142
|
|
|
124
143
|
date(): Date {
|
|
125
144
|
const date = this.dateWithoutTimezoneAdjustment();
|
|
126
|
-
return new Date(date.getTime() + this.
|
|
145
|
+
return new Date(date.getTime() + this.getSystemTimezoneAdjustmentMinute() * 60000);
|
|
127
146
|
}
|
|
128
147
|
|
|
129
148
|
private dateWithoutTimezoneAdjustment() {
|
|
@@ -141,28 +160,34 @@ export class ParsingComponents implements ParsedComponents {
|
|
|
141
160
|
return date;
|
|
142
161
|
}
|
|
143
162
|
|
|
144
|
-
private
|
|
145
|
-
|
|
146
|
-
const
|
|
147
|
-
|
|
163
|
+
private getSystemTimezoneAdjustmentMinute() {
|
|
164
|
+
const currentTimezoneOffset = -new Date().getTimezoneOffset();
|
|
165
|
+
const targetTimezoneOffset = this.get("timezoneOffset") ?? this.reference.timezoneOffset;
|
|
166
|
+
|
|
148
167
|
return currentTimezoneOffset - targetTimezoneOffset;
|
|
149
168
|
}
|
|
150
169
|
|
|
151
|
-
static
|
|
152
|
-
|
|
170
|
+
static createRelativeFromReference(
|
|
171
|
+
reference: ReferenceWithTimezone,
|
|
153
172
|
fragments: { [c in OpUnitType | QUnitType]?: number }
|
|
154
173
|
): ParsingComponents {
|
|
155
|
-
let date = dayjs(
|
|
174
|
+
let date = dayjs(reference.instant);
|
|
156
175
|
for (const key in fragments) {
|
|
157
176
|
date = date.add(fragments[key as OpUnitType], key as OpUnitType);
|
|
158
177
|
}
|
|
159
178
|
|
|
160
|
-
const components = new ParsingComponents(
|
|
179
|
+
const components = new ParsingComponents(reference);
|
|
161
180
|
if (fragments["hour"] || fragments["minute"] || fragments["second"]) {
|
|
162
181
|
assignSimilarTime(components, date);
|
|
163
182
|
assignSimilarDate(components, date);
|
|
183
|
+
if (reference.timezoneOffset !== null) {
|
|
184
|
+
components.assign("timezoneOffset", -reference.instant.getTimezoneOffset());
|
|
185
|
+
}
|
|
164
186
|
} else {
|
|
165
187
|
implySimilarTime(components, date);
|
|
188
|
+
if (reference.timezoneOffset !== null) {
|
|
189
|
+
components.imply("timezoneOffset", -reference.instant.getTimezoneOffset());
|
|
190
|
+
}
|
|
166
191
|
|
|
167
192
|
if (fragments["d"]) {
|
|
168
193
|
components.assign("day", date.date());
|
|
@@ -197,19 +222,28 @@ export class ParsingResult implements ParsedResult {
|
|
|
197
222
|
index: number;
|
|
198
223
|
text: string;
|
|
199
224
|
|
|
225
|
+
reference: ReferenceWithTimezone;
|
|
226
|
+
|
|
200
227
|
start: ParsingComponents;
|
|
201
228
|
end?: ParsingComponents;
|
|
202
229
|
|
|
203
|
-
constructor(
|
|
204
|
-
|
|
230
|
+
constructor(
|
|
231
|
+
reference: ReferenceWithTimezone,
|
|
232
|
+
index: number,
|
|
233
|
+
text: string,
|
|
234
|
+
start?: ParsingComponents,
|
|
235
|
+
end?: ParsingComponents
|
|
236
|
+
) {
|
|
237
|
+
this.reference = reference;
|
|
238
|
+
this.refDate = reference.instant;
|
|
205
239
|
this.index = index;
|
|
206
240
|
this.text = text;
|
|
207
|
-
this.start = start || new ParsingComponents(
|
|
241
|
+
this.start = start || new ParsingComponents(reference);
|
|
208
242
|
this.end = end;
|
|
209
243
|
}
|
|
210
244
|
|
|
211
245
|
clone() {
|
|
212
|
-
const result = new ParsingResult(this.
|
|
246
|
+
const result = new ParsingResult(this.reference, this.index, this.text);
|
|
213
247
|
result.start = this.start ? this.start.clone() : null;
|
|
214
248
|
result.end = this.end ? this.end.clone() : null;
|
|
215
249
|
return result;
|
package/src/timezone.ts
ADDED
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
export const TIMEZONE_ABBR_MAP = {
|
|
2
|
+
ACDT: 630,
|
|
3
|
+
ACST: 570,
|
|
4
|
+
ADT: -180,
|
|
5
|
+
AEDT: 660,
|
|
6
|
+
AEST: 600,
|
|
7
|
+
AFT: 270,
|
|
8
|
+
AKDT: -480,
|
|
9
|
+
AKST: -540,
|
|
10
|
+
ALMT: 360,
|
|
11
|
+
AMST: -180,
|
|
12
|
+
AMT: -240,
|
|
13
|
+
ANAST: 720,
|
|
14
|
+
ANAT: 720,
|
|
15
|
+
AQTT: 300,
|
|
16
|
+
ART: -180,
|
|
17
|
+
AST: -240,
|
|
18
|
+
AWDT: 540,
|
|
19
|
+
AWST: 480,
|
|
20
|
+
AZOST: 0,
|
|
21
|
+
AZOT: -60,
|
|
22
|
+
AZST: 300,
|
|
23
|
+
AZT: 240,
|
|
24
|
+
BNT: 480,
|
|
25
|
+
BOT: -240,
|
|
26
|
+
BRST: -120,
|
|
27
|
+
BRT: -180,
|
|
28
|
+
BST: 60,
|
|
29
|
+
BTT: 360,
|
|
30
|
+
CAST: 480,
|
|
31
|
+
CAT: 120,
|
|
32
|
+
CCT: 390,
|
|
33
|
+
CDT: -300,
|
|
34
|
+
CEST: 120,
|
|
35
|
+
CET: 60,
|
|
36
|
+
CHADT: 825,
|
|
37
|
+
CHAST: 765,
|
|
38
|
+
CKT: -600,
|
|
39
|
+
CLST: -180,
|
|
40
|
+
CLT: -240,
|
|
41
|
+
COT: -300,
|
|
42
|
+
CST: -360,
|
|
43
|
+
CVT: -60,
|
|
44
|
+
CXT: 420,
|
|
45
|
+
ChST: 600,
|
|
46
|
+
DAVT: 420,
|
|
47
|
+
EASST: -300,
|
|
48
|
+
EAST: -360,
|
|
49
|
+
EAT: 180,
|
|
50
|
+
ECT: -300,
|
|
51
|
+
EDT: -240,
|
|
52
|
+
EEST: 180,
|
|
53
|
+
EET: 120,
|
|
54
|
+
EGST: 0,
|
|
55
|
+
EGT: -60,
|
|
56
|
+
EST: -300,
|
|
57
|
+
ET: -300,
|
|
58
|
+
FJST: 780,
|
|
59
|
+
FJT: 720,
|
|
60
|
+
FKST: -180,
|
|
61
|
+
FKT: -240,
|
|
62
|
+
FNT: -120,
|
|
63
|
+
GALT: -360,
|
|
64
|
+
GAMT: -540,
|
|
65
|
+
GET: 240,
|
|
66
|
+
GFT: -180,
|
|
67
|
+
GILT: 720,
|
|
68
|
+
GMT: 0,
|
|
69
|
+
GST: 240,
|
|
70
|
+
GYT: -240,
|
|
71
|
+
HAA: -180,
|
|
72
|
+
HAC: -300,
|
|
73
|
+
HADT: -540,
|
|
74
|
+
HAE: -240,
|
|
75
|
+
HAP: -420,
|
|
76
|
+
HAR: -360,
|
|
77
|
+
HAST: -600,
|
|
78
|
+
HAT: -90,
|
|
79
|
+
HAY: -480,
|
|
80
|
+
HKT: 480,
|
|
81
|
+
HLV: -210,
|
|
82
|
+
HNA: -240,
|
|
83
|
+
HNC: -360,
|
|
84
|
+
HNE: -300,
|
|
85
|
+
HNP: -480,
|
|
86
|
+
HNR: -420,
|
|
87
|
+
HNT: -150,
|
|
88
|
+
HNY: -540,
|
|
89
|
+
HOVT: 420,
|
|
90
|
+
ICT: 420,
|
|
91
|
+
IDT: 180,
|
|
92
|
+
IOT: 360,
|
|
93
|
+
IRDT: 270,
|
|
94
|
+
IRKST: 540,
|
|
95
|
+
IRKT: 540,
|
|
96
|
+
IRST: 210,
|
|
97
|
+
IST: 330,
|
|
98
|
+
JST: 540,
|
|
99
|
+
KGT: 360,
|
|
100
|
+
KRAST: 480,
|
|
101
|
+
KRAT: 480,
|
|
102
|
+
KST: 540,
|
|
103
|
+
KUYT: 240,
|
|
104
|
+
LHDT: 660,
|
|
105
|
+
LHST: 630,
|
|
106
|
+
LINT: 840,
|
|
107
|
+
MAGST: 720,
|
|
108
|
+
MAGT: 720,
|
|
109
|
+
MART: -510,
|
|
110
|
+
MAWT: 300,
|
|
111
|
+
MDT: -360,
|
|
112
|
+
MESZ: 120,
|
|
113
|
+
MEZ: 60,
|
|
114
|
+
MHT: 720,
|
|
115
|
+
MMT: 390,
|
|
116
|
+
MSD: 240,
|
|
117
|
+
MSK: 240,
|
|
118
|
+
MST: -420,
|
|
119
|
+
MUT: 240,
|
|
120
|
+
MVT: 300,
|
|
121
|
+
MYT: 480,
|
|
122
|
+
NCT: 660,
|
|
123
|
+
NDT: -90,
|
|
124
|
+
NFT: 690,
|
|
125
|
+
NOVST: 420,
|
|
126
|
+
NOVT: 360,
|
|
127
|
+
NPT: 345,
|
|
128
|
+
NST: -150,
|
|
129
|
+
NUT: -660,
|
|
130
|
+
NZDT: 780,
|
|
131
|
+
NZST: 720,
|
|
132
|
+
OMSST: 420,
|
|
133
|
+
OMST: 420,
|
|
134
|
+
PDT: -420,
|
|
135
|
+
PET: -300,
|
|
136
|
+
PETST: 720,
|
|
137
|
+
PETT: 720,
|
|
138
|
+
PGT: 600,
|
|
139
|
+
PHOT: 780,
|
|
140
|
+
PHT: 480,
|
|
141
|
+
PKT: 300,
|
|
142
|
+
PMDT: -120,
|
|
143
|
+
PMST: -180,
|
|
144
|
+
PONT: 660,
|
|
145
|
+
PST: -480,
|
|
146
|
+
PT: -480,
|
|
147
|
+
PWT: 540,
|
|
148
|
+
PYST: -180,
|
|
149
|
+
PYT: -240,
|
|
150
|
+
RET: 240,
|
|
151
|
+
SAMT: 240,
|
|
152
|
+
SAST: 120,
|
|
153
|
+
SBT: 660,
|
|
154
|
+
SCT: 240,
|
|
155
|
+
SGT: 480,
|
|
156
|
+
SRT: -180,
|
|
157
|
+
SST: -660,
|
|
158
|
+
TAHT: -600,
|
|
159
|
+
TFT: 300,
|
|
160
|
+
TJT: 300,
|
|
161
|
+
TKT: 780,
|
|
162
|
+
TLT: 540,
|
|
163
|
+
TMT: 300,
|
|
164
|
+
TVT: 720,
|
|
165
|
+
ULAT: 480,
|
|
166
|
+
UTC: 0,
|
|
167
|
+
UYST: -120,
|
|
168
|
+
UYT: -180,
|
|
169
|
+
UZT: 300,
|
|
170
|
+
VET: -210,
|
|
171
|
+
VLAST: 660,
|
|
172
|
+
VLAT: 660,
|
|
173
|
+
VUT: 660,
|
|
174
|
+
WAST: 120,
|
|
175
|
+
WAT: 60,
|
|
176
|
+
WEST: 60,
|
|
177
|
+
WESZ: 60,
|
|
178
|
+
WET: 0,
|
|
179
|
+
WEZ: 0,
|
|
180
|
+
WFT: 720,
|
|
181
|
+
WGST: -120,
|
|
182
|
+
WGT: -180,
|
|
183
|
+
WIB: 420,
|
|
184
|
+
WIT: 540,
|
|
185
|
+
WITA: 480,
|
|
186
|
+
WST: 780,
|
|
187
|
+
WT: 0,
|
|
188
|
+
YAKST: 600,
|
|
189
|
+
YAKT: 600,
|
|
190
|
+
YAPT: 600,
|
|
191
|
+
YEKST: 360,
|
|
192
|
+
YEKT: 360,
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
export function toTimezoneOffset(timezoneInput: string | number): number | null {
|
|
196
|
+
if (timezoneInput === null) {
|
|
197
|
+
return null;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
if (typeof timezoneInput === "number") {
|
|
201
|
+
return timezoneInput;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
return TIMEZONE_ABBR_MAP[timezoneInput] ?? 0;
|
|
205
|
+
}
|
package/src/utils/dayjs.ts
CHANGED
|
@@ -18,7 +18,6 @@ export function assignSimilarTime(component: ParsingComponents, targetDayJs: day
|
|
|
18
18
|
component.assign("minute", targetDayJs.minute());
|
|
19
19
|
component.assign("second", targetDayJs.second());
|
|
20
20
|
component.assign("millisecond", targetDayJs.millisecond());
|
|
21
|
-
component.assign("timezoneOffset", targetDayJs.utcOffset());
|
|
22
21
|
}
|
|
23
22
|
|
|
24
23
|
export function implySimilarTime(component: ParsingComponents, targetDayJs: dayjs.Dayjs) {
|
|
@@ -26,5 +25,4 @@ export function implySimilarTime(component: ParsingComponents, targetDayJs: dayj
|
|
|
26
25
|
component.imply("minute", targetDayJs.minute());
|
|
27
26
|
component.imply("second", targetDayJs.second());
|
|
28
27
|
component.imply("millisecond", targetDayJs.millisecond());
|
|
29
|
-
component.imply("timezoneOffset", targetDayJs.utcOffset());
|
|
30
28
|
}
|
package/src/utils/pattern.ts
CHANGED
|
@@ -2,7 +2,7 @@ type DictionaryLike = string[] | { [word: string]: unknown } | Map<string, unkno
|
|
|
2
2
|
|
|
3
3
|
export function repeatedTimeunitPattern(prefix: string, singleTimeunitPattern: string): string {
|
|
4
4
|
const singleTimeunitPatternNoCapture = singleTimeunitPattern.replace(/\((?!\?)/g, "(?:");
|
|
5
|
-
return `${prefix}${singleTimeunitPatternNoCapture}\\s
|
|
5
|
+
return `${prefix}${singleTimeunitPatternNoCapture}\\s{0,5}(?:,?\\s{0,5}${singleTimeunitPatternNoCapture}){0,10}`;
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
export function extractTerms(dictionary: DictionaryLike): string[] {
|
|
@@ -364,6 +364,16 @@ test("Test - Forward Option", () => {
|
|
|
364
364
|
expect(result.end.get("day")).toBe(23);
|
|
365
365
|
expect(result.end.get("hour")).toBe(19);
|
|
366
366
|
});
|
|
367
|
+
|
|
368
|
+
testSingleCase(chrono, "17 August 2013 - 19 August 2013", (result) => {
|
|
369
|
+
expect(result.start.get("year")).toBe(2013);
|
|
370
|
+
expect(result.start.get("month")).toBe(8);
|
|
371
|
+
expect(result.start.get("day")).toBe(17);
|
|
372
|
+
|
|
373
|
+
expect(result.end.get("year")).toBe(2013);
|
|
374
|
+
expect(result.end.get("month")).toBe(8);
|
|
375
|
+
expect(result.end.get("day")).toBe(19);
|
|
376
|
+
});
|
|
367
377
|
});
|
|
368
378
|
|
|
369
379
|
test("Test - Impossible Dates (Strict Mode)", function () {
|
|
@@ -208,4 +208,34 @@ test("Test - Relative date components' certainty and imply timezone", () => {
|
|
|
208
208
|
expect(result).toBeDate(new Date("Sun Nov 29 2020 13:34:13 GMT+0900 (Japan Standard Time)"));
|
|
209
209
|
expect(result).toBeDate(new Date("Sun Nov 29 2020 5:34:13 GMT+0100"));
|
|
210
210
|
}
|
|
211
|
+
|
|
212
|
+
{
|
|
213
|
+
const text = "in 10 minutes";
|
|
214
|
+
const result = chrono.parse(text, { instant: refDate, timezone: "BST" })[0] as ParsingResult;
|
|
215
|
+
|
|
216
|
+
expect(result.text).toBe(text);
|
|
217
|
+
result.start.imply("timezoneOffset", 60);
|
|
218
|
+
|
|
219
|
+
expect(result).toBeDate(new Date("Sun Nov 29 2020 13:34:13 GMT+0900 (Japan Standard Time)"));
|
|
220
|
+
expect(result).toBeDate(new Date("Sun Nov 29 2020 5:34:13 GMT+0100"));
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
{
|
|
224
|
+
const text = "in 10 minutes";
|
|
225
|
+
const result = chrono.parse(text, { instant: refDate, timezone: "JST" })[0] as ParsingResult;
|
|
226
|
+
|
|
227
|
+
expect(result.text).toBe(text);
|
|
228
|
+
result.start.imply("timezoneOffset", 60);
|
|
229
|
+
|
|
230
|
+
expect(result).toBeDate(new Date("Sun Nov 29 2020 13:34:13 GMT+0900 (Japan Standard Time)"));
|
|
231
|
+
expect(result).toBeDate(new Date("Sun Nov 29 2020 5:34:13 GMT+0100"));
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
{
|
|
235
|
+
const text = "in 20 minutes";
|
|
236
|
+
const result = chrono.parse(text, { instant: refDate, timezone: null })[0] as ParsingResult;
|
|
237
|
+
|
|
238
|
+
expect(result.text).toBe(text);
|
|
239
|
+
expect(result.start.isCertain("timezoneOffset")).toBe(false);
|
|
240
|
+
}
|
|
211
241
|
});
|
package/test/en/en_slash.test.ts
CHANGED
|
@@ -203,4 +203,15 @@ test("Test - forward dates only option", function () {
|
|
|
203
203
|
|
|
204
204
|
expect(result.start).toBeDate(new Date(2000, 5 - 1, 31, 12));
|
|
205
205
|
});
|
|
206
|
+
|
|
207
|
+
testSingleCase(chrono, "1/8 at 12pm", new Date("Sep 25 2021 12:00:00"), { forwardDate: true }, (result) => {
|
|
208
|
+
expect(result.text).toBe("1/8 at 12pm");
|
|
209
|
+
|
|
210
|
+
expect(result.start).not.toBeNull();
|
|
211
|
+
expect(result.start.get("year")).toBe(2022);
|
|
212
|
+
expect(result.start.get("month")).toBe(1);
|
|
213
|
+
expect(result.start.get("day")).toBe(8);
|
|
214
|
+
|
|
215
|
+
expect(result.start).toBeDate(new Date(2022, 1 - 1, 8, 12));
|
|
216
|
+
});
|
|
206
217
|
});
|
|
@@ -88,10 +88,13 @@ test("Test - Not parsing timezone from relative time", function () {
|
|
|
88
88
|
expect(result.start.get("timezoneOffset")).toBe(-refDate.getTimezoneOffset());
|
|
89
89
|
});
|
|
90
90
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
91
|
+
// This test fail when the system/assume timezone is exactly similar to the mentioned timezone
|
|
92
|
+
// Temporary disable this test
|
|
93
|
+
|
|
94
|
+
// testSingleCase(chrono, "in 3 hours GMT", refDate, (result, text) => {
|
|
95
|
+
// expect(result.text).toBe("in 3 hours");
|
|
96
|
+
// expect(result.start.get("timezoneOffset")).toBe(-refDate.getTimezoneOffset());
|
|
97
|
+
// });
|
|
95
98
|
});
|
|
96
99
|
|
|
97
100
|
test("Test - Parsing timezone from relative date when valid", function () {
|
|
@@ -20,30 +20,6 @@ test("Test - Single Expression", function () {
|
|
|
20
20
|
expect(result.start).toBeDate(new Date(2012, 7, 6, 12));
|
|
21
21
|
});
|
|
22
22
|
|
|
23
|
-
testSingleCase(
|
|
24
|
-
chrono.casual,
|
|
25
|
-
"Monday (forward dates only)",
|
|
26
|
-
new Date(2012, 7, 9),
|
|
27
|
-
{ forwardDate: true },
|
|
28
|
-
(result) => {
|
|
29
|
-
expect(result.index).toBe(0);
|
|
30
|
-
expect(result.text).toBe("Monday");
|
|
31
|
-
|
|
32
|
-
expect(result.start).not.toBeNull();
|
|
33
|
-
expect(result.start.get("year")).toBe(2012);
|
|
34
|
-
expect(result.start.get("month")).toBe(8);
|
|
35
|
-
expect(result.start.get("day")).toBe(13);
|
|
36
|
-
expect(result.start.get("weekday")).toBe(1);
|
|
37
|
-
|
|
38
|
-
expect(result.start.isCertain("day")).toBe(false);
|
|
39
|
-
expect(result.start.isCertain("month")).toBe(false);
|
|
40
|
-
expect(result.start.isCertain("year")).toBe(false);
|
|
41
|
-
expect(result.start.isCertain("weekday")).toBe(true);
|
|
42
|
-
|
|
43
|
-
expect(result.start).toBeDate(new Date(2012, 7, 13, 12));
|
|
44
|
-
}
|
|
45
|
-
);
|
|
46
|
-
|
|
47
23
|
testSingleCase(chrono.casual, "Thursday", new Date(2012, 7, 9), (result) => {
|
|
48
24
|
expect(result.index).toBe(0);
|
|
49
25
|
expect(result.text).toBe("Thursday");
|
|
@@ -182,7 +158,31 @@ test("Test - Weekday Overlap", function () {
|
|
|
182
158
|
});
|
|
183
159
|
});
|
|
184
160
|
|
|
185
|
-
test("Test - forward dates only option",
|
|
161
|
+
test("Test - forward dates only option", () => {
|
|
162
|
+
testSingleCase(
|
|
163
|
+
chrono.casual,
|
|
164
|
+
"Monday (forward dates only)",
|
|
165
|
+
new Date(2012, 7, 9),
|
|
166
|
+
{ forwardDate: true },
|
|
167
|
+
(result) => {
|
|
168
|
+
expect(result.index).toBe(0);
|
|
169
|
+
expect(result.text).toBe("Monday");
|
|
170
|
+
|
|
171
|
+
expect(result.start).not.toBeNull();
|
|
172
|
+
expect(result.start.get("year")).toBe(2012);
|
|
173
|
+
expect(result.start.get("month")).toBe(8);
|
|
174
|
+
expect(result.start.get("day")).toBe(13);
|
|
175
|
+
expect(result.start.get("weekday")).toBe(1);
|
|
176
|
+
|
|
177
|
+
expect(result.start.isCertain("day")).toBe(false);
|
|
178
|
+
expect(result.start.isCertain("month")).toBe(false);
|
|
179
|
+
expect(result.start.isCertain("year")).toBe(false);
|
|
180
|
+
expect(result.start.isCertain("weekday")).toBe(true);
|
|
181
|
+
|
|
182
|
+
expect(result.start).toBeDate(new Date(2012, 7, 13, 12));
|
|
183
|
+
}
|
|
184
|
+
);
|
|
185
|
+
|
|
186
186
|
testSingleCase(
|
|
187
187
|
chrono.casual,
|
|
188
188
|
"this Friday to this Monday",
|
|
@@ -219,4 +219,48 @@ test("Test - forward dates only option", function () {
|
|
|
219
219
|
expect(result.end).toBeDate(new Date(2016, 8 - 1, 8, 12));
|
|
220
220
|
}
|
|
221
221
|
);
|
|
222
|
+
|
|
223
|
+
testSingleCase(
|
|
224
|
+
chrono.casual,
|
|
225
|
+
"sunday morning",
|
|
226
|
+
new Date("August 15, 2021, 20:00"),
|
|
227
|
+
{ forwardDate: true },
|
|
228
|
+
(result) => {
|
|
229
|
+
expect(result.index).toBe(0);
|
|
230
|
+
expect(result.text).toBe("sunday morning");
|
|
231
|
+
|
|
232
|
+
expect(result.start).not.toBeNull();
|
|
233
|
+
expect(result.start.get("year")).toBe(2021);
|
|
234
|
+
expect(result.start.get("month")).toBe(8);
|
|
235
|
+
expect(result.start.get("day")).toBe(22);
|
|
236
|
+
expect(result.start.get("weekday")).toBe(0);
|
|
237
|
+
|
|
238
|
+
expect(result.start.isCertain("day")).toBe(false);
|
|
239
|
+
expect(result.start.isCertain("month")).toBe(false);
|
|
240
|
+
expect(result.start.isCertain("year")).toBe(false);
|
|
241
|
+
expect(result.start.isCertain("weekday")).toBe(true);
|
|
242
|
+
|
|
243
|
+
expect(result.start).toBeDate(new Date(2021, 8 - 1, 22, 6));
|
|
244
|
+
}
|
|
245
|
+
);
|
|
246
|
+
|
|
247
|
+
testSingleCase(
|
|
248
|
+
chrono.casual,
|
|
249
|
+
"vacation monday - friday",
|
|
250
|
+
new Date("thursday 13 June 2019"),
|
|
251
|
+
{ forwardDate: true },
|
|
252
|
+
(result) => {
|
|
253
|
+
expect(result.text).toBe("monday - friday");
|
|
254
|
+
|
|
255
|
+
expect(result.start).not.toBeNull();
|
|
256
|
+
expect(result.start.get("year")).toBe(2019);
|
|
257
|
+
expect(result.start.get("month")).toBe(6);
|
|
258
|
+
expect(result.start.get("day")).toBe(17);
|
|
259
|
+
|
|
260
|
+
expect(result.end).not.toBeNull();
|
|
261
|
+
expect(result.end.get("year")).toBe(2019);
|
|
262
|
+
expect(result.end.get("month")).toBe(6);
|
|
263
|
+
expect(result.end.get("day")).toBe(21);
|
|
264
|
+
}
|
|
265
|
+
);
|
|
222
266
|
});
|
|
@@ -21,6 +21,8 @@ test("Test - Skip random non-date patterns", function () {
|
|
|
21
21
|
testUnexpectedResult(chrono, "Total: $1,194.09 [image: View Reservation");
|
|
22
22
|
|
|
23
23
|
testUnexpectedResult(chrono, "at 6.5 kilograms");
|
|
24
|
+
|
|
25
|
+
testUnexpectedResult(chrono, "ah that is unusual", null, { forwardDate: true });
|
|
24
26
|
});
|
|
25
27
|
|
|
26
28
|
test("Test - URLs % encoded", function () {
|