chrono-node 2.6.6 → 2.7.1

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 (130) hide show
  1. package/dist/cjs/calculation/mergingCalculation.js +2 -0
  2. package/dist/cjs/calculation/mergingCalculation.js.map +1 -1
  3. package/dist/cjs/common/casualReferences.js +13 -3
  4. package/dist/cjs/common/casualReferences.js.map +1 -1
  5. package/dist/cjs/common/parsers/AbstractParserWithWordBoundary.d.ts +2 -1
  6. package/dist/cjs/common/parsers/AbstractParserWithWordBoundary.js +9 -5
  7. package/dist/cjs/common/parsers/AbstractParserWithWordBoundary.js.map +1 -1
  8. package/dist/cjs/locales/en/parsers/ENCasualDateParser.js +12 -6
  9. package/dist/cjs/locales/en/parsers/ENCasualDateParser.js.map +1 -1
  10. package/dist/cjs/locales/en/parsers/ENCasualTimeParser.d.ts +1 -1
  11. package/dist/cjs/locales/en/parsers/ENCasualTimeParser.js +15 -6
  12. package/dist/cjs/locales/en/parsers/ENCasualTimeParser.js.map +1 -1
  13. package/dist/cjs/locales/en/parsers/ENTimeExpressionParser.js +23 -22
  14. package/dist/cjs/locales/en/parsers/ENTimeExpressionParser.js.map +1 -1
  15. package/dist/cjs/locales/en/parsers/ENTimeUnitWithinFormatParser.js +3 -2
  16. package/dist/cjs/locales/en/parsers/ENTimeUnitWithinFormatParser.js.map +1 -1
  17. package/dist/cjs/locales/ru/parsers/AbstractParserWithWordBoundaryChecking.d.ts +11 -0
  18. package/dist/cjs/locales/ru/parsers/AbstractParserWithWordBoundaryChecking.js +24 -0
  19. package/dist/cjs/locales/ru/parsers/AbstractParserWithWordBoundaryChecking.js.map +1 -0
  20. package/dist/cjs/locales/ru/parsers/RUCasualDateParser.d.ts +3 -4
  21. package/dist/cjs/locales/ru/parsers/RUCasualDateParser.js +4 -9
  22. package/dist/cjs/locales/ru/parsers/RUCasualDateParser.js.map +1 -1
  23. package/dist/cjs/locales/ru/parsers/RUCasualTimeParser.d.ts +3 -4
  24. package/dist/cjs/locales/ru/parsers/RUCasualTimeParser.js +4 -10
  25. package/dist/cjs/locales/ru/parsers/RUCasualTimeParser.js.map +1 -1
  26. package/dist/cjs/locales/ru/parsers/RUMonthNameLittleEndianParser.d.ts +3 -4
  27. package/dist/cjs/locales/ru/parsers/RUMonthNameLittleEndianParser.js +14 -19
  28. package/dist/cjs/locales/ru/parsers/RUMonthNameLittleEndianParser.js.map +1 -1
  29. package/dist/cjs/locales/ru/parsers/RUMonthNameParser.d.ts +3 -4
  30. package/dist/cjs/locales/ru/parsers/RUMonthNameParser.js +10 -14
  31. package/dist/cjs/locales/ru/parsers/RUMonthNameParser.js.map +1 -1
  32. package/dist/cjs/locales/ru/parsers/RURelativeDateFormatParser.d.ts +3 -4
  33. package/dist/cjs/locales/ru/parsers/RURelativeDateFormatParser.js +4 -8
  34. package/dist/cjs/locales/ru/parsers/RURelativeDateFormatParser.js.map +1 -1
  35. package/dist/cjs/locales/ru/parsers/RUTimeUnitAgoFormatParser.d.ts +3 -4
  36. package/dist/cjs/locales/ru/parsers/RUTimeUnitAgoFormatParser.js +4 -8
  37. package/dist/cjs/locales/ru/parsers/RUTimeUnitAgoFormatParser.js.map +1 -1
  38. package/dist/cjs/locales/ru/parsers/RUTimeUnitCasualRelativeFormatParser.d.ts +3 -4
  39. package/dist/cjs/locales/ru/parsers/RUTimeUnitCasualRelativeFormatParser.js +4 -8
  40. package/dist/cjs/locales/ru/parsers/RUTimeUnitCasualRelativeFormatParser.js.map +1 -1
  41. package/dist/cjs/locales/ru/parsers/RUTimeUnitWithinFormatParser.d.ts +3 -0
  42. package/dist/cjs/locales/ru/parsers/RUTimeUnitWithinFormatParser.js +6 -3
  43. package/dist/cjs/locales/ru/parsers/RUTimeUnitWithinFormatParser.js.map +1 -1
  44. package/dist/cjs/locales/ru/parsers/RUWeekdayParser.d.ts +3 -4
  45. package/dist/cjs/locales/ru/parsers/RUWeekdayParser.js +9 -14
  46. package/dist/cjs/locales/ru/parsers/RUWeekdayParser.js.map +1 -1
  47. package/dist/cjs/results.d.ts +5 -0
  48. package/dist/cjs/results.js +30 -2
  49. package/dist/cjs/results.js.map +1 -1
  50. package/dist/cjs/types.d.ts +2 -0
  51. package/dist/cjs/types.js.map +1 -1
  52. package/dist/esm/calculation/mergingCalculation.js +2 -0
  53. package/dist/esm/calculation/mergingCalculation.js.map +1 -1
  54. package/dist/esm/common/casualReferences.js +13 -3
  55. package/dist/esm/common/casualReferences.js.map +1 -1
  56. package/dist/esm/common/parsers/AbstractParserWithWordBoundary.d.ts +2 -1
  57. package/dist/esm/common/parsers/AbstractParserWithWordBoundary.js +9 -5
  58. package/dist/esm/common/parsers/AbstractParserWithWordBoundary.js.map +1 -1
  59. package/dist/esm/locales/en/parsers/ENCasualDateParser.js +12 -6
  60. package/dist/esm/locales/en/parsers/ENCasualDateParser.js.map +1 -1
  61. package/dist/esm/locales/en/parsers/ENCasualTimeParser.d.ts +1 -1
  62. package/dist/esm/locales/en/parsers/ENCasualTimeParser.js +15 -6
  63. package/dist/esm/locales/en/parsers/ENCasualTimeParser.js.map +1 -1
  64. package/dist/esm/locales/en/parsers/ENTimeExpressionParser.js +23 -22
  65. package/dist/esm/locales/en/parsers/ENTimeExpressionParser.js.map +1 -1
  66. package/dist/esm/locales/en/parsers/ENTimeUnitWithinFormatParser.js +3 -2
  67. package/dist/esm/locales/en/parsers/ENTimeUnitWithinFormatParser.js.map +1 -1
  68. package/dist/esm/locales/ru/parsers/AbstractParserWithWordBoundaryChecking.d.ts +11 -0
  69. package/dist/esm/locales/ru/parsers/AbstractParserWithWordBoundaryChecking.js +19 -0
  70. package/dist/esm/locales/ru/parsers/AbstractParserWithWordBoundaryChecking.js.map +1 -0
  71. package/dist/esm/locales/ru/parsers/RUCasualDateParser.d.ts +3 -4
  72. package/dist/esm/locales/ru/parsers/RUCasualDateParser.js +4 -9
  73. package/dist/esm/locales/ru/parsers/RUCasualDateParser.js.map +1 -1
  74. package/dist/esm/locales/ru/parsers/RUCasualTimeParser.d.ts +3 -4
  75. package/dist/esm/locales/ru/parsers/RUCasualTimeParser.js +4 -10
  76. package/dist/esm/locales/ru/parsers/RUCasualTimeParser.js.map +1 -1
  77. package/dist/esm/locales/ru/parsers/RUMonthNameLittleEndianParser.d.ts +3 -4
  78. package/dist/esm/locales/ru/parsers/RUMonthNameLittleEndianParser.js +15 -20
  79. package/dist/esm/locales/ru/parsers/RUMonthNameLittleEndianParser.js.map +1 -1
  80. package/dist/esm/locales/ru/parsers/RUMonthNameParser.d.ts +3 -4
  81. package/dist/esm/locales/ru/parsers/RUMonthNameParser.js +11 -15
  82. package/dist/esm/locales/ru/parsers/RUMonthNameParser.js.map +1 -1
  83. package/dist/esm/locales/ru/parsers/RURelativeDateFormatParser.d.ts +3 -4
  84. package/dist/esm/locales/ru/parsers/RURelativeDateFormatParser.js +5 -9
  85. package/dist/esm/locales/ru/parsers/RURelativeDateFormatParser.js.map +1 -1
  86. package/dist/esm/locales/ru/parsers/RUTimeUnitAgoFormatParser.d.ts +3 -4
  87. package/dist/esm/locales/ru/parsers/RUTimeUnitAgoFormatParser.js +5 -9
  88. package/dist/esm/locales/ru/parsers/RUTimeUnitAgoFormatParser.js.map +1 -1
  89. package/dist/esm/locales/ru/parsers/RUTimeUnitCasualRelativeFormatParser.d.ts +3 -4
  90. package/dist/esm/locales/ru/parsers/RUTimeUnitCasualRelativeFormatParser.js +5 -9
  91. package/dist/esm/locales/ru/parsers/RUTimeUnitCasualRelativeFormatParser.js.map +1 -1
  92. package/dist/esm/locales/ru/parsers/RUTimeUnitWithinFormatParser.d.ts +3 -0
  93. package/dist/esm/locales/ru/parsers/RUTimeUnitWithinFormatParser.js +6 -3
  94. package/dist/esm/locales/ru/parsers/RUTimeUnitWithinFormatParser.js.map +1 -1
  95. package/dist/esm/locales/ru/parsers/RUWeekdayParser.d.ts +3 -4
  96. package/dist/esm/locales/ru/parsers/RUWeekdayParser.js +10 -15
  97. package/dist/esm/locales/ru/parsers/RUWeekdayParser.js.map +1 -1
  98. package/dist/esm/results.d.ts +5 -0
  99. package/dist/esm/results.js +30 -2
  100. package/dist/esm/results.js.map +1 -1
  101. package/dist/esm/types.d.ts +2 -0
  102. package/dist/esm/types.js.map +1 -1
  103. package/package.json +1 -1
  104. package/src/calculation/mergingCalculation.ts +2 -0
  105. package/src/common/casualReferences.ts +13 -3
  106. package/src/common/parsers/AbstractParserWithWordBoundary.ts +17 -9
  107. package/src/locales/en/parsers/ENCasualDateParser.ts +12 -7
  108. package/src/locales/en/parsers/ENCasualTimeParser.ts +15 -6
  109. package/src/locales/en/parsers/ENTimeExpressionParser.ts +24 -22
  110. package/src/locales/en/parsers/ENTimeUnitWithinFormatParser.ts +4 -3
  111. package/src/locales/ru/parsers/AbstractParserWithWordBoundaryChecking.ts +25 -0
  112. package/src/locales/ru/parsers/RUCasualDateParser.ts +4 -14
  113. package/src/locales/ru/parsers/RUCasualTimeParser.ts +4 -14
  114. package/src/locales/ru/parsers/RUMonthNameLittleEndianParser.ts +16 -26
  115. package/src/locales/ru/parsers/RUMonthNameParser.ts +13 -20
  116. package/src/locales/ru/parsers/RURelativeDateFormatParser.ts +6 -14
  117. package/src/locales/ru/parsers/RUTimeUnitAgoFormatParser.ts +5 -11
  118. package/src/locales/ru/parsers/RUTimeUnitCasualRelativeFormatParser.ts +4 -13
  119. package/src/locales/ru/parsers/RUTimeUnitWithinFormatParser.ts +10 -4
  120. package/src/locales/ru/parsers/RUWeekdayParser.ts +12 -20
  121. package/src/results.ts +34 -4
  122. package/src/types.ts +11 -1
  123. package/test/en/en.test.ts +3 -3
  124. package/test/en/en_time_units_within.test.ts +22 -1
  125. package/test/result.test.ts +65 -3
  126. package/test/ru/ru_relative.test.ts +44 -11
  127. package/test/ru/ru_time_units_casual_relative.test.ts +96 -30
  128. package/test/system.test.ts +37 -0
  129. package/test/uk/uk_relative.test.ts +44 -11
  130. package/test/uk/uk_time_units_casual_relative.test.ts +40 -10
@@ -0,0 +1,25 @@
1
+ import { AbstractParserWithWordBoundaryChecking } from "../../../common/parsers/AbstractParserWithWordBoundary";
2
+ import { REGEX_PARTS } from "../constants";
3
+ import { ParsingContext } from "../../../chrono";
4
+
5
+ export abstract class AbstractParserWithLeftBoundaryChecking extends AbstractParserWithWordBoundaryChecking {
6
+ abstract innerPatternString(context: ParsingContext): string;
7
+
8
+ patternLeftBoundary(): string {
9
+ return REGEX_PARTS.leftBoundary;
10
+ }
11
+
12
+ innerPattern(context: ParsingContext): RegExp {
13
+ return new RegExp(this.innerPatternString(context), REGEX_PARTS.flags);
14
+ }
15
+
16
+ innerPatternHasChange(context: ParsingContext, currentInnerPattern: RegExp): boolean {
17
+ return false;
18
+ }
19
+ }
20
+
21
+ export abstract class AbstractParserWithLeftRightBoundaryChecking extends AbstractParserWithLeftBoundaryChecking {
22
+ innerPattern(context: ParsingContext): RegExp {
23
+ return new RegExp(`${this.innerPatternString(context)}${REGEX_PARTS.rightBoundary}`, REGEX_PARTS.flags);
24
+ }
25
+ }
@@ -1,21 +1,11 @@
1
1
  import { ParsingContext } from "../../../chrono";
2
2
  import { ParsingComponents, ParsingResult } from "../../../results";
3
- import { AbstractParserWithWordBoundaryChecking } from "../../../common/parsers/AbstractParserWithWordBoundary";
4
3
  import * as references from "../../../common/casualReferences";
5
- import { REGEX_PARTS } from "../constants";
4
+ import { AbstractParserWithLeftRightBoundaryChecking } from "./AbstractParserWithWordBoundaryChecking";
6
5
 
7
- const PATTERN = new RegExp(
8
- `(?:с|со)?\\s*(сегодня|вчера|завтра|послезавтра|послепослезавтра|позапозавчера|позавчера)${REGEX_PARTS.rightBoundary}`,
9
- REGEX_PARTS.flags
10
- );
11
-
12
- export default class RUCasualDateParser extends AbstractParserWithWordBoundaryChecking {
13
- patternLeftBoundary(): string {
14
- return REGEX_PARTS.leftBoundary;
15
- }
16
-
17
- innerPattern(context: ParsingContext): RegExp {
18
- return PATTERN;
6
+ export default class RUCasualDateParser extends AbstractParserWithLeftRightBoundaryChecking {
7
+ innerPatternString(context: ParsingContext): string {
8
+ return `(?:с|со)?\\s*(сегодня|вчера|завтра|послезавтра|послепослезавтра|позапозавчера|позавчера)`;
19
9
  }
20
10
 
21
11
  innerExtract(context: ParsingContext, match: RegExpMatchArray): ParsingComponents | ParsingResult {
@@ -1,22 +1,12 @@
1
1
  import { ParsingContext } from "../../../chrono";
2
- import { AbstractParserWithWordBoundaryChecking } from "../../../common/parsers/AbstractParserWithWordBoundary";
3
2
  import * as references from "../../../common/casualReferences";
4
3
  import { assignSimilarDate } from "../../../utils/dayjs";
5
4
  import dayjs from "dayjs";
6
- import { REGEX_PARTS } from "../constants";
5
+ import { AbstractParserWithLeftRightBoundaryChecking } from "./AbstractParserWithWordBoundaryChecking";
7
6
 
8
- const PATTERN = new RegExp(
9
- `(сейчас|прошлым\\s*вечером|прошлой\\s*ночью|следующей\\s*ночью|сегодня\\s*ночью|этой\\s*ночью|ночью|этим утром|утром|утра|в\\s*полдень|вечером|вечера|в\\s*полночь)` +
10
- `${REGEX_PARTS.rightBoundary}`,
11
- REGEX_PARTS.flags
12
- );
13
- export default class RUCasualTimeParser extends AbstractParserWithWordBoundaryChecking {
14
- patternLeftBoundary(): string {
15
- return REGEX_PARTS.leftBoundary;
16
- }
17
-
18
- innerPattern() {
19
- return PATTERN;
7
+ export default class RUCasualTimeParser extends AbstractParserWithLeftRightBoundaryChecking {
8
+ innerPatternString(context: ParsingContext): string {
9
+ return `(сейчас|прошлым\\s*вечером|прошлой\\s*ночью|следующей\\s*ночью|сегодня\\s*ночью|этой\\s*ночью|ночью|этим утром|утром|утра|в\\s*полдень|вечером|вечера|в\\s*полночь)`;
20
10
  }
21
11
 
22
12
  innerExtract(context: ParsingContext, match: RegExpMatchArray) {
@@ -1,41 +1,31 @@
1
1
  import { ParsingContext } from "../../../chrono";
2
2
  import { ParsingResult } from "../../../results";
3
3
  import { findYearClosestToRef } from "../../../calculation/years";
4
- import { MONTH_DICTIONARY, REGEX_PARTS } from "../constants";
4
+ import { MONTH_DICTIONARY } from "../constants";
5
5
  import { YEAR_PATTERN, parseYear } from "../constants";
6
6
  import { ORDINAL_NUMBER_PATTERN, parseOrdinalNumberPattern } from "../constants";
7
7
  import { matchAnyPattern } from "../../../utils/pattern";
8
- import { AbstractParserWithWordBoundaryChecking } from "../../../common/parsers/AbstractParserWithWordBoundary";
9
-
10
- // prettier-ignore
11
- const PATTERN = new RegExp(
12
- `(?:с)?\\s*(${ORDINAL_NUMBER_PATTERN})` +
13
- `(?:` +
14
- `\\s{0,3}(?:по|-|–|до)?\\s{0,3}` +
15
- `(${ORDINAL_NUMBER_PATTERN})` +
16
- `)?` +
17
- `(?:-|\\/|\\s{0,3}(?:of)?\\s{0,3})` +
18
- `(${matchAnyPattern(MONTH_DICTIONARY)})` +
19
- `(?:` +
20
- `(?:-|\\/|,?\\s{0,3})` +
21
- `(${YEAR_PATTERN}(?![^\\s]\\d))` +
22
- `)?` +
23
- `${REGEX_PARTS.rightBoundary}`,
24
- REGEX_PARTS.flags
25
- );
8
+ import { AbstractParserWithLeftRightBoundaryChecking } from "./AbstractParserWithWordBoundaryChecking";
26
9
 
27
10
  const DATE_GROUP = 1;
28
11
  const DATE_TO_GROUP = 2;
29
12
  const MONTH_NAME_GROUP = 3;
30
13
  const YEAR_GROUP = 4;
31
14
 
32
- export default class RUMonthNameLittleEndianParser extends AbstractParserWithWordBoundaryChecking {
33
- patternLeftBoundary(): string {
34
- return REGEX_PARTS.leftBoundary;
35
- }
36
-
37
- innerPattern(): RegExp {
38
- return PATTERN;
15
+ export default class RUMonthNameLittleEndianParser extends AbstractParserWithLeftRightBoundaryChecking {
16
+ innerPatternString(context: ParsingContext): string {
17
+ // prettier-ignore
18
+ return `(?:с)?\\s*(${ORDINAL_NUMBER_PATTERN})` +
19
+ `(?:` +
20
+ `\\s{0,3}(?:по|-|–|до)?\\s{0,3}` +
21
+ `(${ORDINAL_NUMBER_PATTERN})` +
22
+ `)?` +
23
+ `(?:-|\\/|\\s{0,3}(?:of)?\\s{0,3})` +
24
+ `(${matchAnyPattern(MONTH_DICTIONARY)})` +
25
+ `(?:` +
26
+ `(?:-|\\/|,?\\s{0,3})` +
27
+ `(${YEAR_PATTERN}(?![^\\s]\\d))` +
28
+ `)?`;
39
29
  }
40
30
 
41
31
  innerExtract(context: ParsingContext, match: RegExpMatchArray): ParsingResult {
@@ -1,20 +1,9 @@
1
- import { FULL_MONTH_NAME_DICTIONARY, MONTH_DICTIONARY, REGEX_PARTS } from "../constants";
1
+ import { FULL_MONTH_NAME_DICTIONARY, MONTH_DICTIONARY } from "../constants";
2
2
  import { ParsingContext } from "../../../chrono";
3
3
  import { findYearClosestToRef } from "../../../calculation/years";
4
4
  import { matchAnyPattern } from "../../../utils/pattern";
5
5
  import { YEAR_PATTERN, parseYear } from "../constants";
6
- import { AbstractParserWithWordBoundaryChecking } from "../../../common/parsers/AbstractParserWithWordBoundary";
7
-
8
- const PATTERN = new RegExp(
9
- `((?:в)\\s*)?` +
10
- `(${matchAnyPattern(MONTH_DICTIONARY)})` +
11
- `\\s*` +
12
- `(?:` +
13
- `[,-]?\\s*(${YEAR_PATTERN})?` +
14
- `)?` +
15
- `(?=[^\\s\\w]|\\s+[^0-9]|\\s+$|$)`,
16
- REGEX_PARTS.flags
17
- );
6
+ import { AbstractParserWithLeftBoundaryChecking } from "./AbstractParserWithWordBoundaryChecking";
18
7
 
19
8
  const MONTH_NAME_GROUP = 2;
20
9
  const YEAR_GROUP = 3;
@@ -25,13 +14,17 @@ const YEAR_GROUP = 3;
25
14
  * - Январь 2012
26
15
  * - Январь
27
16
  */
28
- export default class RUMonthNameParser extends AbstractParserWithWordBoundaryChecking {
29
- patternLeftBoundary(): string {
30
- return REGEX_PARTS.leftBoundary;
31
- }
32
-
33
- innerPattern(): RegExp {
34
- return PATTERN;
17
+ export default class RUMonthNameParser extends AbstractParserWithLeftBoundaryChecking {
18
+ innerPatternString(context: ParsingContext): string {
19
+ return (
20
+ `((?:в)\\s*)?` +
21
+ `(${matchAnyPattern(MONTH_DICTIONARY)})` +
22
+ `\\s*` +
23
+ `(?:` +
24
+ `[,-]?\\s*(${YEAR_PATTERN})?` +
25
+ `)?` +
26
+ `(?=[^\\s\\w]|\\s+[^0-9]|\\s+$|$)`
27
+ );
35
28
  }
36
29
 
37
30
  innerExtract(context: ParsingContext, match: RegExpMatchArray) {
@@ -4,24 +4,16 @@ import { ParsingComponents } from "../../../results";
4
4
  import dayjs from "dayjs";
5
5
  import { AbstractParserWithWordBoundaryChecking } from "../../../common/parsers/AbstractParserWithWordBoundary";
6
6
  import { matchAnyPattern } from "../../../utils/pattern";
7
-
8
- const PATTERN = new RegExp(
9
- `(в прошлом|на прошлой|на следующей|в следующем|на этой|в этом)\\s*(${matchAnyPattern(
10
- TIME_UNIT_DICTIONARY
11
- )})(?=\\s*)${REGEX_PARTS.rightBoundary}`,
12
- REGEX_PARTS.flags
13
- );
7
+ import { AbstractParserWithLeftRightBoundaryChecking } from "./AbstractParserWithWordBoundaryChecking";
14
8
 
15
9
  const MODIFIER_WORD_GROUP = 1;
16
10
  const RELATIVE_WORD_GROUP = 2;
17
11
 
18
- export default class RURelativeDateFormatParser extends AbstractParserWithWordBoundaryChecking {
19
- patternLeftBoundary(): string {
20
- return REGEX_PARTS.leftBoundary;
21
- }
22
-
23
- innerPattern(): RegExp {
24
- return PATTERN;
12
+ export default class RURelativeDateFormatParser extends AbstractParserWithLeftRightBoundaryChecking {
13
+ innerPatternString(context: ParsingContext): string {
14
+ return `(в прошлом|на прошлой|на следующей|в следующем|на этой|в этом)\\s*(${matchAnyPattern(
15
+ TIME_UNIT_DICTIONARY
16
+ )})`;
25
17
  }
26
18
 
27
19
  innerExtract(context: ParsingContext, match: RegExpMatchArray): ParsingComponents {
@@ -1,18 +1,12 @@
1
1
  import { ParsingContext } from "../../../chrono";
2
- import { parseTimeUnits, REGEX_PARTS, TIME_UNITS_PATTERN } from "../constants";
2
+ import { parseTimeUnits, TIME_UNITS_PATTERN } from "../constants";
3
3
  import { ParsingComponents } from "../../../results";
4
- import { AbstractParserWithWordBoundaryChecking } from "../../../common/parsers/AbstractParserWithWordBoundary";
5
4
  import { reverseTimeUnits } from "../../../utils/timeunits";
5
+ import { AbstractParserWithLeftBoundaryChecking } from "./AbstractParserWithWordBoundaryChecking";
6
6
 
7
- const PATTERN = new RegExp(`(${TIME_UNITS_PATTERN})\\s{0,5}назад(?=(?:\\W|$))`, REGEX_PARTS.flags);
8
-
9
- export default class RUTimeUnitAgoFormatParser extends AbstractParserWithWordBoundaryChecking {
10
- patternLeftBoundary(): string {
11
- return REGEX_PARTS.leftBoundary;
12
- }
13
-
14
- innerPattern(): RegExp {
15
- return PATTERN;
7
+ export default class RUTimeUnitAgoFormatParser extends AbstractParserWithLeftBoundaryChecking {
8
+ innerPatternString(context: ParsingContext): string {
9
+ return `(${TIME_UNITS_PATTERN})\\s{0,5}назад(?=(?:\\W|$))`;
16
10
  }
17
11
 
18
12
  innerExtract(context: ParsingContext, match: RegExpMatchArray) {
@@ -1,21 +1,12 @@
1
1
  import { TIME_UNITS_PATTERN, parseTimeUnits, REGEX_PARTS } from "../constants";
2
2
  import { ParsingContext } from "../../../chrono";
3
3
  import { ParsingComponents } from "../../../results";
4
- import { AbstractParserWithWordBoundaryChecking } from "../../../common/parsers/AbstractParserWithWordBoundary";
5
4
  import { reverseTimeUnits } from "../../../utils/timeunits";
5
+ import { AbstractParserWithLeftRightBoundaryChecking } from "./AbstractParserWithWordBoundaryChecking";
6
6
 
7
- const PATTERN = new RegExp(
8
- `(эти|последние|прошлые|следующие|после|спустя|через|\\+|-)\\s*(${TIME_UNITS_PATTERN})${REGEX_PARTS.rightBoundary}`,
9
- REGEX_PARTS.flags
10
- );
11
-
12
- export default class RUTimeUnitCasualRelativeFormatParser extends AbstractParserWithWordBoundaryChecking {
13
- patternLeftBoundary(): string {
14
- return REGEX_PARTS.leftBoundary;
15
- }
16
-
17
- innerPattern(): RegExp {
18
- return PATTERN;
7
+ export default class RUTimeUnitCasualRelativeFormatParser extends AbstractParserWithLeftRightBoundaryChecking {
8
+ innerPatternString(context: ParsingContext): string {
9
+ return `(эти|последние|прошлые|следующие|после|спустя|через|\\+|-)\\s*(${TIME_UNITS_PATTERN})`;
19
10
  }
20
11
 
21
12
  innerExtract(context: ParsingContext, match: RegExpMatchArray): ParsingComponents {
@@ -4,17 +4,23 @@ import { ParsingComponents } from "../../../results";
4
4
  import { AbstractParserWithWordBoundaryChecking } from "../../../common/parsers/AbstractParserWithWordBoundary";
5
5
 
6
6
  const PATTERN = `(?:(?:около|примерно)\\s*(?:~\\s*)?)?(${TIME_UNITS_PATTERN})${REGEX_PARTS.rightBoundary}`;
7
- const PATTERN_WITH_PREFIX = new RegExp(`(?:в течение|в течении)\\s*${PATTERN}`, REGEX_PARTS.flags);
8
-
9
- const PATTERN_WITHOUT_PREFIX = new RegExp(PATTERN, "i");
10
7
 
11
8
  export default class RUTimeUnitWithinFormatParser extends AbstractParserWithWordBoundaryChecking {
9
+ private readonly patternWithPrefix: RegExp;
10
+ private readonly patternWithoutPrefix: RegExp;
11
+
12
+ constructor() {
13
+ super();
14
+ this.patternWithPrefix = new RegExp(`(?:в течение|в течении)\\s*${PATTERN}`, REGEX_PARTS.flags);
15
+ this.patternWithoutPrefix = new RegExp(PATTERN, REGEX_PARTS.flags);
16
+ }
17
+
12
18
  patternLeftBoundary(): string {
13
19
  return REGEX_PARTS.leftBoundary;
14
20
  }
15
21
 
16
22
  innerPattern(context: ParsingContext): RegExp {
17
- return context.option.forwardDate ? PATTERN_WITHOUT_PREFIX : PATTERN_WITH_PREFIX;
23
+ return context.option.forwardDate ? this.patternWithoutPrefix : this.patternWithPrefix;
18
24
  }
19
25
 
20
26
  innerExtract(context: ParsingContext, match: RegExpMatchArray): ParsingComponents {
@@ -1,32 +1,24 @@
1
1
  import { ParsingContext } from "../../../chrono";
2
2
  import { ParsingComponents } from "../../../results";
3
- import { REGEX_PARTS, WEEKDAY_DICTIONARY } from "../constants";
3
+ import { WEEKDAY_DICTIONARY } from "../constants";
4
4
  import { matchAnyPattern } from "../../../utils/pattern";
5
- import { AbstractParserWithWordBoundaryChecking } from "../../../common/parsers/AbstractParserWithWordBoundary";
6
5
  import { createParsingComponentsAtWeekday } from "../../../common/calculation/weekdays";
7
-
8
- const PATTERN = new RegExp(
9
- `(?:(?:,|\\(|()\\s*)?` +
10
- `(?:в\\s*?)?` +
11
- `(?:(эту|этот|прошлый|прошлую|следующий|следующую|следующего)\\s*)?` +
12
- `(${matchAnyPattern(WEEKDAY_DICTIONARY)})` +
13
- `(?:\\s*(?:,|\\)|)))?` +
14
- `(?:\\s*на\\s*(этой|прошлой|следующей)\\s*неделе)?` +
15
- `${REGEX_PARTS.rightBoundary}`,
16
- REGEX_PARTS.flags
17
- );
6
+ import { AbstractParserWithLeftRightBoundaryChecking } from "./AbstractParserWithWordBoundaryChecking";
18
7
 
19
8
  const PREFIX_GROUP = 1;
20
9
  const WEEKDAY_GROUP = 2;
21
10
  const POSTFIX_GROUP = 3;
22
11
 
23
- export default class RUWeekdayParser extends AbstractParserWithWordBoundaryChecking {
24
- innerPattern(): RegExp {
25
- return PATTERN;
26
- }
27
-
28
- patternLeftBoundary(): string {
29
- return REGEX_PARTS.leftBoundary;
12
+ export default class RUWeekdayParser extends AbstractParserWithLeftRightBoundaryChecking {
13
+ innerPatternString(context: ParsingContext): string {
14
+ return (
15
+ `(?:(?:,|\\(|()\\s*)?` +
16
+ `(?:в\\s*?)?` +
17
+ `(?:(эту|этот|прошлый|прошлую|следующий|следующую|следующего)\\s*)?` +
18
+ `(${matchAnyPattern(WEEKDAY_DICTIONARY)})` +
19
+ `(?:\\s*(?:,|\\)|)))?` +
20
+ `(?:\\s*на\\s*(этой|прошлой|следующей)\\s*неделе)?`
21
+ );
30
22
  }
31
23
 
32
24
  innerExtract(context: ParsingContext, match: RegExpMatchArray): ParsingComponents {
package/src/results.ts CHANGED
@@ -50,6 +50,7 @@ export class ParsingComponents implements ParsedComponents {
50
50
  private knownValues: { [c in Component]?: number };
51
51
  private impliedValues: { [c in Component]?: number };
52
52
  private reference: ReferenceWithTimezone;
53
+ private _tags = new Set<string>();
53
54
 
54
55
  constructor(reference: ReferenceWithTimezone, knownComponents?: { [c in Component]?: number }) {
55
56
  this.reference = reference;
@@ -155,9 +156,11 @@ export class ParsingComponents implements ParsedComponents {
155
156
  }
156
157
 
157
158
  toString() {
158
- return `[ParsingComponents {knownValues: ${JSON.stringify(this.knownValues)}, impliedValues: ${JSON.stringify(
159
- this.impliedValues
160
- )}}, reference: ${JSON.stringify(this.reference)}]`;
159
+ return `[ParsingComponents {
160
+ tags: ${JSON.stringify(Array.from(this._tags).sort())},
161
+ knownValues: ${JSON.stringify(this.knownValues)},
162
+ impliedValues: ${JSON.stringify(this.impliedValues)}},
163
+ reference: ${JSON.stringify(this.reference)}]`;
161
164
  }
162
165
 
163
166
  dayjs() {
@@ -170,6 +173,22 @@ export class ParsingComponents implements ParsedComponents {
170
173
  return new Date(date.getTime() + timezoneAdjustment * 60000);
171
174
  }
172
175
 
176
+ addTag(tag: string): ParsingComponents {
177
+ this._tags.add(tag);
178
+ return this;
179
+ }
180
+
181
+ addTags(tags: string[] | Set<string>): ParsingComponents {
182
+ for (const tag of tags) {
183
+ this._tags.add(tag);
184
+ }
185
+ return this;
186
+ }
187
+
188
+ tags(): Set<string> {
189
+ return new Set(this._tags);
190
+ }
191
+
173
192
  private dateWithoutTimezoneAdjustment() {
174
193
  const date = new Date(
175
194
  this.get("year"),
@@ -271,7 +290,18 @@ export class ParsingResult implements ParsedResult {
271
290
  return this.start.date();
272
291
  }
273
292
 
293
+ tags(): Set<string> {
294
+ const combinedTags: Set<string> = new Set(this.start.tags());
295
+ if (this.end) {
296
+ for (const tag of this.end.tags()) {
297
+ combinedTags.add(tag);
298
+ }
299
+ }
300
+ return combinedTags;
301
+ }
302
+
274
303
  toString() {
275
- return `[ParsingResult {index: ${this.index}, text: '${this.text}', ...}]`;
304
+ const tags = Array.from(this.tags()).sort();
305
+ return `[ParsingResult {index: ${this.index}, text: '${this.text}', tags: ${JSON.stringify(tags)} ...}]`;
276
306
  }
277
307
  }
package/src/types.ts CHANGED
@@ -77,9 +77,14 @@ export interface ParsedResult {
77
77
  readonly end?: ParsedComponents;
78
78
 
79
79
  /**
80
- * Create a javascript date object (from the result.start).
80
+ * @return a javascript date object created from the `result.start`.
81
81
  */
82
82
  date(): Date;
83
+
84
+ /**
85
+ * @return debugging tags combined of the `result.start` and `result.end`.
86
+ */
87
+ tags(): Set<string>;
83
88
  }
84
89
 
85
90
  /**
@@ -105,6 +110,11 @@ export interface ParsedComponents {
105
110
  * @return a javascript date object.
106
111
  */
107
112
  date(): Date;
113
+
114
+ /**
115
+ * @return debugging tags of the parsed component.
116
+ */
117
+ tags(): Set<string>;
108
118
  }
109
119
 
110
120
  export type Component =
@@ -107,10 +107,10 @@ test("Test - Random text", function () {
107
107
  expect(result.end.get("month")).toBe(7);
108
108
  });
109
109
 
110
- testSingleCase(chrono, "03-27-2022, 02:00 AM", new Date(2017, 7 - 1, 7), (result) => {
111
- expect(result.text).toBe("03-27-2022, 02:00 AM");
110
+ testSingleCase(chrono, "07-27-2022, 02:00 AM", new Date(2017, 7 - 1, 7), (result) => {
111
+ expect(result.text).toBe("07-27-2022, 02:00 AM");
112
112
  expect(result.start.get("day")).toBe(27);
113
- expect(result.start.get("month")).toBe(3);
113
+ expect(result.start.get("month")).toBe(7);
114
114
  expect(result.start.get("year")).toBe(2022);
115
115
  expect(result.start.get("hour")).toBe(2);
116
116
  expect(result.start.get("meridiem")).toBe(Meridiem.AM);
@@ -336,7 +336,7 @@ test("Test - Time units' certainty", () => {
336
336
  });
337
337
  });
338
338
 
339
- test("Test - Strict mode", function () {
339
+ test("Test - Strict mode", () => {
340
340
  testSingleCase(chrono, "in 2hour", new Date(2016, 10 - 1, 1, 14, 52), (result, text) => {
341
341
  expect(result.start.get("hour")).toBe(16);
342
342
  expect(result.start.get("minute")).toBe(52);
@@ -345,3 +345,24 @@ test("Test - Strict mode", function () {
345
345
  testUnexpectedResult(chrono.strict, "in 15m");
346
346
  testUnexpectedResult(chrono.strict, "within 5hr");
347
347
  });
348
+
349
+ test("Test - Forward date option", () => {
350
+ testSingleCase(chrono, "1 hour", new Date(2012, 7, 10, 12, 14), { forwardDate: true }, (result) => {
351
+ expect(result.text).toBe("1 hour");
352
+ expect(result.start).toBeDate(new Date(2012, 7, 10, 13, 14));
353
+ });
354
+
355
+ testSingleCase(chrono, "1 month", new Date(2016, 10 - 1, 1, 14, 52), { forwardDate: true }, (result, text) => {
356
+ expect(result.text).toBe("1 month");
357
+ expect(result.start.get("year")).toBe(2016);
358
+ expect(result.start.get("month")).toBe(11);
359
+ expect(result.start.get("day")).toBe(1);
360
+ });
361
+
362
+ testSingleCase(chrono, "in 1 month", new Date(2016, 10 - 1, 1, 14, 52), { forwardDate: true }, (result, text) => {
363
+ expect(result.text).toBe("in 1 month");
364
+ expect(result.start.get("year")).toBe(2016);
365
+ expect(result.start.get("month")).toBe(11);
366
+ expect(result.start.get("day")).toBe(1);
367
+ });
368
+ });
@@ -1,6 +1,6 @@
1
- import { ParsingComponents, ReferenceWithTimezone } from "../src/results";
1
+ import { ParsingComponents, ParsingResult, ReferenceWithTimezone } from "../src/results";
2
2
 
3
- test("Test - Create & manipulate date results", () => {
3
+ test("Test - Create & manipulate parsing components", () => {
4
4
  const reference = new ReferenceWithTimezone(new Date());
5
5
  const components = new ParsingComponents(reference, { year: 2014, month: 11, day: 24 });
6
6
 
@@ -8,6 +8,7 @@ test("Test - Create & manipulate date results", () => {
8
8
  expect(components.get("month")).toBe(11);
9
9
  expect(components.get("day")).toBe(24);
10
10
  expect(components.date()).toBeDefined();
11
+ expect(components.tags().size).toBe(0);
11
12
 
12
13
  // null
13
14
  expect(components.get("weekday")).toBeNull();
@@ -23,13 +24,45 @@ test("Test - Create & manipulate date results", () => {
23
24
  expect(components.get("weekday")).toBe(2);
24
25
  expect(components.isCertain("weekday")).toBe(true);
25
26
 
26
- // "imply" doesn't overrides "assign"
27
+ // "imply" doesn't override "assign"
27
28
  components.imply("year", 2013);
28
29
  expect(components.get("year")).toBe(2014);
29
30
 
30
31
  // "assign" overrides "assign"
31
32
  components.assign("year", 2013);
32
33
  expect(components.get("year")).toBe(2013);
34
+
35
+ components.addTag("custom/testing_component_tag");
36
+ expect(components.tags().size).toBe(1);
37
+ expect(components.tags()).toContain("custom/testing_component_tag");
38
+ expect(components.toString()).toContain("custom/testing_component_tag");
39
+ });
40
+
41
+ test("Test - Create & manipulate parsing results", () => {
42
+ const reference = new ReferenceWithTimezone(new Date());
43
+ const text = "1 - 2 hour later";
44
+
45
+ const startComponents = ParsingComponents.createRelativeFromReference(reference, { "hour": 1 }).addTag(
46
+ "custom/testing_start_component_tag"
47
+ );
48
+
49
+ const endComponents = ParsingComponents.createRelativeFromReference(reference, { "hour": 2 }).addTag(
50
+ "custom/testing_end_component_tag"
51
+ );
52
+
53
+ const result = new ParsingResult(reference, 0, text, startComponents, endComponents);
54
+
55
+ // The result's date() should be the same as the start components' date()
56
+ expect(result.date()).toStrictEqual(startComponents.date());
57
+
58
+ // The result's tags should include both the start and end components' tags
59
+ expect(result.tags()).toContain("custom/testing_start_component_tag");
60
+ expect(result.tags()).toContain("custom/testing_end_component_tag");
61
+
62
+ // The result's toString() should include the text and tags
63
+ expect(result.toString()).toContain(text);
64
+ expect(result.toString()).toContain("custom/testing_start_component_tag");
65
+ expect(result.toString()).toContain("custom/testing_end_component_tag");
33
66
  });
34
67
 
35
68
  test("Test - Calendar checking with implied components", () => {
@@ -113,3 +146,32 @@ test("Test - Calendar Checking", () => {
113
146
  expect(components.isValidDate()).toBe(false);
114
147
  }
115
148
  });
149
+
150
+ test("Test - Checking non-existing date during DST skip", () => {
151
+ // Only CET (or CEST) timezones where the DST starts on "Sunday, March 27, 2022" at "02:00 (2 am) local time"
152
+ const dateDstPre = new Date(2022, 3 - 1, 27, 2);
153
+ const dateDstPost = new Date(2022, 3 - 1, 27, 3);
154
+ if (dateDstPre.getTime() == dateDstPost.getTime()) {
155
+ const reference = new ReferenceWithTimezone(new Date());
156
+
157
+ // On "Sunday, March 27, 2022" at "02:00 local time", the clock is moved forward to "03:00 local time".
158
+ // Thus, the time between "02:00 and 02:59:59" does not exist.
159
+ expect(
160
+ new ParsingComponents(reference, { year: 2022, month: 3, day: 27, hour: 2, minute: 0 }).isValidDate()
161
+ ).toBe(false);
162
+ expect(
163
+ new ParsingComponents(reference, { year: 2022, month: 3, day: 27, hour: 2, minute: 1 }).isValidDate()
164
+ ).toBe(false);
165
+ expect(
166
+ new ParsingComponents(reference, { year: 2022, month: 3, day: 27, hour: 2, minute: 59 }).isValidDate()
167
+ ).toBe(false);
168
+
169
+ // Otherwise, it
170
+ expect(
171
+ new ParsingComponents(reference, { year: 2022, month: 3, day: 27, hour: 1, minute: 59 }).isValidDate()
172
+ ).toBe(true);
173
+ expect(
174
+ new ParsingComponents(reference, { year: 2022, month: 3, day: 27, hour: 3, minute: 0 }).isValidDate()
175
+ ).toBe(true);
176
+ }
177
+ });