chrono-node 2.6.2 → 2.6.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 +32 -2
- package/dist/cjs/common/refiners/AbstractMergeDateRangeRefiner.js +15 -7
- package/dist/cjs/common/refiners/AbstractMergeDateRangeRefiner.js.map +1 -1
- package/dist/cjs/common/refiners/ExtractTimezoneAbbrRefiner.d.ts +3 -4
- package/dist/cjs/common/refiners/ExtractTimezoneAbbrRefiner.js +6 -196
- package/dist/cjs/common/refiners/ExtractTimezoneAbbrRefiner.js.map +1 -1
- package/dist/cjs/common/refiners/ForwardDateRefiner.js +14 -14
- package/dist/cjs/common/refiners/ForwardDateRefiner.js.map +1 -1
- package/dist/cjs/configurations.js +1 -1
- package/dist/cjs/configurations.js.map +1 -1
- package/dist/cjs/index.d.ts +24 -3
- package/dist/cjs/index.js +16 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/locales/en/constants.d.ts +4 -0
- package/dist/cjs/locales/en/constants.js +5 -18
- package/dist/cjs/locales/en/constants.js.map +1 -1
- package/dist/cjs/locales/en/index.js +1 -1
- package/dist/cjs/locales/en/index.js.map +1 -1
- package/dist/cjs/locales/en/parsers/ENTimeUnitAgoFormatParser.js +2 -2
- package/dist/cjs/locales/en/parsers/ENTimeUnitAgoFormatParser.js.map +1 -1
- package/dist/cjs/locales/en/parsers/ENTimeUnitCasualRelativeFormatParser.d.ts +2 -0
- package/dist/cjs/locales/en/parsers/ENTimeUnitCasualRelativeFormatParser.js +6 -1
- package/dist/cjs/locales/en/parsers/ENTimeUnitCasualRelativeFormatParser.js.map +1 -1
- package/dist/cjs/locales/en/parsers/ENTimeUnitLaterFormatParser.js +1 -1
- package/dist/cjs/locales/en/parsers/ENTimeUnitLaterFormatParser.js.map +1 -1
- package/dist/cjs/locales/en/parsers/ENTimeUnitWithinFormatParser.d.ts +2 -0
- package/dist/cjs/locales/en/parsers/ENTimeUnitWithinFormatParser.js +10 -1
- package/dist/cjs/locales/en/parsers/ENTimeUnitWithinFormatParser.js.map +1 -1
- package/dist/cjs/locales/ru/constants.js +4 -1
- package/dist/cjs/locales/ru/constants.js.map +1 -1
- package/dist/cjs/results.d.ts +1 -1
- package/dist/cjs/results.js +3 -3
- package/dist/cjs/results.js.map +1 -1
- package/dist/cjs/timezone.d.ts +5 -194
- package/dist/cjs/timezone.js +80 -7
- package/dist/cjs/timezone.js.map +1 -1
- package/dist/esm/common/refiners/AbstractMergeDateRangeRefiner.js +15 -7
- package/dist/esm/common/refiners/AbstractMergeDateRangeRefiner.js.map +1 -1
- package/dist/esm/common/refiners/ExtractTimezoneAbbrRefiner.d.ts +3 -4
- package/dist/esm/common/refiners/ExtractTimezoneAbbrRefiner.js +6 -196
- package/dist/esm/common/refiners/ExtractTimezoneAbbrRefiner.js.map +1 -1
- package/dist/esm/common/refiners/ForwardDateRefiner.js +14 -14
- package/dist/esm/common/refiners/ForwardDateRefiner.js.map +1 -1
- package/dist/esm/configurations.js +1 -1
- package/dist/esm/configurations.js.map +1 -1
- package/dist/esm/index.d.ts +24 -3
- package/dist/esm/index.js +15 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/locales/en/constants.d.ts +4 -0
- package/dist/esm/locales/en/constants.js +21 -0
- package/dist/esm/locales/en/constants.js.map +1 -1
- package/dist/esm/locales/en/index.js +1 -1
- package/dist/esm/locales/en/index.js.map +1 -1
- package/dist/esm/locales/en/parsers/ENTimeUnitAgoFormatParser.js +3 -3
- package/dist/esm/locales/en/parsers/ENTimeUnitAgoFormatParser.js.map +1 -1
- package/dist/esm/locales/en/parsers/ENTimeUnitCasualRelativeFormatParser.d.ts +2 -0
- package/dist/esm/locales/en/parsers/ENTimeUnitCasualRelativeFormatParser.js +7 -2
- package/dist/esm/locales/en/parsers/ENTimeUnitCasualRelativeFormatParser.js.map +1 -1
- package/dist/esm/locales/en/parsers/ENTimeUnitLaterFormatParser.js +2 -2
- package/dist/esm/locales/en/parsers/ENTimeUnitLaterFormatParser.js.map +1 -1
- package/dist/esm/locales/en/parsers/ENTimeUnitWithinFormatParser.d.ts +2 -0
- package/dist/esm/locales/en/parsers/ENTimeUnitWithinFormatParser.js +11 -2
- package/dist/esm/locales/en/parsers/ENTimeUnitWithinFormatParser.js.map +1 -1
- package/dist/esm/locales/ru/constants.js +4 -1
- package/dist/esm/locales/ru/constants.js.map +1 -1
- package/dist/esm/results.d.ts +1 -1
- package/dist/esm/results.js +3 -3
- package/dist/esm/results.js.map +1 -1
- package/dist/esm/timezone.d.ts +5 -194
- package/dist/esm/timezone.js +74 -6
- package/dist/esm/timezone.js.map +1 -1
- package/package.json +4 -5
- package/src/common/refiners/AbstractMergeDateRangeRefiner.ts +13 -8
- package/src/common/refiners/ExtractTimezoneAbbrRefiner.ts +7 -201
- package/src/common/refiners/ForwardDateRefiner.ts +18 -16
- package/src/configurations.ts +3 -1
- package/src/index.ts +46 -2
- package/src/locales/en/constants.ts +30 -0
- package/src/locales/en/index.ts +1 -1
- package/src/locales/en/parsers/ENTimeUnitAgoFormatParser.ts +3 -3
- package/src/locales/en/parsers/ENTimeUnitCasualRelativeFormatParser.ts +10 -2
- package/src/locales/en/parsers/ENTimeUnitLaterFormatParser.ts +5 -2
- package/src/locales/en/parsers/ENTimeUnitWithinFormatParser.ts +16 -3
- package/src/locales/ru/constants.ts +4 -1
- package/src/results.ts +3 -3
- package/src/timezone.ts +124 -7
- package/test/de/de_time_exp.test.ts +7 -7
- package/test/en/en_month.test.ts +70 -0
- package/test/en/en_time_units_ago.test.ts +12 -0
- package/test/en/en_time_units_casual_relative.test.ts +18 -0
- package/test/en/en_time_units_later.test.ts +13 -10
- package/test/en/en_time_units_within.test.ts +12 -1
- package/test/en/en_timezone_exp.test.ts +142 -0
- package/test/en/en_weekday.test.ts +26 -0
- package/test/en/negative_cases.test.ts +2 -0
- package/test/fr/fr_time_exp.test.ts +2 -2
- package/test/system.test.ts +23 -1
package/src/timezone.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
import dayjs from "dayjs";
|
|
2
|
+
import { TimezoneAbbrMap, Weekday, Month } from "./index";
|
|
3
|
+
|
|
4
|
+
export const TIMEZONE_ABBR_MAP: TimezoneAbbrMap = {
|
|
2
5
|
ACDT: 630,
|
|
3
6
|
ACST: 570,
|
|
4
7
|
ADT: -180,
|
|
@@ -32,7 +35,14 @@ export const TIMEZONE_ABBR_MAP = {
|
|
|
32
35
|
CCT: 390,
|
|
33
36
|
CDT: -300,
|
|
34
37
|
CEST: 120,
|
|
35
|
-
|
|
38
|
+
// Note: Many sources define CET as a constant UTC+1. In common usage, however,
|
|
39
|
+
// CET usually refers to the time observed in most of Europe, be it standard time or daylight saving time.
|
|
40
|
+
CET: {
|
|
41
|
+
timezoneOffsetDuringDst: 2 * 60,
|
|
42
|
+
timezoneOffsetNonDst: 60,
|
|
43
|
+
dstStart: (year: number) => getLastWeekdayOfMonth(year, Month.MARCH, Weekday.SUNDAY, 2),
|
|
44
|
+
dstEnd: (year: number) => getLastWeekdayOfMonth(year, Month.OCTOBER, Weekday.SUNDAY, 3),
|
|
45
|
+
},
|
|
36
46
|
CHADT: 825,
|
|
37
47
|
CHAST: 765,
|
|
38
48
|
CKT: -600,
|
|
@@ -40,6 +50,12 @@ export const TIMEZONE_ABBR_MAP = {
|
|
|
40
50
|
CLT: -240,
|
|
41
51
|
COT: -300,
|
|
42
52
|
CST: -360,
|
|
53
|
+
CT: {
|
|
54
|
+
timezoneOffsetDuringDst: -5 * 60,
|
|
55
|
+
timezoneOffsetNonDst: -6 * 60,
|
|
56
|
+
dstStart: (year: number) => getNthWeekdayOfMonth(year, Month.MARCH, Weekday.SUNDAY, 2, 2),
|
|
57
|
+
dstEnd: (year: number) => getNthWeekdayOfMonth(year, Month.NOVEMBER, Weekday.SUNDAY, 1, 2),
|
|
58
|
+
},
|
|
43
59
|
CVT: -60,
|
|
44
60
|
CXT: 420,
|
|
45
61
|
ChST: 600,
|
|
@@ -54,7 +70,12 @@ export const TIMEZONE_ABBR_MAP = {
|
|
|
54
70
|
EGST: 0,
|
|
55
71
|
EGT: -60,
|
|
56
72
|
EST: -300,
|
|
57
|
-
ET:
|
|
73
|
+
ET: {
|
|
74
|
+
timezoneOffsetDuringDst: -4 * 60,
|
|
75
|
+
timezoneOffsetNonDst: -5 * 60,
|
|
76
|
+
dstStart: (year: number) => getNthWeekdayOfMonth(year, Month.MARCH, Weekday.SUNDAY, 2, 2),
|
|
77
|
+
dstEnd: (year: number) => getNthWeekdayOfMonth(year, Month.NOVEMBER, Weekday.SUNDAY, 1, 2),
|
|
78
|
+
},
|
|
58
79
|
FJST: 780,
|
|
59
80
|
FJT: 720,
|
|
60
81
|
FKST: -180,
|
|
@@ -116,6 +137,12 @@ export const TIMEZONE_ABBR_MAP = {
|
|
|
116
137
|
MSD: 240,
|
|
117
138
|
MSK: 180,
|
|
118
139
|
MST: -420,
|
|
140
|
+
MT: {
|
|
141
|
+
timezoneOffsetDuringDst: -6 * 60,
|
|
142
|
+
timezoneOffsetNonDst: -7 * 60,
|
|
143
|
+
dstStart: (year: number) => getNthWeekdayOfMonth(year, Month.MARCH, Weekday.SUNDAY, 2, 2),
|
|
144
|
+
dstEnd: (year: number) => getNthWeekdayOfMonth(year, Month.NOVEMBER, Weekday.SUNDAY, 1, 2),
|
|
145
|
+
},
|
|
119
146
|
MUT: 240,
|
|
120
147
|
MVT: 300,
|
|
121
148
|
MYT: 480,
|
|
@@ -143,7 +170,12 @@ export const TIMEZONE_ABBR_MAP = {
|
|
|
143
170
|
PMST: -180,
|
|
144
171
|
PONT: 660,
|
|
145
172
|
PST: -480,
|
|
146
|
-
PT:
|
|
173
|
+
PT: {
|
|
174
|
+
timezoneOffsetDuringDst: -7 * 60,
|
|
175
|
+
timezoneOffsetNonDst: -8 * 60,
|
|
176
|
+
dstStart: (year: number) => getNthWeekdayOfMonth(year, Month.MARCH, Weekday.SUNDAY, 2, 2),
|
|
177
|
+
dstEnd: (year: number) => getNthWeekdayOfMonth(year, Month.NOVEMBER, Weekday.SUNDAY, 1, 2),
|
|
178
|
+
},
|
|
147
179
|
PWT: 540,
|
|
148
180
|
PYST: -180,
|
|
149
181
|
PYT: -240,
|
|
@@ -192,8 +224,67 @@ export const TIMEZONE_ABBR_MAP = {
|
|
|
192
224
|
YEKT: 360,
|
|
193
225
|
};
|
|
194
226
|
|
|
195
|
-
|
|
196
|
-
|
|
227
|
+
/**
|
|
228
|
+
* Get the date which is the nth occurence of a given weekday in a given month and year.
|
|
229
|
+
*
|
|
230
|
+
* @param year The year for which to find the date
|
|
231
|
+
* @param month The month in which the date occurs
|
|
232
|
+
* @param weekday The weekday on which the date occurs
|
|
233
|
+
* @param n The nth occurence of the given weekday on the month to return
|
|
234
|
+
* @param hour The hour of day which should be set on the returned date
|
|
235
|
+
* @return The date which is the nth occurence of a given weekday in a given
|
|
236
|
+
* month and year, at the given hour of day
|
|
237
|
+
*/
|
|
238
|
+
export function getNthWeekdayOfMonth(year: number, month: Month, weekday: Weekday, n: 1 | 2 | 3 | 4, hour = 0): Date {
|
|
239
|
+
let dayOfMonth = 0;
|
|
240
|
+
let i = 0;
|
|
241
|
+
while (i < n) {
|
|
242
|
+
dayOfMonth++;
|
|
243
|
+
const date = new Date(year, month - 1, dayOfMonth);
|
|
244
|
+
if (date.getDay() === weekday) i++;
|
|
245
|
+
}
|
|
246
|
+
return new Date(year, month - 1, dayOfMonth, hour);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Get the date which is the last occurence of a given weekday in a given month and year.
|
|
251
|
+
*
|
|
252
|
+
* @param year The year for which to find the date
|
|
253
|
+
* @param month The month in which the date occurs
|
|
254
|
+
* @param weekday The weekday on which the date occurs
|
|
255
|
+
* @param hour The hour of day which should be set on the returned date
|
|
256
|
+
* @return The date which is the last occurence of a given weekday in a given
|
|
257
|
+
* month and year, at the given hour of day
|
|
258
|
+
*/
|
|
259
|
+
export function getLastWeekdayOfMonth(year: number, month: Month, weekday: Weekday, hour = 0): Date {
|
|
260
|
+
// Procedure: Find the first weekday of the next month, compare with the given weekday,
|
|
261
|
+
// and use the difference to determine how many days to subtract from the first of the next month.
|
|
262
|
+
const oneIndexedWeekday = weekday === 0 ? 7 : weekday;
|
|
263
|
+
const date = new Date(year, month - 1 + 1, 1, 12);
|
|
264
|
+
const firstWeekdayNextMonth = date.getDay() === 0 ? 7 : date.getDay();
|
|
265
|
+
let dayDiff;
|
|
266
|
+
if (firstWeekdayNextMonth === oneIndexedWeekday) dayDiff = 7;
|
|
267
|
+
else if (firstWeekdayNextMonth < oneIndexedWeekday) dayDiff = 7 + firstWeekdayNextMonth - oneIndexedWeekday;
|
|
268
|
+
else dayDiff = firstWeekdayNextMonth - oneIndexedWeekday;
|
|
269
|
+
date.setDate(date.getDate() - dayDiff);
|
|
270
|
+
return new Date(year, month - 1, date.getDate(), hour);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Finds and returns timezone offset. If timezoneInput is numeric, it is returned. Otherwise, look for timezone offsets
|
|
275
|
+
* in the following order: timezoneOverrides -> {@link TIMEZONE_ABBR_MAP}.
|
|
276
|
+
*
|
|
277
|
+
* @param timezoneInput Uppercase timezone abbreviation or numeric offset in minutes
|
|
278
|
+
* @param date The date to use to determine whether to return DST offsets for ambiguous timezones
|
|
279
|
+
* @param timezoneOverrides Overrides for timezones
|
|
280
|
+
* @return timezone offset in minutes
|
|
281
|
+
*/
|
|
282
|
+
export function toTimezoneOffset(
|
|
283
|
+
timezoneInput?: string | number,
|
|
284
|
+
date?: Date,
|
|
285
|
+
timezoneOverrides: TimezoneAbbrMap = {}
|
|
286
|
+
): number | null {
|
|
287
|
+
if (timezoneInput == null) {
|
|
197
288
|
return null;
|
|
198
289
|
}
|
|
199
290
|
|
|
@@ -201,5 +292,31 @@ export function toTimezoneOffset(timezoneInput?: string | number): number | null
|
|
|
201
292
|
return timezoneInput;
|
|
202
293
|
}
|
|
203
294
|
|
|
204
|
-
|
|
295
|
+
const matchedTimezone = timezoneOverrides[timezoneInput] ?? TIMEZONE_ABBR_MAP[timezoneInput];
|
|
296
|
+
if (matchedTimezone == null) {
|
|
297
|
+
return null;
|
|
298
|
+
}
|
|
299
|
+
// This means that we have matched an unambiguous timezone
|
|
300
|
+
if (typeof matchedTimezone == "number") {
|
|
301
|
+
return matchedTimezone;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// The matched timezone is an ambiguous timezone, where the offset depends on whether the context (refDate)
|
|
305
|
+
// is during daylight savings or not.
|
|
306
|
+
|
|
307
|
+
// Without refDate as context, there's no way to know if DST or non-DST offset should be used. Return null instead.
|
|
308
|
+
if (date == null) {
|
|
309
|
+
return null;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// Return DST offset if the refDate is during daylight savings
|
|
313
|
+
if (
|
|
314
|
+
dayjs(date).isAfter(matchedTimezone.dstStart(date.getFullYear())) &&
|
|
315
|
+
!dayjs(date).isAfter(matchedTimezone.dstEnd(date.getFullYear()))
|
|
316
|
+
) {
|
|
317
|
+
return matchedTimezone.timezoneOffsetDuringDst;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// refDate is not during DST => return non-DST offset
|
|
321
|
+
return matchedTimezone.timezoneOffsetNonDst;
|
|
205
322
|
}
|
|
@@ -180,22 +180,22 @@ test("Test - Range Expression", function () {
|
|
|
180
180
|
});
|
|
181
181
|
|
|
182
182
|
test("Test - Timezone extraction", function () {
|
|
183
|
-
testSingleCase(chrono.de, "um 14 Uhr", new Date(2016,
|
|
183
|
+
testSingleCase(chrono.de, "um 14 Uhr", new Date(2016, 1, 28), (result, text) => {
|
|
184
184
|
expect(result.text).toBe(text);
|
|
185
185
|
expect(result.start.isCertain("timezoneOffset")).toBe(false);
|
|
186
186
|
expect(!result.start.get("timezoneOffset")).not.toBeNull();
|
|
187
187
|
});
|
|
188
188
|
|
|
189
|
-
testSingleCase(chrono.de, "um 14 Uhr CET", new Date(2016,
|
|
189
|
+
testSingleCase(chrono.de, "um 14 Uhr CET", new Date(2016, 1, 28), (result, text) => {
|
|
190
190
|
expect(result.text).toBe(text);
|
|
191
191
|
expect(result.start.isCertain("timezoneOffset")).toBe(true);
|
|
192
192
|
expect(result.start.get("timezoneOffset")).toBe(60);
|
|
193
193
|
});
|
|
194
194
|
|
|
195
|
-
testSingleCase(chrono.de, "14 Uhr cet", new Date(2016,
|
|
195
|
+
testSingleCase(chrono.de, "14 Uhr cet", new Date(2016, 4, 28), (result, text) => {
|
|
196
196
|
expect(result.text).toBe(text);
|
|
197
197
|
expect(result.start.isCertain("timezoneOffset")).toBe(true);
|
|
198
|
-
expect(result.start.get("timezoneOffset")).toBe(
|
|
198
|
+
expect(result.start.get("timezoneOffset")).toBe(120);
|
|
199
199
|
});
|
|
200
200
|
});
|
|
201
201
|
|
|
@@ -209,15 +209,15 @@ test("Test - Random date + time expression", function () {
|
|
|
209
209
|
expect(result.start.get("hour")).toBe(12);
|
|
210
210
|
});
|
|
211
211
|
|
|
212
|
-
testSingleCase(chrono.de, "am Freitag um 14 Uhr cetteln wir etwas an", new Date(2016,
|
|
212
|
+
testSingleCase(chrono.de, "am Freitag um 14 Uhr cetteln wir etwas an", new Date(2016, 1, 28), (result, text) => {
|
|
213
213
|
expect(result.text).toBe("am Freitag um 14 Uhr");
|
|
214
214
|
expect(result.start.isCertain("timezoneOffset")).toBe(false);
|
|
215
215
|
expect(!result.start.get("timezoneOffset")).not.toBeNull();
|
|
216
216
|
});
|
|
217
217
|
|
|
218
|
-
testSingleCase(chrono.de, "Freitag um 14 Uhr CET", new Date(2016,
|
|
218
|
+
testSingleCase(chrono.de, "Freitag um 14 Uhr CET", new Date(2016, 4, 28), (result, text) => {
|
|
219
219
|
expect(result.text).toBe(text);
|
|
220
220
|
expect(result.start.isCertain("timezoneOffset")).toBe(true);
|
|
221
|
-
expect(result.start.get("timezoneOffset")).toBe(
|
|
221
|
+
expect(result.start.get("timezoneOffset")).toBe(120);
|
|
222
222
|
});
|
|
223
223
|
});
|
package/test/en/en_month.test.ts
CHANGED
|
@@ -117,6 +117,76 @@ test("Test - Month-Only expression", function () {
|
|
|
117
117
|
});
|
|
118
118
|
});
|
|
119
119
|
|
|
120
|
+
test("Test - Month-Only Range expression", () => {
|
|
121
|
+
testSingleCase(chrono, "From May to December", new Date(2023, 4 - 1, 9), (result) => {
|
|
122
|
+
expect(result.start.get("year")).toBe(2023);
|
|
123
|
+
expect(result.start.get("month")).toBe(5);
|
|
124
|
+
expect(result.end.get("year")).toBe(2023);
|
|
125
|
+
expect(result.end.get("month")).toBe(12);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
testSingleCase(chrono, "From December to May", new Date(2023, 4 - 1, 9), (result) => {
|
|
129
|
+
expect(result.start.get("year")).toBe(2022);
|
|
130
|
+
expect(result.start.get("month")).toBe(12);
|
|
131
|
+
expect(result.end.get("year")).toBe(2023);
|
|
132
|
+
expect(result.end.get("month")).toBe(5);
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
testSingleCase(chrono, "From May to December, 2022", new Date(2023, 4 - 1, 9), (result) => {
|
|
136
|
+
expect(result.start.get("year")).toBe(2022);
|
|
137
|
+
expect(result.start.get("month")).toBe(5);
|
|
138
|
+
expect(result.end.get("year")).toBe(2022);
|
|
139
|
+
expect(result.end.get("month")).toBe(12);
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
testSingleCase(chrono, "From December to May 2022", new Date(2023, 4 - 1, 9), (result) => {
|
|
143
|
+
expect(result.start.get("year")).toBe(2021);
|
|
144
|
+
expect(result.start.get("month")).toBe(12);
|
|
145
|
+
expect(result.end.get("year")).toBe(2022);
|
|
146
|
+
expect(result.end.get("month")).toBe(5);
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
testSingleCase(chrono, "From December to May 2020", new Date(2023, 4 - 1, 9), (result) => {
|
|
150
|
+
expect(result.start.get("year")).toBe(2019);
|
|
151
|
+
expect(result.start.get("month")).toBe(12);
|
|
152
|
+
expect(result.end.get("year")).toBe(2020);
|
|
153
|
+
expect(result.end.get("month")).toBe(5);
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
testSingleCase(chrono, "From December to May 2025", new Date(2023, 4 - 1, 9), (result) => {
|
|
157
|
+
expect(result.start.get("year")).toBe(2024);
|
|
158
|
+
expect(result.start.get("month")).toBe(12);
|
|
159
|
+
expect(result.end.get("year")).toBe(2025);
|
|
160
|
+
expect(result.end.get("month")).toBe(5);
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
test("Test - Month with farward date option", () => {
|
|
165
|
+
testSingleCase(chrono, "in December", new Date(2023, 4 - 1, 9), { forwardDate: true }, (result) => {
|
|
166
|
+
expect(result.start.get("year")).toBe(2023);
|
|
167
|
+
expect(result.start.get("month")).toBe(12);
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
testSingleCase(chrono, "in May", new Date(2023, 4 - 1, 9), { forwardDate: true }, (result) => {
|
|
171
|
+
expect(result.start.get("year")).toBe(2023);
|
|
172
|
+
expect(result.start.get("month")).toBe(5);
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
testSingleCase(chrono, "From May to December", new Date(2023, 4 - 1, 9), { forwardDate: true }, (result) => {
|
|
176
|
+
expect(result.start.get("year")).toBe(2023);
|
|
177
|
+
expect(result.start.get("month")).toBe(5);
|
|
178
|
+
expect(result.end.get("year")).toBe(2023);
|
|
179
|
+
expect(result.end.get("month")).toBe(12);
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
testSingleCase(chrono, "From December to May", new Date(2023, 4 - 1, 9), { forwardDate: true }, (result) => {
|
|
183
|
+
expect(result.start.get("year")).toBe(2023);
|
|
184
|
+
expect(result.start.get("month")).toBe(12);
|
|
185
|
+
expect(result.end.get("year")).toBe(2024);
|
|
186
|
+
expect(result.end.get("month")).toBe(5);
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
|
|
120
190
|
test("Test - Month expression in context", function () {
|
|
121
191
|
testSingleCase(chrono, "The date is Sep 2012 is the date", (result) => {
|
|
122
192
|
expect(result.index).toBe(12);
|
|
@@ -300,6 +300,18 @@ test("Test - Before with reference", () => {
|
|
|
300
300
|
});
|
|
301
301
|
});
|
|
302
302
|
|
|
303
|
+
test("Test - Strict mode", function () {
|
|
304
|
+
testSingleCase(chrono.strict, "5 minutes ago", new Date(2012, 7, 10, 12, 14), (result, text) => {
|
|
305
|
+
expect(result.start.get("hour")).toBe(12);
|
|
306
|
+
expect(result.start.get("minute")).toBe(9);
|
|
307
|
+
expect(result.start).toBeDate(new Date(2012, 7, 10, 12, 9));
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
testUnexpectedResult(chrono.strict, "5m ago", new Date(2012, 7, 10, 12, 14));
|
|
311
|
+
testUnexpectedResult(chrono.strict, "5hr before", new Date(2012, 7, 10, 12, 14));
|
|
312
|
+
testUnexpectedResult(chrono.strict, "5 h ago", new Date(2012, 7, 10, 12, 14));
|
|
313
|
+
});
|
|
314
|
+
|
|
303
315
|
test("Test - Negative cases", function () {
|
|
304
316
|
testUnexpectedResult(chrono, "15 hours 29 min");
|
|
305
317
|
testUnexpectedResult(chrono, "a few hour");
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as chrono from "../../src";
|
|
2
2
|
import { testSingleCase, testUnexpectedResult } from "../test_util";
|
|
3
|
+
import ENTimeUnitCasualRelativeFormatParser from "../../src/locales/en/parsers/ENTimeUnitCasualRelativeFormatParser";
|
|
3
4
|
|
|
4
5
|
test("Test - Positive time units", () => {
|
|
5
6
|
testSingleCase(chrono, "next 2 weeks", new Date(2016, 10 - 1, 1, 12), (result, text) => {
|
|
@@ -141,6 +142,23 @@ test("Test - Minus '-' sign", () => {
|
|
|
141
142
|
});
|
|
142
143
|
});
|
|
143
144
|
|
|
145
|
+
test("Test - Without custom parser without abbreviations", function () {
|
|
146
|
+
const custom = chrono.en.strict.clone();
|
|
147
|
+
custom.parsers.push(new ENTimeUnitCasualRelativeFormatParser(false));
|
|
148
|
+
|
|
149
|
+
testUnexpectedResult(custom, "-3y");
|
|
150
|
+
testUnexpectedResult(custom, "last 2m");
|
|
151
|
+
|
|
152
|
+
testSingleCase(custom, "-2 hours 5 minutes", new Date(2016, 10 - 1, 1, 12), (result, text) => {
|
|
153
|
+
expect(result.text).toBe(text);
|
|
154
|
+
expect(result.start.get("year")).toBe(2016);
|
|
155
|
+
expect(result.start.get("month")).toBe(10);
|
|
156
|
+
expect(result.start.get("day")).toBe(1);
|
|
157
|
+
expect(result.start.get("hour")).toBe(9);
|
|
158
|
+
expect(result.start.get("minute")).toBe(55);
|
|
159
|
+
});
|
|
160
|
+
});
|
|
161
|
+
|
|
144
162
|
test("Test - Negative cases", () => {
|
|
145
163
|
testUnexpectedResult(chrono.casual, "3y", new Date(2015, 7 - 1, 10, 12, 14));
|
|
146
164
|
testUnexpectedResult(chrono.casual, "1 m", new Date(2015, 7 - 1, 10, 12, 14));
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as chrono from "../../src/";
|
|
2
|
-
import { testSingleCase } from "../test_util";
|
|
2
|
+
import { testSingleCase, testUnexpectedResult } from "../test_util";
|
|
3
3
|
import { Meridiem } from "../../src/";
|
|
4
4
|
|
|
5
5
|
test("Test - Later Expression", function () {
|
|
@@ -262,6 +262,16 @@ test("Test - From now Expression", () => {
|
|
|
262
262
|
});
|
|
263
263
|
|
|
264
264
|
test("Test - Strict mode", function () {
|
|
265
|
+
testSingleCase(chrono, "the min after", new Date(2012, 7, 10, 12, 14), (result) => {
|
|
266
|
+
expect(result.index).toBe(0);
|
|
267
|
+
expect(result.text).toBe("the min after");
|
|
268
|
+
expect(result.start.get("hour")).toBe(12);
|
|
269
|
+
expect(result.start.get("minute")).toBe(15);
|
|
270
|
+
expect(result.start.get("meridiem")).toBe(Meridiem.PM);
|
|
271
|
+
|
|
272
|
+
expect(result.start).toBeDate(new Date(2012, 7, 10, 12, 15));
|
|
273
|
+
});
|
|
274
|
+
|
|
265
275
|
testSingleCase(chrono.strict, "15 minutes from now", new Date(2012, 7, 10, 12, 14), (result, text) => {
|
|
266
276
|
expect(result.text).toBe(text);
|
|
267
277
|
expect(result.start.get("hour")).toBe(12);
|
|
@@ -279,15 +289,8 @@ test("Test - Strict mode", function () {
|
|
|
279
289
|
expect(result.start).toBeDate(new Date(2012, 7, 10, 13, 5));
|
|
280
290
|
});
|
|
281
291
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
expect(result.text).toBe("the min after");
|
|
285
|
-
expect(result.start.get("hour")).toBe(12);
|
|
286
|
-
expect(result.start.get("minute")).toBe(15);
|
|
287
|
-
expect(result.start.get("meridiem")).toBe(Meridiem.PM);
|
|
288
|
-
|
|
289
|
-
expect(result.start).toBeDate(new Date(2012, 7, 10, 12, 15));
|
|
290
|
-
});
|
|
292
|
+
testUnexpectedResult(chrono.strict, "15m from now");
|
|
293
|
+
testUnexpectedResult(chrono.strict, "15s later");
|
|
291
294
|
});
|
|
292
295
|
|
|
293
296
|
test("Test - After with reference", () => {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as chrono from "../../src";
|
|
2
|
-
import { testSingleCase } from "../test_util";
|
|
2
|
+
import { testSingleCase, testUnexpectedResult } from "../test_util";
|
|
3
|
+
import { Meridiem } from "../../src";
|
|
3
4
|
|
|
4
5
|
test("Test - The normal within expression", () => {
|
|
5
6
|
testSingleCase(chrono, "we have to make something in 5 days.", new Date(2012, 7, 10), (result) => {
|
|
@@ -327,3 +328,13 @@ test("Test - Time units' certainty", () => {
|
|
|
327
328
|
expect(result.start.isCertain("minute")).toBeFalsy();
|
|
328
329
|
});
|
|
329
330
|
});
|
|
331
|
+
|
|
332
|
+
test("Test - Strict mode", function () {
|
|
333
|
+
testSingleCase(chrono, "in 2hour", new Date(2016, 10 - 1, 1, 14, 52), (result, text) => {
|
|
334
|
+
expect(result.start.get("hour")).toBe(16);
|
|
335
|
+
expect(result.start.get("minute")).toBe(52);
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
testUnexpectedResult(chrono.strict, "in 15m");
|
|
339
|
+
testUnexpectedResult(chrono.strict, "within 5hr");
|
|
340
|
+
});
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import * as chrono from "../../src";
|
|
2
|
+
import { Month, Weekday } from "../../src";
|
|
3
|
+
import { getLastWeekdayOfMonth } from "../../src/timezone";
|
|
2
4
|
import { testSingleCase } from "../test_util";
|
|
3
5
|
|
|
4
6
|
test("Test - Parsing date/time with UTC offset", function () {
|
|
@@ -100,6 +102,146 @@ test("Test - Parsing date/time with timezone abbreviation", function () {
|
|
|
100
102
|
});
|
|
101
103
|
});
|
|
102
104
|
|
|
105
|
+
test("Test - Parsing date/time with ambiguous timezone abbreviations", function () {
|
|
106
|
+
// Test dates around transition to DST for ET
|
|
107
|
+
testSingleCase(chrono, "2022-03-12 23:00 ET", (result, text) => {
|
|
108
|
+
expect(result.text).toBe(text);
|
|
109
|
+
expect(result.start.get("hour")).toBe(23);
|
|
110
|
+
expect(result.start.get("timezoneOffset")).toBe(-5 * 60); // ET during standard time (EST) in 2022
|
|
111
|
+
});
|
|
112
|
+
testSingleCase(chrono, "2022-03-13 23:00 ET", (result, text) => {
|
|
113
|
+
expect(result.text).toBe(text);
|
|
114
|
+
expect(result.start.get("hour")).toBe(23);
|
|
115
|
+
expect(result.start.get("timezoneOffset")).toBe(-4 * 60); // ET during DST (EDT) in 2022
|
|
116
|
+
});
|
|
117
|
+
testSingleCase(chrono, "2021-03-13 23:00 ET", (result, text) => {
|
|
118
|
+
expect(result.text).toBe(text);
|
|
119
|
+
expect(result.start.get("hour")).toBe(23);
|
|
120
|
+
expect(result.start.get("timezoneOffset")).toBe(-5 * 60); // ET during standard time (EST) in 2021
|
|
121
|
+
});
|
|
122
|
+
testSingleCase(chrono, "2021-03-14 23:00 ET", (result, text) => {
|
|
123
|
+
expect(result.text).toBe(text);
|
|
124
|
+
expect(result.start.get("hour")).toBe(23);
|
|
125
|
+
expect(result.start.get("timezoneOffset")).toBe(-4 * 60); // ET during DST (EDT) in 2021
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
// Also test around transition *from* DST
|
|
129
|
+
testSingleCase(chrono, "2021-11-06 23:00 ET", (result, text) => {
|
|
130
|
+
expect(result.text).toBe(text);
|
|
131
|
+
expect(result.start.get("hour")).toBe(23);
|
|
132
|
+
expect(result.start.get("timezoneOffset")).toBe(-4 * 60); // ET during DST (EDT) in 2021
|
|
133
|
+
});
|
|
134
|
+
testSingleCase(chrono, "2021-11-07 23:00 ET", (result, text) => {
|
|
135
|
+
expect(result.text).toBe(text);
|
|
136
|
+
expect(result.start.get("hour")).toBe(23);
|
|
137
|
+
expect(result.start.get("timezoneOffset")).toBe(-5 * 60); // ET during standard time (EST) in 2021
|
|
138
|
+
});
|
|
139
|
+
testSingleCase(chrono, "2020-10-31 23:00 ET", (result, text) => {
|
|
140
|
+
expect(result.text).toBe(text);
|
|
141
|
+
expect(result.start.get("hour")).toBe(23);
|
|
142
|
+
expect(result.start.get("timezoneOffset")).toBe(-4 * 60); // ET during DST (EDT) in 2020
|
|
143
|
+
});
|
|
144
|
+
testSingleCase(chrono, "2020-11-01 23:00 ET", (result, text) => {
|
|
145
|
+
expect(result.text).toBe(text);
|
|
146
|
+
expect(result.start.get("hour")).toBe(23);
|
|
147
|
+
expect(result.start.get("timezoneOffset")).toBe(-5 * 60); // ET during standard time (EST) in 2020
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
// Same checks, but for CET (which transitions at different dates with different rules)
|
|
151
|
+
// Test dates around transition to DST for CET
|
|
152
|
+
testSingleCase(chrono, "2022-03-26 23:00 CET", (result, text) => {
|
|
153
|
+
expect(result.text).toBe(text);
|
|
154
|
+
expect(result.start.get("hour")).toBe(23);
|
|
155
|
+
expect(result.start.get("timezoneOffset")).toBe(60); // CET during standard time (CET) in 2022
|
|
156
|
+
});
|
|
157
|
+
testSingleCase(chrono, "2022-03-27 23:00 CET", (result, text) => {
|
|
158
|
+
expect(result.text).toBe(text);
|
|
159
|
+
expect(result.start.get("hour")).toBe(23);
|
|
160
|
+
expect(result.start.get("timezoneOffset")).toBe(2 * 60); // CET during DST (CEST) in 2022
|
|
161
|
+
});
|
|
162
|
+
testSingleCase(chrono, "2021-03-27 23:00 CET", (result, text) => {
|
|
163
|
+
expect(result.text).toBe(text);
|
|
164
|
+
expect(result.start.get("hour")).toBe(23);
|
|
165
|
+
expect(result.start.get("timezoneOffset")).toBe(60); // CET during standard time (CET) in 2021
|
|
166
|
+
});
|
|
167
|
+
testSingleCase(chrono, "2021-03-28 23:00 CET", (result, text) => {
|
|
168
|
+
expect(result.text).toBe(text);
|
|
169
|
+
expect(result.start.get("hour")).toBe(23);
|
|
170
|
+
expect(result.start.get("timezoneOffset")).toBe(2 * 60); // CET during DST (CEST) in 2021
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
// Also test around transition *from* DST for CET
|
|
174
|
+
testSingleCase(chrono, "2022-10-29 23:00 CET", (result, text) => {
|
|
175
|
+
expect(result.text).toBe(text);
|
|
176
|
+
expect(result.start.get("hour")).toBe(23);
|
|
177
|
+
expect(result.start.get("timezoneOffset")).toBe(2 * 60); // CET during DST (CEST) in 2022
|
|
178
|
+
});
|
|
179
|
+
testSingleCase(chrono, "2022-10-30 23:00 CET", (result, text) => {
|
|
180
|
+
expect(result.text).toBe(text);
|
|
181
|
+
expect(result.start.get("hour")).toBe(23);
|
|
182
|
+
expect(result.start.get("timezoneOffset")).toBe(60); // CET during standard time (CET) in 2022
|
|
183
|
+
});
|
|
184
|
+
testSingleCase(chrono, "2021-10-30 23:00 CET", (result, text) => {
|
|
185
|
+
expect(result.text).toBe(text);
|
|
186
|
+
expect(result.start.get("hour")).toBe(23);
|
|
187
|
+
expect(result.start.get("timezoneOffset")).toBe(2 * 60); // CET during DST (CEST) in 2021
|
|
188
|
+
});
|
|
189
|
+
testSingleCase(chrono, "2021-10-31 23:00 CET", (result, text) => {
|
|
190
|
+
expect(result.text).toBe(text);
|
|
191
|
+
expect(result.start.get("hour")).toBe(23);
|
|
192
|
+
expect(result.start.get("timezoneOffset")).toBe(60); // CET during standard time (CET) in 2021
|
|
193
|
+
});
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
test("Test - Timezone parsing overrides", function () {
|
|
197
|
+
// chrono.parse('at 10:00 XYZ', new Date(2023, 3, 20), {timezones: {XYZ: -180}})
|
|
198
|
+
// XYZ shouldn't be recognized or parsed as a timezone
|
|
199
|
+
testSingleCase(chrono, "Jan 1st 2023 at 10:00 XYZ", (result) => {
|
|
200
|
+
expect(result.text).toBe("Jan 1st 2023 at 10:00");
|
|
201
|
+
expect(result.start).toBeDate(new Date(2023, 1 - 1, 1, 10));
|
|
202
|
+
});
|
|
203
|
+
// Parse the correct tzoffset when XYZ is provided as a custom tz in parsingOptions
|
|
204
|
+
testSingleCase(
|
|
205
|
+
chrono,
|
|
206
|
+
"Jan 1st 2023 at 10:00 XYZ",
|
|
207
|
+
new Date(2023, 1, 1),
|
|
208
|
+
{ timezones: { XYZ: -180 } },
|
|
209
|
+
(result) => {
|
|
210
|
+
expect(result.text).toBe("Jan 1st 2023 at 10:00 XYZ");
|
|
211
|
+
expect(result.start.get("timezoneOffset")).toBe(-180);
|
|
212
|
+
}
|
|
213
|
+
);
|
|
214
|
+
// Parse the correct tzoffset when XYZ is provided as a custom ambiguous tz in parsingOptions
|
|
215
|
+
const parseXYZAsAmbiguousTz = {
|
|
216
|
+
timezoneOffsetDuringDst: -120,
|
|
217
|
+
timezoneOffsetNonDst: -180,
|
|
218
|
+
dstStart: (year: number) => getLastWeekdayOfMonth(year, Month.MARCH, Weekday.SUNDAY, 2),
|
|
219
|
+
dstEnd: (year: number) => getLastWeekdayOfMonth(year, Month.OCTOBER, Weekday.SUNDAY, 3),
|
|
220
|
+
};
|
|
221
|
+
// Parsing a non-DST date
|
|
222
|
+
testSingleCase(
|
|
223
|
+
chrono,
|
|
224
|
+
"Jan 1st 2023 at 10:00 XYZ",
|
|
225
|
+
new Date(2023, 1, 1),
|
|
226
|
+
{ timezones: { XYZ: parseXYZAsAmbiguousTz } },
|
|
227
|
+
(result) => {
|
|
228
|
+
expect(result.text).toBe("Jan 1st 2023 at 10:00 XYZ");
|
|
229
|
+
expect(result.start.get("timezoneOffset")).toBe(-180);
|
|
230
|
+
}
|
|
231
|
+
);
|
|
232
|
+
// Parsing a DST date
|
|
233
|
+
testSingleCase(
|
|
234
|
+
chrono,
|
|
235
|
+
"Jun 1st 2023 at 10:00 XYZ",
|
|
236
|
+
new Date(2023, 1, 1),
|
|
237
|
+
{ timezones: { XYZ: parseXYZAsAmbiguousTz } },
|
|
238
|
+
(result) => {
|
|
239
|
+
expect(result.text).toBe("Jun 1st 2023 at 10:00 XYZ");
|
|
240
|
+
expect(result.start.get("timezoneOffset")).toBe(-120);
|
|
241
|
+
}
|
|
242
|
+
);
|
|
243
|
+
});
|
|
244
|
+
|
|
103
245
|
test("Test - Parsing date with timezone abbreviation", function () {
|
|
104
246
|
testSingleCase(chrono, "Wednesday, September 16, 2020, EST", (result, text) => {
|
|
105
247
|
expect(result.text).toBe(text);
|
|
@@ -273,6 +273,32 @@ test("Test - Weekday Overlap", function () {
|
|
|
273
273
|
});
|
|
274
274
|
});
|
|
275
275
|
|
|
276
|
+
test("Test - Weekday range", () => {
|
|
277
|
+
testSingleCase(chrono.casual, "Friday to Monday", new Date(2023, 4 - 1, 9) /*Sunday*/, (result) => {
|
|
278
|
+
expect(result.start.get("year")).toBe(2023);
|
|
279
|
+
expect(result.start.get("month")).toBe(4);
|
|
280
|
+
expect(result.start.get("day")).toBe(7);
|
|
281
|
+
expect(result.start.get("weekday")).toBe(5);
|
|
282
|
+
|
|
283
|
+
expect(result.end.get("year")).toBe(2023);
|
|
284
|
+
expect(result.end.get("month")).toBe(4);
|
|
285
|
+
expect(result.end.get("day")).toBe(10);
|
|
286
|
+
expect(result.end.get("weekday")).toBe(1);
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
testSingleCase(chrono.casual, "Monday to Friday", new Date(2023, 4 - 1, 9) /*Sunday*/, (result) => {
|
|
290
|
+
expect(result.start.get("year")).toBe(2023);
|
|
291
|
+
expect(result.start.get("month")).toBe(4);
|
|
292
|
+
expect(result.start.get("day")).toBe(10);
|
|
293
|
+
expect(result.start.get("weekday")).toBe(1);
|
|
294
|
+
|
|
295
|
+
expect(result.end.get("year")).toBe(2023);
|
|
296
|
+
expect(result.end.get("month")).toBe(4);
|
|
297
|
+
expect(result.end.get("day")).toBe(14);
|
|
298
|
+
expect(result.end.get("weekday")).toBe(5);
|
|
299
|
+
});
|
|
300
|
+
});
|
|
301
|
+
|
|
276
302
|
test("Test - forward dates only option", () => {
|
|
277
303
|
testSingleCase(
|
|
278
304
|
chrono.casual,
|
|
@@ -63,6 +63,8 @@ test("Test - Skip impossible dates/times", () => {
|
|
|
63
63
|
|
|
64
64
|
testUnexpectedResult(chrono, "14PM");
|
|
65
65
|
testUnexpectedResult(chrono, "25:12");
|
|
66
|
+
|
|
67
|
+
testUnexpectedResult(chrono, "An appointment on 13/31/2018");
|
|
66
68
|
});
|
|
67
69
|
|
|
68
70
|
test("Test - Skip version number pattern", () => {
|
|
@@ -488,13 +488,13 @@ test("Test - Timezone extraction", function () {
|
|
|
488
488
|
expect(result.start.get("timezoneOffset")).toBe(-300);
|
|
489
489
|
});
|
|
490
490
|
|
|
491
|
-
testSingleCase(chrono.fr, "vendredi 15h CET", new Date(2016,
|
|
491
|
+
testSingleCase(chrono.fr, "vendredi 15h CET", new Date(2016, 1, 28), (result, text) => {
|
|
492
492
|
expect(result.text).toBe(text);
|
|
493
493
|
expect(result.start.isCertain("timezoneOffset")).toBe(true);
|
|
494
494
|
expect(result.start.get("timezoneOffset")).toBe(60);
|
|
495
495
|
});
|
|
496
496
|
|
|
497
|
-
testSingleCase(chrono.fr, "vendredi 15h cest", new Date(2016,
|
|
497
|
+
testSingleCase(chrono.fr, "vendredi 15h cest", new Date(2016, 1, 28), (result, text) => {
|
|
498
498
|
expect(result.text).toBe(text);
|
|
499
499
|
expect(result.start.isCertain("timezoneOffset")).toBe(true);
|
|
500
500
|
expect(result.start.get("timezoneOffset")).toBe(120);
|