chrono-node 2.3.1 → 2.3.5

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.
Files changed (97) hide show
  1. package/README.md +1 -1
  2. package/dist/common/casualReferences.js +3 -1
  3. package/dist/common/parsers/AbstractParserWithWordBoundary.js +2 -1
  4. package/dist/common/refiners/ForwardDateRefiner.js +1 -1
  5. package/dist/index.d.ts +2 -1
  6. package/dist/index.js +3 -1
  7. package/dist/locales/de/constants.js +1 -1
  8. package/dist/locales/en/constants.js +1 -1
  9. package/dist/locales/en/parsers/ENRelativeDateFormatParser.js +3 -3
  10. package/dist/locales/en/parsers/ENTimeUnitAgoFormatParser.js +1 -1
  11. package/dist/locales/en/parsers/ENTimeUnitCasualRelativeFormatParser.js +1 -1
  12. package/dist/locales/en/parsers/ENTimeUnitLaterFormatParser.js +1 -1
  13. package/dist/locales/en/parsers/ENTimeUnitWithinFormatParser.js +1 -1
  14. package/dist/locales/fr/constants.js +1 -1
  15. package/dist/locales/fr/parsers/FRTimeUnitAgoFormatParser.js +1 -1
  16. package/dist/locales/fr/parsers/FRTimeUnitRelativeFormatParser.js +1 -1
  17. package/dist/locales/fr/parsers/FRTimeUnitWithinFormatParser.js +1 -1
  18. package/dist/locales/nl/parsers/NLRelativeDateFormatParser.js +3 -3
  19. package/dist/locales/nl/parsers/NLTimeUnitAgoFormatParser.js +1 -1
  20. package/dist/locales/nl/parsers/NLTimeUnitCasualRelativeFormatParser.js +1 -1
  21. package/dist/locales/nl/parsers/NLTimeUnitLaterFormatParser.js +1 -1
  22. package/dist/locales/nl/parsers/NLTimeUnitWithinFormatParser.js +1 -1
  23. package/dist/locales/zh/hant/constants.d.ts +28 -0
  24. package/dist/locales/zh/hant/constants.js +52 -0
  25. package/dist/locales/zh/hant/parsers/ZHHantCasualDateParser.d.ts +7 -0
  26. package/dist/locales/zh/hant/parsers/ZHHantCasualDateParser.js +138 -0
  27. package/dist/locales/zh/hant/parsers/ZHHantDateParser.d.ts +6 -0
  28. package/dist/locales/zh/hant/parsers/ZHHantDateParser.js +64 -0
  29. package/dist/locales/zh/hant/parsers/ZHHantDeadlineFormatParser.d.ts +6 -0
  30. package/dist/locales/zh/hant/parsers/ZHHantDeadlineFormatParser.js +78 -0
  31. package/dist/locales/zh/hant/parsers/ZHHantRelationWeekdayParser.d.ts +7 -0
  32. package/dist/locales/zh/hant/parsers/ZHHantRelationWeekdayParser.js +70 -0
  33. package/dist/locales/zh/hant/parsers/ZHHantTimeExpressionParser.d.ts +6 -0
  34. package/dist/locales/zh/hant/parsers/ZHHantTimeExpressionParser.js +438 -0
  35. package/dist/locales/zh/hant/parsers/ZHHantWeekdayParser.d.ts +7 -0
  36. package/dist/locales/zh/hant/parsers/ZHHantWeekdayParser.js +46 -0
  37. package/dist/locales/zh/hant/refiners/ZHHantMergeDateRangeRefiner.d.ts +4 -0
  38. package/dist/locales/zh/hant/refiners/ZHHantMergeDateRangeRefiner.js +12 -0
  39. package/dist/locales/zh/hant/refiners/ZHHantMergeDateTimeRefiner.d.ts +4 -0
  40. package/dist/locales/zh/hant/refiners/ZHHantMergeDateTimeRefiner.js +12 -0
  41. package/dist/locales/zh/index.d.ts +9 -0
  42. package/dist/locales/zh/index.js +49 -0
  43. package/dist/results.d.ts +2 -2
  44. package/dist/results.js +18 -12
  45. package/dist/timezone.d.ts +1 -1
  46. package/dist/timezone.js +3 -0
  47. package/dist/utils/dayjs.js +7 -0
  48. package/package.json +1 -1
  49. package/src/common/casualReferences.ts +3 -1
  50. package/src/common/parsers/AbstractParserWithWordBoundary.ts +1 -1
  51. package/src/common/refiners/ForwardDateRefiner.ts +1 -1
  52. package/src/index.ts +2 -1
  53. package/src/locales/de/constants.ts +1 -1
  54. package/src/locales/en/constants.ts +1 -1
  55. package/src/locales/en/parsers/ENRelativeDateFormatParser.ts +3 -3
  56. package/src/locales/en/parsers/ENTimeUnitAgoFormatParser.ts +1 -1
  57. package/src/locales/en/parsers/ENTimeUnitCasualRelativeFormatParser.ts +1 -1
  58. package/src/locales/en/parsers/ENTimeUnitLaterFormatParser.ts +1 -1
  59. package/src/locales/en/parsers/ENTimeUnitWithinFormatParser.ts +1 -1
  60. package/src/locales/fr/constants.ts +1 -1
  61. package/src/locales/fr/parsers/FRTimeUnitAgoFormatParser.ts +1 -1
  62. package/src/locales/fr/parsers/FRTimeUnitRelativeFormatParser.ts +1 -1
  63. package/src/locales/fr/parsers/FRTimeUnitWithinFormatParser.ts +1 -1
  64. package/src/locales/nl/parsers/NLRelativeDateFormatParser.ts +3 -3
  65. package/src/locales/nl/parsers/NLTimeUnitAgoFormatParser.ts +1 -1
  66. package/src/locales/nl/parsers/NLTimeUnitCasualRelativeFormatParser.ts +1 -1
  67. package/src/locales/nl/parsers/NLTimeUnitLaterFormatParser.ts +1 -1
  68. package/src/locales/nl/parsers/NLTimeUnitWithinFormatParser.ts +1 -1
  69. package/src/locales/zh/hant/constants.ts +53 -0
  70. package/src/locales/zh/hant/parsers/ZHHantCasualDateParser.ts +128 -0
  71. package/src/locales/zh/hant/parsers/ZHHantDateParser.ts +68 -0
  72. package/src/locales/zh/hant/parsers/ZHHantDeadlineFormatParser.ts +81 -0
  73. package/src/locales/zh/hant/parsers/ZHHantRelationWeekdayParser.ts +69 -0
  74. package/src/locales/zh/hant/parsers/ZHHantTimeExpressionParser.ts +424 -0
  75. package/src/locales/zh/hant/parsers/ZHHantWeekdayParser.ts +46 -0
  76. package/src/locales/zh/hant/refiners/ZHHantMergeDateRangeRefiner.ts +7 -0
  77. package/src/locales/zh/hant/refiners/ZHHantMergeDateTimeRefiner.ts +7 -0
  78. package/src/locales/zh/index.ts +63 -0
  79. package/src/results.ts +22 -12
  80. package/src/timezone.ts +5 -1
  81. package/src/utils/dayjs.ts +6 -0
  82. package/test/en/en_casual.test.ts +11 -0
  83. package/test/en/en_month_name_little_endian.test.ts +10 -0
  84. package/test/en/en_relative.test.ts +8 -0
  85. package/test/en/en_slash.test.ts +11 -0
  86. package/test/en/en_time_units_ago.test.ts +16 -0
  87. package/test/en/en_time_units_later.test.ts +6 -0
  88. package/test/en/en_timezone_exp.test.ts +85 -10
  89. package/test/en/en_weekday.test.ts +69 -25
  90. package/test/en/negative_cases.test.ts +2 -0
  91. package/test/test_util.ts +5 -2
  92. package/test/zh/zh.test.ts +18 -0
  93. package/test/zh/zh_hant_casual.test.ts +246 -0
  94. package/test/zh/zh_hant_date.test.ts +103 -0
  95. package/test/zh/zh_hant_deadline.test.ts +136 -0
  96. package/test/zh/zh_hant_time_exp.test.ts +182 -0
  97. package/test/zh/zh_hant_weekday.test.ts +132 -0
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Chrono components for zh support
3
+ * TODO: Complete general zh support (current support only zh-Hant)
4
+ */
5
+
6
+ import { Chrono, Configuration } from "../../chrono";
7
+ import ExtractTimezoneOffsetRefiner from "../../common/refiners/ExtractTimezoneOffsetRefiner";
8
+ import { includeCommonConfiguration } from "../../configurations";
9
+ import { ParsedResult, ParsingOption } from "../../index";
10
+ import ZHHantCasualDateParser from "./hant/parsers/ZHHantCasualDateParser";
11
+ import ZHHantDateParser from "./hant/parsers/ZHHantDateParser";
12
+ import ZHHantDeadlineFormatParser from "./hant/parsers/ZHHantDeadlineFormatParser";
13
+ import ZHHantRelationWeekdayParser from "./hant/parsers/ZHHantRelationWeekdayParser";
14
+ import ZHHantTimeExpressionParser from "./hant/parsers/ZHHantTimeExpressionParser";
15
+ import ZHHantWeekdayParser from "./hant/parsers/ZHHantWeekdayParser";
16
+ import ZHHantMergeDateRangeRefiner from "./hant/refiners/ZHHantMergeDateRangeRefiner";
17
+ import ZHHantMergeDateTimeRefiner from "./hant/refiners/ZHHantMergeDateTimeRefiner";
18
+
19
+ // Shortcuts
20
+ export const hant = new Chrono(createCasualConfiguration());
21
+
22
+ export const casual = new Chrono(createCasualConfiguration());
23
+ export const strict = new Chrono(createConfiguration());
24
+
25
+ export function parse(text: string, ref?: Date, option?: ParsingOption): ParsedResult[] {
26
+ return casual.parse(text, ref, option);
27
+ }
28
+
29
+ export function parseDate(text: string, ref?: Date, option?: ParsingOption): Date {
30
+ return casual.parseDate(text, ref, option);
31
+ }
32
+
33
+ /**
34
+ * @ignore (to be documented later)
35
+ */
36
+ export function createCasualConfiguration(): Configuration {
37
+ const option = createConfiguration();
38
+ option.parsers.unshift(new ZHHantCasualDateParser());
39
+ return option;
40
+ }
41
+
42
+ /**
43
+ * @ignore (to be documented later)
44
+ */
45
+ export function createConfiguration(): Configuration {
46
+ const configuration = includeCommonConfiguration({
47
+ parsers: [
48
+ new ZHHantDateParser(),
49
+ new ZHHantRelationWeekdayParser(),
50
+ new ZHHantWeekdayParser(),
51
+ new ZHHantTimeExpressionParser(),
52
+ new ZHHantDeadlineFormatParser(),
53
+ ],
54
+ refiners: [new ZHHantMergeDateRangeRefiner(), new ZHHantMergeDateTimeRefiner()],
55
+ });
56
+
57
+ // REMOVE ExtractTimezoneOffsetRefiner
58
+ configuration.refiners = configuration.refiners.filter(
59
+ (refiner) => !(refiner instanceof ExtractTimezoneOffsetRefiner)
60
+ );
61
+
62
+ return configuration;
63
+ }
package/src/results.ts CHANGED
@@ -8,7 +8,7 @@ dayjs.extend(quarterOfYear);
8
8
 
9
9
  export class ReferenceWithTimezone {
10
10
  readonly instant: Date;
11
- readonly timezoneOffset: number;
11
+ readonly timezoneOffset?: number;
12
12
 
13
13
  constructor(input?: ParsingReference | Date) {
14
14
  input = input ?? new Date();
@@ -17,7 +17,7 @@ export class ReferenceWithTimezone {
17
17
  this.timezoneOffset = -input.getTimezoneOffset();
18
18
  } else {
19
19
  this.instant = input.instant ?? new Date();
20
- this.timezoneOffset = toTimezoneOffset(input.timezone ?? -this.instant.getTimezoneOffset());
20
+ this.timezoneOffset = toTimezoneOffset(input.timezone);
21
21
  }
22
22
  }
23
23
  }
@@ -142,7 +142,7 @@ export class ParsingComponents implements ParsedComponents {
142
142
 
143
143
  date(): Date {
144
144
  const date = this.dateWithoutTimezoneAdjustment();
145
- return new Date(date.getTime() + this.getSystemTimezoneAdjustmentMinute() * 60000);
145
+ return new Date(date.getTime() + this.getSystemTimezoneAdjustmentMinute(date) * 60000);
146
146
  }
147
147
 
148
148
  private dateWithoutTimezoneAdjustment() {
@@ -160,31 +160,41 @@ export class ParsingComponents implements ParsedComponents {
160
160
  return date;
161
161
  }
162
162
 
163
- private getSystemTimezoneAdjustmentMinute() {
164
- const currentTimezoneOffset = -new Date().getTimezoneOffset();
165
- const targetTimezoneOffset = this.get("timezoneOffset") ?? this.reference.timezoneOffset;
163
+ private getSystemTimezoneAdjustmentMinute(date?: Date) {
164
+ if (!date || date.getTime() < 0) {
165
+ // Javascript date timezone calculation got effect when the time epoch < 0
166
+ // e.g. new Date('Tue Feb 02 1300 00:00:00 GMT+0900 (JST)') => Tue Feb 02 1300 00:18:59 GMT+0918 (JST)
167
+ date = new Date();
168
+ }
169
+
170
+ const currentTimezoneOffset = -date.getTimezoneOffset();
171
+ const targetTimezoneOffset =
172
+ this.get("timezoneOffset") ?? this.reference.timezoneOffset ?? currentTimezoneOffset;
166
173
 
167
174
  return currentTimezoneOffset - targetTimezoneOffset;
168
175
  }
169
176
 
170
- static createRelativeFromRefInstant(
171
- refInstant: Date,
177
+ static createRelativeFromReference(
178
+ reference: ReferenceWithTimezone,
172
179
  fragments: { [c in OpUnitType | QUnitType]?: number }
173
180
  ): ParsingComponents {
174
- let date = dayjs(refInstant);
181
+ let date = dayjs(reference.instant);
175
182
  for (const key in fragments) {
176
183
  date = date.add(fragments[key as OpUnitType], key as OpUnitType);
177
184
  }
178
185
 
179
- const reference = new ReferenceWithTimezone(refInstant);
180
186
  const components = new ParsingComponents(reference);
181
187
  if (fragments["hour"] || fragments["minute"] || fragments["second"]) {
182
188
  assignSimilarTime(components, date);
183
189
  assignSimilarDate(components, date);
184
- components.assign("timezoneOffset", -refInstant.getTimezoneOffset());
190
+ if (reference.timezoneOffset !== null) {
191
+ components.assign("timezoneOffset", -reference.instant.getTimezoneOffset());
192
+ }
185
193
  } else {
186
194
  implySimilarTime(components, date);
187
- components.imply("timezoneOffset", -refInstant.getTimezoneOffset());
195
+ if (reference.timezoneOffset !== null) {
196
+ components.imply("timezoneOffset", -reference.instant.getTimezoneOffset());
197
+ }
188
198
 
189
199
  if (fragments["d"]) {
190
200
  components.assign("day", date.date());
package/src/timezone.ts CHANGED
@@ -192,7 +192,11 @@ export const TIMEZONE_ABBR_MAP = {
192
192
  YEKT: 360,
193
193
  };
194
194
 
195
- export function toTimezoneOffset(timezoneInput: string | number): number {
195
+ export function toTimezoneOffset(timezoneInput: string | number): number | null {
196
+ if (timezoneInput === null) {
197
+ return null;
198
+ }
199
+
196
200
  if (typeof timezoneInput === "number") {
197
201
  return timezoneInput;
198
202
  }
@@ -1,5 +1,6 @@
1
1
  import { ParsingComponents } from "../results";
2
2
  import dayjs from "dayjs";
3
+ import { Meridiem } from "../index";
3
4
 
4
5
  export function assignTheNextDay(component: ParsingComponents, targetDayJs: dayjs.Dayjs) {
5
6
  targetDayJs = targetDayJs.add(1, "day");
@@ -18,6 +19,11 @@ export function assignSimilarTime(component: ParsingComponents, targetDayJs: day
18
19
  component.assign("minute", targetDayJs.minute());
19
20
  component.assign("second", targetDayJs.second());
20
21
  component.assign("millisecond", targetDayJs.millisecond());
22
+ if (component.get("hour") < 12) {
23
+ component.assign("meridiem", Meridiem.AM);
24
+ } else {
25
+ component.assign("meridiem", Meridiem.PM);
26
+ }
21
27
  }
22
28
 
23
29
  export function implySimilarTime(component: ParsingComponents, targetDayJs: dayjs.Dayjs) {
@@ -21,6 +21,17 @@ test("Test - Single Expression", () => {
21
21
  expect(result.start).toBeDate(new Date(2012, 7, 10, 8, 9, 10, 11));
22
22
  });
23
23
 
24
+ testSingleCase(
25
+ chrono.casual,
26
+ "The Deadline is now, without implicit local timezone",
27
+ { instant: new Date(1637674343000), timezone: null },
28
+ (result) => {
29
+ expect(result.text).toBe("now");
30
+ expect(result.start).toBeDate(new Date(1637674343000));
31
+ expect(result.start.isCertain("timezoneOffset")).toBe(false);
32
+ }
33
+ );
34
+
24
35
  testSingleCase(chrono.casual, "The Deadline is today", new Date(2012, 7, 10, 14, 12), (result) => {
25
36
  expect(result.index).toBe(16);
26
37
  expect(result.text).toBe("today");
@@ -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 () {
@@ -230,4 +230,12 @@ test("Test - Relative date components' certainty and imply timezone", () => {
230
230
  expect(result).toBeDate(new Date("Sun Nov 29 2020 13:34:13 GMT+0900 (Japan Standard Time)"));
231
231
  expect(result).toBeDate(new Date("Sun Nov 29 2020 5:34:13 GMT+0100"));
232
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
+ }
233
241
  });
@@ -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
  });
@@ -1,5 +1,6 @@
1
1
  import * as chrono from "../../src/";
2
2
  import { testSingleCase, testUnexpectedResult } from "../test_util";
3
+ import { Meridiem } from "../../src/";
3
4
 
4
5
  test("Test - Single Expression", function () {
5
6
  testSingleCase(chrono, "5 days ago, we did something", new Date(2012, 7, 10), (result) => {
@@ -31,6 +32,7 @@ test("Test - Single Expression", function () {
31
32
  expect(result.text).toBe("15 minute ago");
32
33
  expect(result.start.get("hour")).toBe(11);
33
34
  expect(result.start.get("minute")).toBe(59);
35
+ expect(result.start.get("meridiem")).toBe(Meridiem.AM);
34
36
 
35
37
  expect(result.start).toBeDate(new Date(2012, 7, 10, 11, 59));
36
38
  });
@@ -40,6 +42,7 @@ test("Test - Single Expression", function () {
40
42
  expect(result.text).toBe("15 minute earlier");
41
43
  expect(result.start.get("hour")).toBe(11);
42
44
  expect(result.start.get("minute")).toBe(59);
45
+ expect(result.start.get("meridiem")).toBe(Meridiem.AM);
43
46
 
44
47
  expect(result.start).toBeDate(new Date(2012, 7, 10, 11, 59));
45
48
  });
@@ -49,6 +52,7 @@ test("Test - Single Expression", function () {
49
52
  expect(result.text).toBe("15 minute before");
50
53
  expect(result.start.get("hour")).toBe(11);
51
54
  expect(result.start.get("minute")).toBe(59);
55
+ expect(result.start.get("meridiem")).toBe(Meridiem.AM);
52
56
 
53
57
  expect(result.start).toBeDate(new Date(2012, 7, 10, 11, 59));
54
58
  });
@@ -58,6 +62,7 @@ test("Test - Single Expression", function () {
58
62
  expect(result.text).toBe("12 hours ago");
59
63
  expect(result.start.get("hour")).toBe(0);
60
64
  expect(result.start.get("minute")).toBe(14);
65
+ expect(result.start.get("meridiem")).toBe(Meridiem.AM);
61
66
 
62
67
  expect(result.start).toBeDate(new Date(2012, 7, 10, 0, 14));
63
68
  });
@@ -67,6 +72,7 @@ test("Test - Single Expression", function () {
67
72
  expect(result.text).toBe("1h ago");
68
73
  expect(result.start.get("hour")).toBe(11);
69
74
  expect(result.start.get("minute")).toBe(14);
75
+ expect(result.start.get("meridiem")).toBe(Meridiem.AM);
70
76
  });
71
77
 
72
78
  testSingleCase(chrono, "1hr ago", new Date(2012, 7, 10, 12, 14), (result) => {
@@ -74,6 +80,7 @@ test("Test - Single Expression", function () {
74
80
  expect(result.text).toBe("1hr ago");
75
81
  expect(result.start.get("hour")).toBe(11);
76
82
  expect(result.start.get("minute")).toBe(14);
83
+ expect(result.start.get("meridiem")).toBe(Meridiem.AM);
77
84
  });
78
85
 
79
86
  testSingleCase(chrono, " half an hour ago", new Date(2012, 7, 10, 12, 14), (result) => {
@@ -81,6 +88,7 @@ test("Test - Single Expression", function () {
81
88
  expect(result.text).toBe("half an hour ago");
82
89
  expect(result.start.get("hour")).toBe(11);
83
90
  expect(result.start.get("minute")).toBe(44);
91
+ expect(result.start.get("meridiem")).toBe(Meridiem.AM);
84
92
 
85
93
  expect(result.start).toBeDate(new Date(2012, 7, 10, 11, 44));
86
94
  });
@@ -90,6 +98,7 @@ test("Test - Single Expression", function () {
90
98
  expect(result.text).toBe("12 hours ago");
91
99
  expect(result.start.get("hour")).toBe(0);
92
100
  expect(result.start.get("minute")).toBe(14);
101
+ expect(result.start.get("meridiem")).toBe(Meridiem.AM);
93
102
 
94
103
  expect(result.start).toBeDate(new Date(2012, 7, 10, 0, 14));
95
104
  });
@@ -100,6 +109,7 @@ test("Test - Single Expression", function () {
100
109
  expect(result.start.get("hour")).toBe(12);
101
110
  expect(result.start.get("minute")).toBe(13);
102
111
  expect(result.start.get("second")).toBe(48);
112
+ expect(result.start.get("meridiem")).toBe(Meridiem.PM);
103
113
 
104
114
  expect(result.start).toBeDate(new Date(2012, 7, 10, 12, 13, 48));
105
115
  });
@@ -110,6 +120,7 @@ test("Test - Single Expression", function () {
110
120
  expect(result.start.get("hour")).toBe(12);
111
121
  expect(result.start.get("minute")).toBe(13);
112
122
  expect(result.start.get("second")).toBe(57);
123
+ expect(result.start.get("meridiem")).toBe(Meridiem.PM);
113
124
 
114
125
  expect(result.start).toBeDate(new Date(2012, 7, 10, 12, 13, 57));
115
126
  });
@@ -131,6 +142,7 @@ test("Test - Single Expression", function () {
131
142
  expect(result.text).toBe("half An hour ago");
132
143
  expect(result.start.get("hour")).toBe(11);
133
144
  expect(result.start.get("minute")).toBe(44);
145
+ expect(result.start.get("meridiem")).toBe(Meridiem.AM);
134
146
 
135
147
  expect(result.start).toBeDate(new Date(2012, 7, 10, 11, 44));
136
148
  });
@@ -152,6 +164,7 @@ test("Test - Single Expression", function () {
152
164
  expect(result.text).toBe("a min before");
153
165
  expect(result.start.get("hour")).toBe(12);
154
166
  expect(result.start.get("minute")).toBe(13);
167
+ expect(result.start.get("meridiem")).toBe(Meridiem.PM);
155
168
 
156
169
  expect(result.start).toBeDate(new Date(2012, 7, 10, 12, 13));
157
170
  });
@@ -213,6 +226,7 @@ test("Test - Nested time ago", function () {
213
226
  expect(result.start.get("day")).toBe(10);
214
227
  expect(result.start.get("hour")).toBe(7);
215
228
  expect(result.start.get("minute")).toBe(1);
229
+ expect(result.start.get("meridiem")).toBe(Meridiem.AM);
216
230
  });
217
231
 
218
232
  testSingleCase(chrono, "1 day 21 hours ago ", new Date(2012, 7, 10, 22, 30), (result) => {
@@ -220,6 +234,7 @@ test("Test - Nested time ago", function () {
220
234
  expect(result.start.get("day")).toBe(9);
221
235
  expect(result.start.get("hour")).toBe(1);
222
236
  expect(result.start.get("minute")).toBe(30);
237
+ expect(result.start.get("meridiem")).toBe(Meridiem.AM);
223
238
  });
224
239
 
225
240
  testSingleCase(chrono, "3 min 49 sec ago ", new Date(2012, 7, 10, 22, 30), (result) => {
@@ -228,6 +243,7 @@ test("Test - Nested time ago", function () {
228
243
  expect(result.start.get("hour")).toBe(22);
229
244
  expect(result.start.get("minute")).toBe(26);
230
245
  expect(result.start.get("second")).toBe(11);
246
+ expect(result.start.get("meridiem")).toBe(Meridiem.PM);
231
247
  });
232
248
  });
233
249
 
@@ -1,5 +1,6 @@
1
1
  import * as chrono from "../../src/";
2
2
  import { testSingleCase } from "../test_util";
3
+ import { Meridiem } from "../../src/";
3
4
 
4
5
  test("Test - Later Expression", function () {
5
6
  testSingleCase(chrono, "2 days later", new Date(2012, 7, 10, 12), (result) => {
@@ -77,6 +78,7 @@ test("Test - From now Expression", () => {
77
78
  expect(result.text).toBe("15 minute from now");
78
79
  expect(result.start.get("hour")).toBe(12);
79
80
  expect(result.start.get("minute")).toBe(29);
81
+ expect(result.start.get("meridiem")).toBe(Meridiem.PM);
80
82
 
81
83
  expect(result.start).toBeDate(new Date(2012, 7, 10, 12, 29));
82
84
  });
@@ -86,6 +88,7 @@ test("Test - From now Expression", () => {
86
88
  expect(result.text).toBe("15 minutes earlier");
87
89
  expect(result.start.get("hour")).toBe(11);
88
90
  expect(result.start.get("minute")).toBe(59);
91
+ expect(result.start.get("meridiem")).toBe(Meridiem.AM);
89
92
 
90
93
  expect(result.start).toBeDate(new Date(2012, 7, 10, 11, 59));
91
94
  });
@@ -95,6 +98,7 @@ test("Test - From now Expression", () => {
95
98
  expect(result.text).toBe("15 minute out");
96
99
  expect(result.start.get("hour")).toBe(12);
97
100
  expect(result.start.get("minute")).toBe(29);
101
+ expect(result.start.get("meridiem")).toBe(Meridiem.PM);
98
102
 
99
103
  expect(result.start).toBeDate(new Date(2012, 7, 10, 12, 29));
100
104
  });
@@ -115,6 +119,7 @@ test("Test - From now Expression", () => {
115
119
  expect(result.start.get("day")).toBe(11);
116
120
  expect(result.start.get("hour")).toBe(0);
117
121
  expect(result.start.get("minute")).toBe(14);
122
+ expect(result.start.get("meridiem")).toBe(Meridiem.AM);
118
123
  });
119
124
 
120
125
  testSingleCase(chrono, " half an hour from now", new Date(2012, 7, 10, 12, 14), (result) => {
@@ -122,6 +127,7 @@ test("Test - From now Expression", () => {
122
127
  expect(result.text).toBe("half an hour from now");
123
128
  expect(result.start.get("hour")).toBe(12);
124
129
  expect(result.start.get("minute")).toBe(44);
130
+ expect(result.start.get("meridiem")).toBe(Meridiem.PM);
125
131
 
126
132
  expect(result.start).toBeDate(new Date(2012, 7, 10, 12, 44));
127
133
  });
@@ -81,20 +81,95 @@ test("Test - Parsing date with timezone abbreviation", function () {
81
81
  });
82
82
 
83
83
  test("Test - Not parsing timezone from relative time", function () {
84
- const refDate = new Date(2020, 11 - 1, 14, 13, 48, 22);
84
+ {
85
+ const refInstant = new Date("Sun Nov 29 2020 13:24:13 GMT+0900 (Japan Standard Time)");
86
+ const expectedInstant = new Date("Sun Nov 29 2020 14:24:13 GMT+0900 (Japan Standard Time)");
87
+
88
+ testSingleCase(chrono, "in 1 hour get eggs and milk", refInstant, (result, text) => {
89
+ expect(result.text).toBe("in 1 hour");
90
+ expect(result.start.get("timezoneOffset")).toBe(-refInstant.getTimezoneOffset());
91
+ expect(result.start).toBeDate(expectedInstant);
92
+ });
93
+ }
94
+
95
+ {
96
+ const refInstant = new Date("Sun Nov 29 2020 13:24:13 GMT+0900 (Japan Standard Time)");
97
+ const expectedInstant = new Date("Sun Nov 29 2020 14:24:13 GMT+0900 (Japan Standard Time)");
98
+
99
+ testSingleCase(chrono, "in 1 hour GMT", refInstant, (result, text) => {
100
+ expect(result.text).toBe("in 1 hour");
101
+ expect(result.start).toBeDate(expectedInstant);
102
+ });
103
+ }
104
+
105
+ {
106
+ const refInstant = new Date("Sun Nov 29 2020 13:24:13 GMT+0900 (Japan Standard Time)");
107
+ const expectedInstant = new Date("Sun Nov 29 2020 14:24:13 GMT+0900 (Japan Standard Time)");
108
+
109
+ testSingleCase(chrono, "in 1 hour GMT", { instant: refInstant, timezone: "JST" }, (result, text) => {
110
+ expect(result.text).toBe("in 1 hour");
111
+ expect(result.start).toBeDate(expectedInstant);
112
+ });
113
+ }
114
+
115
+ {
116
+ const refInstant = new Date("Sun Nov 29 2020 13:24:13 GMT+0900 (Japan Standard Time)");
117
+ const expectedInstant = new Date("Sun Nov 29 2020 14:24:13 GMT+0900 (Japan Standard Time)");
118
+
119
+ testSingleCase(chrono, "in 1 hour GMT", { instant: refInstant, timezone: "BST" }, (result, text) => {
120
+ expect(result.text).toBe("in 1 hour");
121
+ expect(result.start).toBeDate(expectedInstant);
122
+ });
123
+ }
124
+ });
85
125
 
86
- testSingleCase(chrono, "in 1 hour get eggs and milk", refDate, (result, text) => {
87
- expect(result.text).toBe("in 1 hour");
88
- expect(result.start.get("timezoneOffset")).toBe(-refDate.getTimezoneOffset());
126
+ test("Test - Relative time (Now) is not effected by timezone setting", function () {
127
+ const refInstant = new Date(1637674343000);
128
+
129
+ testSingleCase(chrono, "now", { instant: refInstant }, (result) => {
130
+ expect(result.text).toBe("now");
131
+ expect(result.start).toBeDate(refInstant);
132
+ });
133
+
134
+ testSingleCase(chrono, "now", { instant: refInstant, timezone: null }, (result) => {
135
+ expect(result.text).toBe("now");
136
+ expect(result.start).toBeDate(refInstant);
137
+ });
138
+
139
+ testSingleCase(chrono, "now", { instant: refInstant, timezone: "BST" }, (result) => {
140
+ expect(result.text).toBe("now");
141
+ expect(result.start).toBeDate(refInstant);
142
+ });
143
+
144
+ testSingleCase(chrono, "now", { instant: refInstant, timezone: "JST" }, (result) => {
145
+ expect(result.text).toBe("now");
146
+ expect(result.start).toBeDate(refInstant);
89
147
  });
148
+ });
90
149
 
91
- // This test fail when the system/assume timezone is exactly similar to the mentioned timezone
92
- // Temporary disable this test
150
+ test("Test - Relative time (2 hour later) is not effected by timezone setting", function () {
151
+ const refInstant = new Date(1637674343000);
152
+ const expectedInstant = new Date(1637674343000 + 2 * 60 * 60 * 1000);
93
153
 
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
- // });
154
+ testSingleCase(chrono, "2 hour later", { instant: refInstant }, (result) => {
155
+ expect(result.text).toBe("2 hour later");
156
+ expect(result.start).toBeDate(expectedInstant);
157
+ });
158
+
159
+ testSingleCase(chrono, "2 hour later", { instant: refInstant, timezone: null }, (result) => {
160
+ expect(result.text).toBe("2 hour later");
161
+ expect(result.start).toBeDate(expectedInstant);
162
+ });
163
+
164
+ testSingleCase(chrono, "2 hour later", { instant: refInstant, timezone: "BST" }, (result) => {
165
+ expect(result.text).toBe("2 hour later");
166
+ expect(result.start).toBeDate(expectedInstant);
167
+ });
168
+
169
+ testSingleCase(chrono, "2 hour later", { instant: refInstant, timezone: "JST" }, (result) => {
170
+ expect(result.text).toBe("2 hour later");
171
+ expect(result.start).toBeDate(expectedInstant);
172
+ });
98
173
  });
99
174
 
100
175
  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", function () {
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 () {
package/test/test_util.ts CHANGED
@@ -61,10 +61,13 @@ export function testWithExpectedDate(chrono: ChronoLike, text: string, expectedD
61
61
  });
62
62
  }
63
63
 
64
- export function testUnexpectedResult(chrono: ChronoLike, text: string, refDate?: Date) {
64
+ export function testUnexpectedResult(chrono: ChronoLike, text: string, refDate?: Date, options?: ParsingOption) {
65
65
  const debugHandler = new BufferedDebugHandler();
66
+ options = options || {};
67
+ options.debug = debugHandler;
68
+
66
69
  try {
67
- const results = chrono.parse(text, refDate, { debug: debugHandler });
70
+ const results = chrono.parse(text, refDate, options);
68
71
  expect(results).toHaveLength(0);
69
72
  } catch (e) {
70
73
  debugHandler.executeBufferedBlocks();