chrono-node 2.10.1 → 2.10.2

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 (89) hide show
  1. package/dist/cjs/calculation/duration.js +12 -7
  2. package/dist/cjs/calculation/duration.js.map +1 -1
  3. package/dist/cjs/common/refiners/AbstractMergeDateTimeRefiner.js +6 -3
  4. package/dist/cjs/common/refiners/AbstractMergeDateTimeRefiner.js.map +1 -1
  5. package/dist/cjs/common/refiners/MergeWeekdayComponentRefiner.js +2 -1
  6. package/dist/cjs/common/refiners/MergeWeekdayComponentRefiner.js.map +1 -1
  7. package/dist/cjs/locales/en/configuration.js +4 -0
  8. package/dist/cjs/locales/en/configuration.js.map +1 -1
  9. package/dist/cjs/locales/en/parsers/ENEndOfCurrentMonthParser.d.ts +7 -0
  10. package/dist/cjs/locales/en/parsers/ENEndOfCurrentMonthParser.js +23 -0
  11. package/dist/cjs/locales/en/parsers/ENEndOfCurrentMonthParser.js.map +1 -0
  12. package/dist/cjs/locales/en/parsers/ENSlashMonthFormatParser.d.ts +1 -1
  13. package/dist/cjs/locales/en/parsers/ENSlashMonthFormatParser.js +3 -0
  14. package/dist/cjs/locales/en/parsers/ENSlashMonthFormatParser.js.map +1 -1
  15. package/dist/cjs/locales/en/parsers/ENTimeUnitWithinFormatParser.js +1 -1
  16. package/dist/cjs/locales/en/parsers/ENTimeUnitWithinFormatParser.js.map +1 -1
  17. package/dist/cjs/locales/en/refiners/ENEndOfPeriodRefiner.d.ts +7 -0
  18. package/dist/cjs/locales/en/refiners/ENEndOfPeriodRefiner.js +81 -0
  19. package/dist/cjs/locales/en/refiners/ENEndOfPeriodRefiner.js.map +1 -0
  20. package/dist/cjs/locales/zh/hans/parsers/ZHHansAgoFormatParser.d.ts +1 -0
  21. package/dist/cjs/locales/zh/hans/parsers/ZHHansAgoFormatParser.js +3 -0
  22. package/dist/cjs/locales/zh/hans/parsers/ZHHansAgoFormatParser.js.map +1 -1
  23. package/dist/cjs/locales/zh/hans/parsers/ZHHansDateParser.d.ts +1 -0
  24. package/dist/cjs/locales/zh/hans/parsers/ZHHansDateParser.js +3 -0
  25. package/dist/cjs/locales/zh/hans/parsers/ZHHansDateParser.js.map +1 -1
  26. package/dist/cjs/locales/zh/hans/parsers/ZHHansDeadlineFormatParser.d.ts +1 -0
  27. package/dist/cjs/locales/zh/hans/parsers/ZHHansDeadlineFormatParser.js +3 -0
  28. package/dist/cjs/locales/zh/hans/parsers/ZHHansDeadlineFormatParser.js.map +1 -1
  29. package/dist/cjs/locales/zh/hant/parsers/ZHHantAgoFormatParser.d.ts +1 -0
  30. package/dist/cjs/locales/zh/hant/parsers/ZHHantAgoFormatParser.js +3 -0
  31. package/dist/cjs/locales/zh/hant/parsers/ZHHantAgoFormatParser.js.map +1 -1
  32. package/dist/cjs/locales/zh/hant/parsers/ZHHantDateParser.d.ts +1 -0
  33. package/dist/cjs/locales/zh/hant/parsers/ZHHantDateParser.js +3 -0
  34. package/dist/cjs/locales/zh/hant/parsers/ZHHantDateParser.js.map +1 -1
  35. package/dist/cjs/locales/zh/hant/parsers/ZHHantDeadlineFormatParser.d.ts +1 -0
  36. package/dist/cjs/locales/zh/hant/parsers/ZHHantDeadlineFormatParser.js +3 -0
  37. package/dist/cjs/locales/zh/hant/parsers/ZHHantDeadlineFormatParser.js.map +1 -1
  38. package/dist/esm/calculation/duration.js +5 -0
  39. package/dist/esm/calculation/duration.js.map +1 -1
  40. package/dist/esm/common/refiners/AbstractMergeDateTimeRefiner.js +6 -3
  41. package/dist/esm/common/refiners/AbstractMergeDateTimeRefiner.js.map +1 -1
  42. package/dist/esm/common/refiners/MergeWeekdayComponentRefiner.js +2 -1
  43. package/dist/esm/common/refiners/MergeWeekdayComponentRefiner.js.map +1 -1
  44. package/dist/esm/locales/en/configuration.js +4 -0
  45. package/dist/esm/locales/en/configuration.js.map +1 -1
  46. package/dist/esm/locales/en/parsers/ENEndOfCurrentMonthParser.d.ts +7 -0
  47. package/dist/esm/locales/en/parsers/ENEndOfCurrentMonthParser.js +20 -0
  48. package/dist/esm/locales/en/parsers/ENEndOfCurrentMonthParser.js.map +1 -0
  49. package/dist/esm/locales/en/parsers/ENSlashMonthFormatParser.d.ts +1 -1
  50. package/dist/esm/locales/en/parsers/ENSlashMonthFormatParser.js +3 -0
  51. package/dist/esm/locales/en/parsers/ENSlashMonthFormatParser.js.map +1 -1
  52. package/dist/esm/locales/en/parsers/ENTimeUnitWithinFormatParser.js +1 -1
  53. package/dist/esm/locales/en/parsers/ENTimeUnitWithinFormatParser.js.map +1 -1
  54. package/dist/esm/locales/en/refiners/ENEndOfPeriodRefiner.d.ts +7 -0
  55. package/dist/esm/locales/en/refiners/ENEndOfPeriodRefiner.js +78 -0
  56. package/dist/esm/locales/en/refiners/ENEndOfPeriodRefiner.js.map +1 -0
  57. package/dist/esm/locales/zh/hans/parsers/ZHHansAgoFormatParser.d.ts +1 -0
  58. package/dist/esm/locales/zh/hans/parsers/ZHHansAgoFormatParser.js +3 -0
  59. package/dist/esm/locales/zh/hans/parsers/ZHHansAgoFormatParser.js.map +1 -1
  60. package/dist/esm/locales/zh/hans/parsers/ZHHansDateParser.d.ts +1 -0
  61. package/dist/esm/locales/zh/hans/parsers/ZHHansDateParser.js +3 -0
  62. package/dist/esm/locales/zh/hans/parsers/ZHHansDateParser.js.map +1 -1
  63. package/dist/esm/locales/zh/hans/parsers/ZHHansDeadlineFormatParser.d.ts +1 -0
  64. package/dist/esm/locales/zh/hans/parsers/ZHHansDeadlineFormatParser.js +3 -0
  65. package/dist/esm/locales/zh/hans/parsers/ZHHansDeadlineFormatParser.js.map +1 -1
  66. package/dist/esm/locales/zh/hant/parsers/ZHHantAgoFormatParser.d.ts +1 -0
  67. package/dist/esm/locales/zh/hant/parsers/ZHHantAgoFormatParser.js +3 -0
  68. package/dist/esm/locales/zh/hant/parsers/ZHHantAgoFormatParser.js.map +1 -1
  69. package/dist/esm/locales/zh/hant/parsers/ZHHantDateParser.d.ts +1 -0
  70. package/dist/esm/locales/zh/hant/parsers/ZHHantDateParser.js +3 -0
  71. package/dist/esm/locales/zh/hant/parsers/ZHHantDateParser.js.map +1 -1
  72. package/dist/esm/locales/zh/hant/parsers/ZHHantDeadlineFormatParser.d.ts +1 -0
  73. package/dist/esm/locales/zh/hant/parsers/ZHHantDeadlineFormatParser.js +3 -0
  74. package/dist/esm/locales/zh/hant/parsers/ZHHantDeadlineFormatParser.js.map +1 -1
  75. package/package.json +1 -1
  76. package/src/calculation/duration.ts +5 -0
  77. package/src/common/refiners/AbstractMergeDateTimeRefiner.ts +13 -5
  78. package/src/common/refiners/MergeWeekdayComponentRefiner.ts +6 -1
  79. package/src/locales/en/configuration.ts +4 -0
  80. package/src/locales/en/parsers/ENEndOfCurrentMonthParser.ts +25 -0
  81. package/src/locales/en/parsers/ENSlashMonthFormatParser.ts +7 -1
  82. package/src/locales/en/parsers/ENTimeUnitWithinFormatParser.ts +1 -1
  83. package/src/locales/en/refiners/ENEndOfPeriodRefiner.ts +101 -0
  84. package/src/locales/zh/hans/parsers/ZHHansAgoFormatParser.ts +6 -0
  85. package/src/locales/zh/hans/parsers/ZHHansDateParser.ts +6 -0
  86. package/src/locales/zh/hans/parsers/ZHHansDeadlineFormatParser.ts +6 -0
  87. package/src/locales/zh/hant/parsers/ZHHantAgoFormatParser.ts +6 -0
  88. package/src/locales/zh/hant/parsers/ZHHantDateParser.ts +6 -0
  89. package/src/locales/zh/hant/parsers/ZHHantDeadlineFormatParser.ts +6 -0
@@ -0,0 +1,25 @@
1
+ import { ParsingContext } from "../../../chrono";
2
+ import { ParsingComponents } from "../../../results";
3
+ import { AbstractParserWithWordBoundaryChecking } from "../../../common/parsers/AbstractParserWithWordBoundary";
4
+
5
+ const PATTERN = /(?:last\s+day|end)\s+of\s+(?:the\s+)?month(?=\W|$)/i;
6
+
7
+ export default class ENEndOfCurrentMonthParser extends AbstractParserWithWordBoundaryChecking {
8
+ innerPattern(): RegExp {
9
+ return PATTERN;
10
+ }
11
+
12
+ innerExtract(context: ParsingContext): ParsingComponents {
13
+ const targetDate = context.reference.getDateWithAdjustedTimezone();
14
+ const year = targetDate.getFullYear();
15
+ const month = targetDate.getMonth() + 1;
16
+ const lastDay = new Date(year, month, 0).getDate();
17
+ const components = context.createParsingComponents();
18
+
19
+ components.assign("day", lastDay);
20
+ components.assign("month", month);
21
+ components.assign("year", year);
22
+ components.addTag("parser/ENEndOfCurrentMonthParser");
23
+ return components;
24
+ }
25
+ }
@@ -17,7 +17,13 @@ export default class ENSlashMonthFormatParser extends AbstractParserWithWordBoun
17
17
  return PATTERN;
18
18
  }
19
19
 
20
- innerExtract(context: ParsingContext, match: RegExpMatchArray): ParsingComponents {
20
+ innerExtract(context: ParsingContext, match: RegExpMatchArray): ParsingComponents | null {
21
+ // Do not extract a month/year suffix from an invalid numeric date (e.g. "50/6/2018").
22
+ // Parsing can also resume within a rejected match, so check the original text.
23
+ if (/\d\/?$/.test(context.text.substring(0, match.index))) {
24
+ return null;
25
+ }
26
+
21
27
  const year = parseInt(match[YEAR_GROUP]);
22
28
  const month = parseInt(match[MONTH_GROUP]);
23
29
 
@@ -35,7 +35,7 @@ export default class ENTimeUnitWithinFormatParser extends AbstractParserWithWord
35
35
 
36
36
  innerExtract(context: ParsingContext, match: RegExpMatchArray) {
37
37
  // Exclude "for the unit" phases, e.g. "for the year"
38
- if (match[0].match(/^for\s*the\s*\w+/)) {
38
+ if (match[0].match(/^for\s*the\s*\w+/i)) {
39
39
  return null;
40
40
  }
41
41
  const timeUnits = parseDuration(match[1]);
@@ -0,0 +1,101 @@
1
+ import { ParsingContext, Refiner } from "../../../chrono";
2
+ import { ParsingResult } from "../../../results";
3
+ import { findYearClosestToRef } from "../../../calculation/years";
4
+
5
+ const PREFIX_PATTERN = /\b(?:last\s+day|end)\s+of\s+(?:the\s+)?$/i;
6
+ const RELATIVE_PERIOD_PATTERN = /^(this|last|past|next)\s*(week|month|year)$/i;
7
+ const RELATIVE_YEAR_SUFFIX_PATTERN = /^\s+(this|last|past|next)\s+year(?=\W|$)/i;
8
+
9
+ function modifierOffset(modifier: string): number {
10
+ return modifier === "next" ? 1 : modifier === "last" || modifier === "past" ? -1 : 0;
11
+ }
12
+
13
+ /**
14
+ * Moves a result preceded by "end of" or "last day of" to the last day of its period.
15
+ * A relative period ("next week", "this year") comes from the relative parsers. Its end follows from the reference
16
+ * date and the modifier alone, so it is computed from those rather than from the day the relative parser picked.
17
+ * A named month ("July", "February 2024") has a certain month and no certain day.
18
+ */
19
+ export default class ENEndOfPeriodRefiner implements Refiner {
20
+ refine(context: ParsingContext, results: ParsingResult[]): ParsingResult[] {
21
+ results.forEach((result) => {
22
+ const prefix = context.text.substring(0, result.index).match(PREFIX_PATTERN);
23
+ if (!prefix) {
24
+ return;
25
+ }
26
+
27
+ const relativePeriod = result.text.match(RELATIVE_PERIOD_PATTERN);
28
+ if (relativePeriod) {
29
+ const modifier = relativePeriod[1].toLowerCase();
30
+ this.moveToEndOfRelativePeriod(context, result, modifier, relativePeriod[2].toLowerCase());
31
+ } else if (result.start.isCertain("month") && !result.start.isCertain("day")) {
32
+ this.moveToEndOfMonth(context, result);
33
+ } else {
34
+ return;
35
+ }
36
+
37
+ // The relative parsers imply the reference time and UTC offset, but the end of a period is a whole day
38
+ // like a named month, and the reference offset is wrong when a DST change lies in between
39
+ result.start.imply("hour", 12);
40
+ result.start.imply("minute", 0);
41
+ result.start.imply("second", 0);
42
+ result.start.imply("millisecond", 0);
43
+ if (!result.start.isCertain("timezoneOffset")) {
44
+ result.start.delete("timezoneOffset");
45
+ }
46
+ result.index -= prefix[0].length;
47
+ result.text = prefix[0] + result.text;
48
+ result.addTag("refiner/ENEndOfPeriodRefiner");
49
+ });
50
+
51
+ return results;
52
+ }
53
+
54
+ private moveToEndOfRelativePeriod(
55
+ context: ParsingContext,
56
+ result: ParsingResult,
57
+ modifier: string,
58
+ period: string
59
+ ) {
60
+ const offset = modifierOffset(modifier);
61
+ const referenceDate = context.reference.getDateWithAdjustedTimezone();
62
+ let lastDay: Date;
63
+
64
+ if (period === "week") {
65
+ lastDay = new Date(referenceDate.getTime());
66
+ lastDay.setDate(referenceDate.getDate() + (6 - referenceDate.getDay()) + offset * 7);
67
+ } else if (period === "month") {
68
+ lastDay = new Date(referenceDate.getFullYear(), referenceDate.getMonth() + offset + 1, 0);
69
+ } else {
70
+ lastDay = new Date(referenceDate.getFullYear() + offset, 11, 31);
71
+ }
72
+
73
+ result.start.assign("day", lastDay.getDate());
74
+ result.start.assign("month", lastDay.getMonth() + 1);
75
+ result.start.assign("year", lastDay.getFullYear());
76
+ result.start.delete("weekday");
77
+ result.start.imply("weekday", lastDay.getDay());
78
+ }
79
+
80
+ private moveToEndOfMonth(context: ParsingContext, result: ParsingResult) {
81
+ let year = result.start.get("year");
82
+ const month = result.start.get("month");
83
+ const suffix = context.text.substring(result.index + result.text.length).match(RELATIVE_YEAR_SUFFIX_PATTERN);
84
+
85
+ if (suffix) {
86
+ const modifier = suffix[1].toLowerCase();
87
+ const referenceYear = context.reference.getDateWithAdjustedTimezone().getFullYear();
88
+ year = referenceYear + modifierOffset(modifier);
89
+ result.start.assign("year", year);
90
+ result.text += suffix[0];
91
+ }
92
+
93
+ if (!result.start.isCertain("year")) {
94
+ const lastDayInReferenceYear = new Date(year, month, 0).getDate();
95
+ year = findYearClosestToRef(context.reference.getDateWithAdjustedTimezone(), lastDayInReferenceYear, month);
96
+ result.start.imply("year", year);
97
+ }
98
+
99
+ result.start.assign("day", new Date(year, month, 0).getDate());
100
+ }
101
+ }
@@ -17,6 +17,12 @@ const NUMBER_GROUP = 1;
17
17
  const UNIT_GROUP = 2;
18
18
 
19
19
  export default class ZHHansAgoFormatParser extends AbstractParserWithWordBoundaryChecking {
20
+ patternLeftBoundary(): string {
21
+ // Return a capturing group to ensure that the match index is correct in the base class
22
+ // while avoiding matching CJK characters as word boundaries.
23
+ return "()";
24
+ }
25
+
20
26
  innerPattern(): RegExp {
21
27
  return PATTERN;
22
28
  }
@@ -7,6 +7,12 @@ const MONTH_GROUP = 2;
7
7
  const DAY_GROUP = 3;
8
8
 
9
9
  export default class ZHHansDateParser extends AbstractParserWithWordBoundaryChecking {
10
+ patternLeftBoundary(): string {
11
+ // Return a capturing group to ensure that the match index is correct in the base class
12
+ // while avoiding matching CJK characters as word boundaries.
13
+ return "()";
14
+ }
15
+
10
16
  innerPattern() {
11
17
  // prettier-ignore
12
18
  return new RegExp(
@@ -17,6 +17,12 @@ const NUMBER_GROUP = 1;
17
17
  const UNIT_GROUP = 2;
18
18
 
19
19
  export default class ZHHansDeadlineFormatParser extends AbstractParserWithWordBoundaryChecking {
20
+ patternLeftBoundary(): string {
21
+ // Return a capturing group to ensure that the match index is correct in the base class
22
+ // while avoiding matching CJK characters as word boundaries.
23
+ return "()";
24
+ }
25
+
20
26
  innerPattern(): RegExp {
21
27
  return PATTERN;
22
28
  }
@@ -17,6 +17,12 @@ const NUMBER_GROUP = 1;
17
17
  const UNIT_GROUP = 2;
18
18
 
19
19
  export default class ZHHantAgoFormatParser extends AbstractParserWithWordBoundaryChecking {
20
+ patternLeftBoundary(): string {
21
+ // Return a capturing group to ensure that the match index is correct in the base class
22
+ // while avoiding matching CJK characters as word boundaries.
23
+ return "()";
24
+ }
25
+
20
26
  innerPattern(): RegExp {
21
27
  return PATTERN;
22
28
  }
@@ -7,6 +7,12 @@ const MONTH_GROUP = 2;
7
7
  const DAY_GROUP = 3;
8
8
 
9
9
  export default class ZHHantDateParser extends AbstractParserWithWordBoundaryChecking {
10
+ patternLeftBoundary(): string {
11
+ // Return a capturing group to ensure that the match index is correct in the base class
12
+ // while avoiding matching CJK characters as word boundaries.
13
+ return "()";
14
+ }
15
+
10
16
  innerPattern() {
11
17
  // prettier-ignore
12
18
  return new RegExp(
@@ -17,6 +17,12 @@ const NUMBER_GROUP = 1;
17
17
  const UNIT_GROUP = 2;
18
18
 
19
19
  export default class ZHHantDeadlineFormatParser extends AbstractParserWithWordBoundaryChecking {
20
+ patternLeftBoundary(): string {
21
+ // Return a capturing group to ensure that the match index is correct in the base class
22
+ // while avoiding matching CJK characters as word boundaries.
23
+ return "()";
24
+ }
25
+
20
26
  innerPattern(): RegExp {
21
27
  return PATTERN;
22
28
  }