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
package/dist/results.d.ts CHANGED
@@ -2,7 +2,7 @@ import { Component, ParsedComponents, ParsedResult, ParsingReference } from "./i
2
2
  import dayjs, { OpUnitType, QUnitType } from "dayjs";
3
3
  export declare class ReferenceWithTimezone {
4
4
  readonly instant: Date;
5
- readonly timezoneOffset: number;
5
+ readonly timezoneOffset?: number;
6
6
  constructor(input?: ParsingReference | Date);
7
7
  }
8
8
  export declare class ParsingComponents implements ParsedComponents {
@@ -29,7 +29,7 @@ export declare class ParsingComponents implements ParsedComponents {
29
29
  date(): Date;
30
30
  private dateWithoutTimezoneAdjustment;
31
31
  private getSystemTimezoneAdjustmentMinute;
32
- static createRelativeFromRefInstant(refInstant: Date, fragments: {
32
+ static createRelativeFromReference(reference: ReferenceWithTimezone, fragments: {
33
33
  [c in OpUnitType | QUnitType]?: number;
34
34
  }): ParsingComponents;
35
35
  }
package/dist/results.js CHANGED
@@ -11,7 +11,7 @@ const timezone_1 = require("./timezone");
11
11
  dayjs_1.default.extend(quarterOfYear_1.default);
12
12
  class ReferenceWithTimezone {
13
13
  constructor(input) {
14
- var _a, _b;
14
+ var _a;
15
15
  input = input !== null && input !== void 0 ? input : new Date();
16
16
  if (input instanceof Date) {
17
17
  this.instant = input;
@@ -19,7 +19,7 @@ class ReferenceWithTimezone {
19
19
  }
20
20
  else {
21
21
  this.instant = (_a = input.instant) !== null && _a !== void 0 ? _a : new Date();
22
- this.timezoneOffset = timezone_1.toTimezoneOffset((_b = input.timezone) !== null && _b !== void 0 ? _b : -this.instant.getTimezoneOffset());
22
+ this.timezoneOffset = timezone_1.toTimezoneOffset(input.timezone);
23
23
  }
24
24
  }
25
25
  }
@@ -120,34 +120,40 @@ class ParsingComponents {
120
120
  }
121
121
  date() {
122
122
  const date = this.dateWithoutTimezoneAdjustment();
123
- return new Date(date.getTime() + this.getSystemTimezoneAdjustmentMinute() * 60000);
123
+ return new Date(date.getTime() + this.getSystemTimezoneAdjustmentMinute(date) * 60000);
124
124
  }
125
125
  dateWithoutTimezoneAdjustment() {
126
126
  const date = new Date(this.get("year"), this.get("month") - 1, this.get("day"), this.get("hour"), this.get("minute"), this.get("second"), this.get("millisecond"));
127
127
  date.setFullYear(this.get("year"));
128
128
  return date;
129
129
  }
130
- getSystemTimezoneAdjustmentMinute() {
131
- var _a;
132
- const currentTimezoneOffset = -new Date().getTimezoneOffset();
133
- const targetTimezoneOffset = (_a = this.get("timezoneOffset")) !== null && _a !== void 0 ? _a : this.reference.timezoneOffset;
130
+ getSystemTimezoneAdjustmentMinute(date) {
131
+ var _a, _b;
132
+ if (!date || date.getTime() < 0) {
133
+ date = new Date();
134
+ }
135
+ const currentTimezoneOffset = -date.getTimezoneOffset();
136
+ const targetTimezoneOffset = (_b = (_a = this.get("timezoneOffset")) !== null && _a !== void 0 ? _a : this.reference.timezoneOffset) !== null && _b !== void 0 ? _b : currentTimezoneOffset;
134
137
  return currentTimezoneOffset - targetTimezoneOffset;
135
138
  }
136
- static createRelativeFromRefInstant(refInstant, fragments) {
137
- let date = dayjs_1.default(refInstant);
139
+ static createRelativeFromReference(reference, fragments) {
140
+ let date = dayjs_1.default(reference.instant);
138
141
  for (const key in fragments) {
139
142
  date = date.add(fragments[key], key);
140
143
  }
141
- const reference = new ReferenceWithTimezone(refInstant);
142
144
  const components = new ParsingComponents(reference);
143
145
  if (fragments["hour"] || fragments["minute"] || fragments["second"]) {
144
146
  dayjs_2.assignSimilarTime(components, date);
145
147
  dayjs_2.assignSimilarDate(components, date);
146
- components.assign("timezoneOffset", -refInstant.getTimezoneOffset());
148
+ if (reference.timezoneOffset !== null) {
149
+ components.assign("timezoneOffset", -reference.instant.getTimezoneOffset());
150
+ }
147
151
  }
148
152
  else {
149
153
  dayjs_2.implySimilarTime(components, date);
150
- components.imply("timezoneOffset", -refInstant.getTimezoneOffset());
154
+ if (reference.timezoneOffset !== null) {
155
+ components.imply("timezoneOffset", -reference.instant.getTimezoneOffset());
156
+ }
151
157
  if (fragments["d"]) {
152
158
  components.assign("day", date.date());
153
159
  components.assign("month", date.month() + 1);
@@ -191,4 +191,4 @@ export declare const TIMEZONE_ABBR_MAP: {
191
191
  YEKST: number;
192
192
  YEKT: number;
193
193
  };
194
- export declare function toTimezoneOffset(timezoneInput: string | number): number;
194
+ export declare function toTimezoneOffset(timezoneInput: string | number): number | null;
package/dist/timezone.js CHANGED
@@ -196,6 +196,9 @@ exports.TIMEZONE_ABBR_MAP = {
196
196
  };
197
197
  function toTimezoneOffset(timezoneInput) {
198
198
  var _a;
199
+ if (timezoneInput === null) {
200
+ return null;
201
+ }
199
202
  if (typeof timezoneInput === "number") {
200
203
  return timezoneInput;
201
204
  }
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.implySimilarTime = exports.assignSimilarTime = exports.assignSimilarDate = exports.assignTheNextDay = void 0;
4
+ const index_1 = require("../index");
4
5
  function assignTheNextDay(component, targetDayJs) {
5
6
  targetDayJs = targetDayJs.add(1, "day");
6
7
  assignSimilarDate(component, targetDayJs);
@@ -18,6 +19,12 @@ function assignSimilarTime(component, targetDayJs) {
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", index_1.Meridiem.AM);
24
+ }
25
+ else {
26
+ component.assign("meridiem", index_1.Meridiem.PM);
27
+ }
21
28
  }
22
29
  exports.assignSimilarTime = assignSimilarTime;
23
30
  function implySimilarTime(component, targetDayJs) {
package/package.json CHANGED
@@ -15,7 +15,7 @@
15
15
  "preset": "ts-jest"
16
16
  },
17
17
  "license": "MIT",
18
- "version": "2.3.1",
18
+ "version": "2.3.5",
19
19
  "directories": {
20
20
  "source": "./src",
21
21
  "test": "./test"
@@ -8,7 +8,9 @@ export function now(reference: ReferenceWithTimezone): ParsingComponents {
8
8
  const component = new ParsingComponents(reference, {});
9
9
  assignSimilarDate(component, targetDate);
10
10
  assignSimilarTime(component, targetDate);
11
- component.assign("timezoneOffset", targetDate.utcOffset());
11
+ if (reference.timezoneOffset !== null) {
12
+ component.assign("timezoneOffset", targetDate.utcOffset());
13
+ }
12
14
  return component;
13
15
  }
14
16
 
@@ -27,7 +27,7 @@ export abstract class AbstractParserWithWordBoundaryChecking implements Parser {
27
27
  }
28
28
 
29
29
  extract(context: ParsingContext, match: RegExpMatchArray) {
30
- const header = match[1];
30
+ const header = match[1] ?? "";
31
31
  match.index = match.index + header.length;
32
32
  match[0] = match[0].substring(header.length);
33
33
  for (let i = 2; i < match.length; i++) {
@@ -34,7 +34,7 @@ export default class ForwardDateRefiner implements Refiner {
34
34
  }
35
35
 
36
36
  if (result.start.isOnlyWeekdayComponent() && refMoment.isAfter(result.start.dayjs())) {
37
- if (refMoment.day() > result.start.get("weekday")) {
37
+ if (refMoment.day() >= result.start.get("weekday")) {
38
38
  refMoment = refMoment.day(result.start.get("weekday") + 7);
39
39
  } else {
40
40
  refMoment = refMoment.day(<number>result.start.get("weekday"));
package/src/index.ts CHANGED
@@ -105,7 +105,8 @@ import * as fr from "./locales/fr";
105
105
  import * as ja from "./locales/ja";
106
106
  import * as pt from "./locales/pt";
107
107
  import * as nl from "./locales/nl";
108
- export { de, fr, ja, pt, nl };
108
+ import * as zh from "./locales/zh";
109
+ export { de, fr, ja, pt, nl, zh };
109
110
 
110
111
  /**
111
112
  * A shortcut for {@link en | chrono.en.strict}
@@ -108,7 +108,7 @@ export const TIME_UNIT_DICTIONARY: { [word: string]: OpUnitType } = {
108
108
 
109
109
  export const NUMBER_PATTERN = `(?:${matchAnyPattern(
110
110
  INTEGER_WORD_DICTIONARY
111
- )}|[0-9]+|[0-9]+\\.[0-9]+|half(?:\\s*an?)?|an?(?:\\s*few)?|few|several|a?\\s*couple\\s*(?:of)?)`;
111
+ )}|[0-9]+|[0-9]+\\.[0-9]+|half(?:\\s*an?)?|an?\\b(?:\\s*few)?|few|several|a?\\s*couple\\s*(?:of)?)`;
112
112
 
113
113
  export function parseNumberPattern(match: string): number {
114
114
  const num = match.toLowerCase();
@@ -162,7 +162,7 @@ export const TIME_UNIT_DICTIONARY: { [word: string]: OpUnitType } = {
162
162
 
163
163
  export const NUMBER_PATTERN = `(?:${matchAnyPattern(
164
164
  INTEGER_WORD_DICTIONARY
165
- )}|[0-9]+|[0-9]+\\.[0-9]+|half(?:\\s{0,2}an?)?|an?(?:\\s{0,2}few)?|few|several|a?\\s{0,2}couple\\s{0,2}(?:of)?)`;
165
+ )}|[0-9]+|[0-9]+\\.[0-9]+|half(?:\\s{0,2}an?)?|an?\\b(?:\\s{0,2}few)?|few|several|a?\\s{0,2}couple\\s{0,2}(?:of)?)`;
166
166
 
167
167
  export function parseNumberPattern(match: string): number {
168
168
  const num = match.toLowerCase();
@@ -26,17 +26,17 @@ export default class ENRelativeDateFormatParser extends AbstractParserWithWordBo
26
26
  if (modifier == "next") {
27
27
  const timeUnits = {};
28
28
  timeUnits[timeunit] = 1;
29
- return ParsingComponents.createRelativeFromRefInstant(context.refDate, timeUnits);
29
+ return ParsingComponents.createRelativeFromReference(context.reference, timeUnits);
30
30
  }
31
31
 
32
32
  if (modifier == "last" || modifier == "past") {
33
33
  const timeUnits = {};
34
34
  timeUnits[timeunit] = -1;
35
- return ParsingComponents.createRelativeFromRefInstant(context.refDate, timeUnits);
35
+ return ParsingComponents.createRelativeFromReference(context.reference, timeUnits);
36
36
  }
37
37
 
38
38
  const components = context.createParsingComponents();
39
- let date = dayjs(context.refDate);
39
+ let date = dayjs(context.reference.instant);
40
40
 
41
41
  // This week
42
42
  if (unitWord.match(/week/i)) {
@@ -20,6 +20,6 @@ export default class ENTimeUnitAgoFormatParser extends AbstractParserWithWordBou
20
20
  const timeUnits = parseTimeUnits(match[1]);
21
21
  const outputTimeUnits = reverseTimeUnits(timeUnits);
22
22
 
23
- return ParsingComponents.createRelativeFromRefInstant(context.refDate, outputTimeUnits);
23
+ return ParsingComponents.createRelativeFromReference(context.reference, outputTimeUnits);
24
24
  }
25
25
  }
@@ -22,6 +22,6 @@ export default class ENTimeUnitCasualRelativeFormatParser extends AbstractParser
22
22
  break;
23
23
  }
24
24
 
25
- return ParsingComponents.createRelativeFromRefInstant(context.refDate, timeUnits);
25
+ return ParsingComponents.createRelativeFromReference(context.reference, timeUnits);
26
26
  }
27
27
  }
@@ -22,6 +22,6 @@ export default class ENTimeUnitLaterFormatParser extends AbstractParserWithWordB
22
22
 
23
23
  innerExtract(context: ParsingContext, match: RegExpMatchArray) {
24
24
  const fragments = parseTimeUnits(match[GROUP_NUM_TIMEUNITS]);
25
- return ParsingComponents.createRelativeFromRefInstant(context.refDate, fragments);
25
+ return ParsingComponents.createRelativeFromReference(context.reference, fragments);
26
26
  }
27
27
  }
@@ -21,6 +21,6 @@ export default class ENTimeUnitWithinFormatParser extends AbstractParserWithWord
21
21
 
22
22
  innerExtract(context: ParsingContext, match: RegExpMatchArray): ParsingComponents {
23
23
  const timeUnits = parseTimeUnits(match[1]);
24
- return ParsingComponents.createRelativeFromRefInstant(context.refDate, timeUnits);
24
+ return ParsingComponents.createRelativeFromReference(context.reference, timeUnits);
25
25
  }
26
26
  }
@@ -105,7 +105,7 @@ export const TIME_UNIT_DICTIONARY: { [word: string]: OpUnitType | QUnitType } =
105
105
 
106
106
  export const NUMBER_PATTERN = `(?:${matchAnyPattern(
107
107
  INTEGER_WORD_DICTIONARY
108
- )}|[0-9]+|[0-9]+\\.[0-9]+|une?|quelques?|demi-?)`;
108
+ )}|[0-9]+|[0-9]+\\.[0-9]+|une?\\b|quelques?|demi-?)`;
109
109
 
110
110
  export function parseNumberPattern(match: string): number {
111
111
  const num = match.toLowerCase();
@@ -17,6 +17,6 @@ export default class FRTimeUnitAgoFormatParser extends AbstractParserWithWordBou
17
17
  const timeUnits = parseTimeUnits(match[1]);
18
18
  const outputTimeUnits = reverseTimeUnits(timeUnits);
19
19
 
20
- return ParsingComponents.createRelativeFromRefInstant(context.refDate, outputTimeUnits);
20
+ return ParsingComponents.createRelativeFromReference(context.reference, outputTimeUnits);
21
21
  }
22
22
  }
@@ -38,6 +38,6 @@ export default class FRTimeUnitAgoFormatParser extends AbstractParserWithWordBou
38
38
  timeUnits = reverseTimeUnits(timeUnits);
39
39
  }
40
40
 
41
- return ParsingComponents.createRelativeFromRefInstant(context.refDate, timeUnits);
41
+ return ParsingComponents.createRelativeFromReference(context.reference, timeUnits);
42
42
  }
43
43
  }
@@ -10,6 +10,6 @@ export default class FRTimeUnitWithinFormatParser extends AbstractParserWithWord
10
10
 
11
11
  innerExtract(context: ParsingContext, match: RegExpMatchArray): ParsingComponents {
12
12
  const timeUnits = parseTimeUnits(match[1]);
13
- return ParsingComponents.createRelativeFromRefInstant(context.refDate, timeUnits);
13
+ return ParsingComponents.createRelativeFromReference(context.reference, timeUnits);
14
14
  }
15
15
  }
@@ -27,17 +27,17 @@ export default class NLRelativeDateFormatParser extends AbstractParserWithWordBo
27
27
  if (modifier == "volgend" || modifier == "volgende" || modifier == "komende") {
28
28
  const timeUnits = {};
29
29
  timeUnits[timeunit] = 1;
30
- return ParsingComponents.createRelativeFromRefInstant(context.refDate, timeUnits);
30
+ return ParsingComponents.createRelativeFromReference(context.reference, timeUnits);
31
31
  }
32
32
 
33
33
  if (modifier == "afgelopen" || modifier == "vorige") {
34
34
  const timeUnits = {};
35
35
  timeUnits[timeunit] = -1;
36
- return ParsingComponents.createRelativeFromRefInstant(context.refDate, timeUnits);
36
+ return ParsingComponents.createRelativeFromReference(context.reference, timeUnits);
37
37
  }
38
38
 
39
39
  const components = context.createParsingComponents();
40
- let date = dayjs(context.refDate);
40
+ let date = dayjs(context.reference.instant);
41
41
 
42
42
  // This week
43
43
  if (unitWord.match(/week/i)) {
@@ -21,6 +21,6 @@ export default class NLTimeUnitAgoFormatParser extends AbstractParserWithWordBou
21
21
  const timeUnits = parseTimeUnits(match[1]);
22
22
  const outputTimeUnits = reverseTimeUnits(timeUnits);
23
23
 
24
- return ParsingComponents.createRelativeFromRefInstant(context.refDate, outputTimeUnits);
24
+ return ParsingComponents.createRelativeFromReference(context.reference, outputTimeUnits);
25
25
  }
26
26
  }
@@ -22,6 +22,6 @@ export default class NLTimeUnitCasualRelativeFormatParser extends AbstractParser
22
22
  break;
23
23
  }
24
24
 
25
- return ParsingComponents.createRelativeFromRefInstant(context.refDate, timeUnits);
25
+ return ParsingComponents.createRelativeFromReference(context.reference, timeUnits);
26
26
  }
27
27
  }
@@ -22,6 +22,6 @@ export default class NLTimeUnitLaterFormatParser extends AbstractParserWithWordB
22
22
 
23
23
  innerExtract(context: ParsingContext, match: RegExpMatchArray) {
24
24
  const fragments = parseTimeUnits(match[GROUP_NUM_TIMEUNITS]);
25
- return ParsingComponents.createRelativeFromRefInstant(context.refDate, fragments);
25
+ return ParsingComponents.createRelativeFromReference(context.reference, fragments);
26
26
  }
27
27
  }
@@ -10,6 +10,6 @@ export default class NLTimeUnitWithinFormatParser extends AbstractParserWithWord
10
10
 
11
11
  innerExtract(context: ParsingContext, match: RegExpMatchArray): ParsingComponents {
12
12
  const timeUnits = parseTimeUnits(match[1]);
13
- return ParsingComponents.createRelativeFromRefInstant(context.refDate, timeUnits);
13
+ return ParsingComponents.createRelativeFromReference(context.reference, timeUnits);
14
14
  }
15
15
  }
@@ -0,0 +1,53 @@
1
+ export const NUMBER = {
2
+ "零": 0,
3
+ "一": 1,
4
+ "二": 2,
5
+ "兩": 2,
6
+ "三": 3,
7
+ "四": 4,
8
+ "五": 5,
9
+ "六": 6,
10
+ "七": 7,
11
+ "八": 8,
12
+ "九": 9,
13
+ "十": 10,
14
+ "廿": 20,
15
+ "卅": 30,
16
+ };
17
+
18
+ export const WEEKDAY_OFFSET = {
19
+ "天": 0,
20
+ "日": 0,
21
+ "一": 1,
22
+ "二": 2,
23
+ "三": 3,
24
+ "四": 4,
25
+ "五": 5,
26
+ "六": 6,
27
+ };
28
+
29
+ export function zhStringToNumber(text: string) {
30
+ let number = 0;
31
+
32
+ for (let i = 0; i < text.length; i++) {
33
+ const char = text[i];
34
+ if (char === "十") {
35
+ number = number === 0 ? NUMBER[char] : number * NUMBER[char];
36
+ } else {
37
+ number += NUMBER[char];
38
+ }
39
+ }
40
+
41
+ return number;
42
+ }
43
+
44
+ export function zhStringToYear(text: string) {
45
+ let string = "";
46
+
47
+ for (let i = 0; i < text.length; i++) {
48
+ const char = text[i];
49
+ string = string + NUMBER[char];
50
+ }
51
+
52
+ return parseInt(string);
53
+ }
@@ -0,0 +1,128 @@
1
+ import dayjs from "dayjs";
2
+ import { ParsingContext } from "../../../../chrono";
3
+ import { AbstractParserWithWordBoundaryChecking } from "../../../../common/parsers/AbstractParserWithWordBoundary";
4
+ import { ParsingComponents, ParsingResult } from "../../../../results";
5
+
6
+ const NOW_GROUP = 1;
7
+ const DAY_GROUP_1 = 2;
8
+ const TIME_GROUP_1 = 3;
9
+ const TIME_GROUP_2 = 4;
10
+ const DAY_GROUP_3 = 5;
11
+ const TIME_GROUP_3 = 6;
12
+
13
+ export default class ZHHantCasualDateParser extends AbstractParserWithWordBoundaryChecking {
14
+ innerPattern(context: ParsingContext): RegExp {
15
+ return new RegExp(
16
+ "(而家|立(?:刻|即)|即刻)|" +
17
+ "(今|明|前|大前|後|大後|聽|昨|尋|琴)(早|朝|晚)|" +
18
+ "(上(?:午|晝)|朝(?:早)|早(?:上)|下(?:午|晝)|晏(?:晝)|晚(?:上)|夜(?:晚)?|中(?:午)|凌(?:晨))|" +
19
+ "(今|明|前|大前|後|大後|聽|昨|尋|琴)(?:日|天)" +
20
+ "(?:[\\s|,|,]*)" +
21
+ "(?:(上(?:午|晝)|朝(?:早)|早(?:上)|下(?:午|晝)|晏(?:晝)|晚(?:上)|夜(?:晚)?|中(?:午)|凌(?:晨)))?",
22
+ "i"
23
+ );
24
+ }
25
+
26
+ innerExtract(context: ParsingContext, match: RegExpMatchArray): ParsingComponents | ParsingResult {
27
+ const index = match.index;
28
+ const result = context.createParsingResult(index, match[0]);
29
+
30
+ const refMoment = dayjs(context.refDate);
31
+ let startMoment = refMoment;
32
+
33
+ if (match[NOW_GROUP]) {
34
+ result.start.imply("hour", refMoment.hour());
35
+ result.start.imply("minute", refMoment.minute());
36
+ result.start.imply("second", refMoment.second());
37
+ result.start.imply("millisecond", refMoment.millisecond());
38
+ } else if (match[DAY_GROUP_1]) {
39
+ const day1 = match[DAY_GROUP_1];
40
+ const time1 = match[TIME_GROUP_1];
41
+
42
+ if (day1 == "明" || day1 == "聽") {
43
+ // Check not "Tomorrow" on late night
44
+ if (refMoment.hour() > 1) {
45
+ startMoment = startMoment.add(1, "day");
46
+ }
47
+ } else if (day1 == "昨" || day1 == "尋" || day1 == "琴") {
48
+ startMoment = startMoment.add(-1, "day");
49
+ } else if (day1 == "前") {
50
+ startMoment = startMoment.add(-2, "day");
51
+ } else if (day1 == "大前") {
52
+ startMoment = startMoment.add(-3, "day");
53
+ } else if (day1 == "後") {
54
+ startMoment = startMoment.add(2, "day");
55
+ } else if (day1 == "大後") {
56
+ startMoment = startMoment.add(3, "day");
57
+ }
58
+
59
+ if (time1 == "早" || time1 == "朝") {
60
+ result.start.imply("hour", 6);
61
+ } else if (time1 == "晚") {
62
+ result.start.imply("hour", 22);
63
+ result.start.imply("meridiem", 1);
64
+ }
65
+ } else if (match[TIME_GROUP_2]) {
66
+ const timeString2 = match[TIME_GROUP_2];
67
+ const time2 = timeString2[0];
68
+ if (time2 == "早" || time2 == "朝" || time2 == "上") {
69
+ result.start.imply("hour", 6);
70
+ } else if (time2 == "下" || time2 == "晏") {
71
+ result.start.imply("hour", 15);
72
+ result.start.imply("meridiem", 1);
73
+ } else if (time2 == "中") {
74
+ result.start.imply("hour", 12);
75
+ result.start.imply("meridiem", 1);
76
+ } else if (time2 == "夜" || time2 == "晚") {
77
+ result.start.imply("hour", 22);
78
+ result.start.imply("meridiem", 1);
79
+ } else if (time2 == "凌") {
80
+ result.start.imply("hour", 0);
81
+ }
82
+ } else if (match[DAY_GROUP_3]) {
83
+ const day3 = match[DAY_GROUP_3];
84
+
85
+ if (day3 == "明" || day3 == "聽") {
86
+ // Check not "Tomorrow" on late night
87
+ if (refMoment.hour() > 1) {
88
+ startMoment = startMoment.add(1, "day");
89
+ }
90
+ } else if (day3 == "昨" || day3 == "尋" || day3 == "琴") {
91
+ startMoment = startMoment.add(-1, "day");
92
+ } else if (day3 == "前") {
93
+ startMoment = startMoment.add(-2, "day");
94
+ } else if (day3 == "大前") {
95
+ startMoment = startMoment.add(-3, "day");
96
+ } else if (day3 == "後") {
97
+ startMoment = startMoment.add(2, "day");
98
+ } else if (day3 == "大後") {
99
+ startMoment = startMoment.add(3, "day");
100
+ }
101
+
102
+ const timeString3 = match[TIME_GROUP_3];
103
+ if (timeString3) {
104
+ const time3 = timeString3[0];
105
+ if (time3 == "早" || time3 == "朝" || time3 == "上") {
106
+ result.start.imply("hour", 6);
107
+ } else if (time3 == "下" || time3 == "晏") {
108
+ result.start.imply("hour", 15);
109
+ result.start.imply("meridiem", 1);
110
+ } else if (time3 == "中") {
111
+ result.start.imply("hour", 12);
112
+ result.start.imply("meridiem", 1);
113
+ } else if (time3 == "夜" || time3 == "晚") {
114
+ result.start.imply("hour", 22);
115
+ result.start.imply("meridiem", 1);
116
+ } else if (time3 == "凌") {
117
+ result.start.imply("hour", 0);
118
+ }
119
+ }
120
+ }
121
+
122
+ result.start.assign("day", startMoment.date());
123
+ result.start.assign("month", startMoment.month() + 1);
124
+ result.start.assign("year", startMoment.year());
125
+
126
+ return result;
127
+ }
128
+ }
@@ -0,0 +1,68 @@
1
+ import dayjs from "dayjs";
2
+ import { ParsingContext } from "../../../../chrono";
3
+ import { AbstractParserWithWordBoundaryChecking } from "../../../../common/parsers/AbstractParserWithWordBoundary";
4
+ import { NUMBER, zhStringToNumber, zhStringToYear } from "../constants";
5
+
6
+ const YEAR_GROUP = 1;
7
+ const MONTH_GROUP = 2;
8
+ const DAY_GROUP = 3;
9
+
10
+ export default class ZHHantDateParser extends AbstractParserWithWordBoundaryChecking {
11
+ innerPattern() {
12
+ // prettier-ignore
13
+ return new RegExp(
14
+ "(" +
15
+ "\\d{2,4}|" +
16
+ "[" + Object.keys(NUMBER).join("") + "]{4}|" +
17
+ "[" + Object.keys(NUMBER).join("") + "]{2}" +
18
+ ")?"+
19
+ "(?:\\s*)" +
20
+ "(?:年)?" +
21
+ "(?:[\\s|,|,]*)" +
22
+
23
+ "(" +
24
+ "\\d{1,2}|"+
25
+ "[" +Object.keys(NUMBER).join("") +"]{1,2}"+
26
+ ")" +
27
+ "(?:\\s*)" +
28
+ "(?:月)" +
29
+ "(?:\\s*)" +
30
+ "(" +
31
+ "\\d{1,2}|" +
32
+ "[" + Object.keys(NUMBER).join("") + "]{1,2}" +
33
+ ")?" +
34
+ "(?:\\s*)" +
35
+ "(?:日|號)?"
36
+ );
37
+ }
38
+
39
+ innerExtract(context: ParsingContext, match: RegExpMatchArray) {
40
+ const startMoment = dayjs(context.refDate);
41
+ const result = context.createParsingResult(match.index, match[0]);
42
+
43
+ //Month
44
+ let month = parseInt(match[MONTH_GROUP]);
45
+ if (isNaN(month)) month = zhStringToNumber(match[MONTH_GROUP]);
46
+ result.start.assign("month", month);
47
+
48
+ //Day
49
+ if (match[DAY_GROUP]) {
50
+ let day = parseInt(match[DAY_GROUP]);
51
+ if (isNaN(day)) day = zhStringToNumber(match[DAY_GROUP]);
52
+ result.start.assign("day", day);
53
+ } else {
54
+ result.start.imply("day", startMoment.date());
55
+ }
56
+
57
+ //Year
58
+ if (match[YEAR_GROUP]) {
59
+ let year = parseInt(match[YEAR_GROUP]);
60
+ if (isNaN(year)) year = zhStringToYear(match[YEAR_GROUP]);
61
+ result.start.assign("year", year);
62
+ } else {
63
+ result.start.imply("year", startMoment.year());
64
+ }
65
+
66
+ return result;
67
+ }
68
+ }