timelang 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +1 -2
- package/dist/index.cjs +419 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +419 -9
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) Kamran Ahmed
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -14,8 +14,7 @@ It takes natural language inputs and converts them into structured date, duratio
|
|
|
14
14
|
- **Forgiving parser** — Extra spaces, mixed case, missing separators all work
|
|
15
15
|
- **Edge case handling** — Year rollovers, leap years, fiscal quarters
|
|
16
16
|
- **Configurable** — Reference date, fiscal year start, week start day, date format
|
|
17
|
-
- **
|
|
18
|
-
- **TypeScript** — Full type definitions included
|
|
17
|
+
- **TypeScript** — Typesafe with full type definitions
|
|
19
18
|
|
|
20
19
|
## Installation
|
|
21
20
|
|
package/dist/index.cjs
CHANGED
|
@@ -270,8 +270,23 @@ var lexer = import_moo.default.compile({
|
|
|
270
270
|
"sat",
|
|
271
271
|
"sun"
|
|
272
272
|
],
|
|
273
|
+
// Ago keyword for relative dates
|
|
274
|
+
kw_ago: ["ago"],
|
|
275
|
+
// Weekend and night keywords
|
|
276
|
+
kw_weekend: ["weekend"],
|
|
277
|
+
kw_tonight: ["tonight"],
|
|
278
|
+
kw_night: ["night"],
|
|
279
|
+
kw_fortnight: ["fortnight", "fortnights"],
|
|
273
280
|
// Other keywords
|
|
274
|
-
otherKeyword: ["fiscal", "fy", "daily", "weekly", "monthly", "yearly", "annually", "
|
|
281
|
+
otherKeyword: ["fiscal", "fy", "daily", "weekly", "monthly", "yearly", "annually", "hence", "later", "earlier"],
|
|
282
|
+
// Business keywords
|
|
283
|
+
kw_business: ["business"],
|
|
284
|
+
// EOD/COB keywords
|
|
285
|
+
kw_eod: ["eod"],
|
|
286
|
+
kw_cob: ["cob"],
|
|
287
|
+
kw_close: ["close"],
|
|
288
|
+
// Week keyword (for "week 1" patterns)
|
|
289
|
+
kw_week: ["week"]
|
|
275
290
|
})
|
|
276
291
|
// Keywords are matched against lowercase input
|
|
277
292
|
},
|
|
@@ -324,6 +339,13 @@ var makeRelative = (direction, duration) => ({
|
|
|
324
339
|
direction,
|
|
325
340
|
duration
|
|
326
341
|
});
|
|
342
|
+
var makeRelativeDate = (direction, duration, baseDate, time2) => ({
|
|
343
|
+
nodeType: "relativeDate",
|
|
344
|
+
direction,
|
|
345
|
+
duration,
|
|
346
|
+
baseDate,
|
|
347
|
+
time: time2
|
|
348
|
+
});
|
|
327
349
|
var makeTitled = (title, expression, titleStart, titleEnd) => ({
|
|
328
350
|
nodeType: "titled",
|
|
329
351
|
title: title.trim(),
|
|
@@ -559,10 +581,14 @@ var grammar = {
|
|
|
559
581
|
{ "name": "expression", "symbols": ["range"], "postprocess": first },
|
|
560
582
|
{ "name": "expression", "symbols": ["span"], "postprocess": first },
|
|
561
583
|
{ "name": "expression", "symbols": ["relative"], "postprocess": first },
|
|
584
|
+
{ "name": "expression", "symbols": ["relativeDate"], "postprocess": first },
|
|
585
|
+
{ "name": "expression", "symbols": ["lastDayOfMonthExpr"], "postprocess": first },
|
|
586
|
+
{ "name": "expression", "symbols": ["date"], "postprocess": first },
|
|
562
587
|
{ "name": "expression", "symbols": ["fuzzy"], "postprocess": first },
|
|
563
588
|
{ "name": "expression", "symbols": ["forDuration"], "postprocess": first },
|
|
564
589
|
{ "name": "expression", "symbols": ["duration"], "postprocess": first },
|
|
565
|
-
{ "name": "
|
|
590
|
+
{ "name": "lastDayOfMonthExpr", "symbols": ["lastRelative", "_", "dayUnit", "_", "ofConnector", "_", "month"], "postprocess": (d) => makeDate({ month: d[6], lastDayOfMonth: true }) },
|
|
591
|
+
{ "name": "lastDayOfMonthExpr", "symbols": ["lastRelative", "_", "dayUnit", "_", "ofConnector", "_", "theConnector", "_", "monthUnit"], "postprocess": (d) => makeDate({ lastDayOfMonth: true, monthFromRef: true }) },
|
|
566
592
|
{ "name": "forDuration", "symbols": ["forConnector", "_", "duration"], "postprocess": (d) => d[2] },
|
|
567
593
|
{ "name": "range", "symbols": ["date", "_", "toConnector", "_", "date"], "postprocess": (d) => makeRange(d[0], d[4]) },
|
|
568
594
|
{ "name": "range", "symbols": ["fromConnector", "_", "date", "_", "toConnector", "_", "date"], "postprocess": (d) => makeRange(d[2], d[6]) },
|
|
@@ -644,6 +670,30 @@ var grammar = {
|
|
|
644
670
|
{ "name": "relative", "symbols": ["inConnector", "_", "theConnector", "_", "pastRelative", "_", "unit"], "postprocess": (d) => makeRelative("past", makeDuration(1, d[6])) },
|
|
645
671
|
{ "name": "relative", "symbols": ["inConnector", "_", "theConnector", "_", "comingRelative", "_", "unit"], "postprocess": (d) => makeRelative("future", makeDuration(1, d[6])) },
|
|
646
672
|
{ "name": "relative", "symbols": ["inConnector", "_", "theConnector", "_", "upcomingRelative", "_", "unit"], "postprocess": (d) => makeRelative("future", makeDuration(1, d[6])) },
|
|
673
|
+
{ "name": "relativeDate", "symbols": ["duration", "_", "agoConnector"], "postprocess": (d) => makeRelativeDate("past", d[0]) },
|
|
674
|
+
{ "name": "relativeDate", "symbols": ["duration", "_", "agoConnector", "_", "atConnector", "_", "time"], "postprocess": (d) => makeRelativeDate("past", d[0], void 0, d[6]) },
|
|
675
|
+
{ "name": "relativeDate", "symbols": ["duration", "_", "agoConnector", "_", "atConnector", "_", "timeWord"], "postprocess": (d) => makeRelativeDate("past", d[0], void 0, { special: d[6] }) },
|
|
676
|
+
{ "name": "relativeDate", "symbols": ["inConnector", "_", "duration"], "postprocess": (d) => makeRelativeDate("future", d[2]) },
|
|
677
|
+
{ "name": "relativeDate", "symbols": ["inConnector", "_", "duration", "_", "atConnector", "_", "time"], "postprocess": (d) => makeRelativeDate("future", d[2], void 0, d[6]) },
|
|
678
|
+
{ "name": "relativeDate", "symbols": ["inConnector", "_", "duration", "_", "atConnector", "_", "timeWord"], "postprocess": (d) => makeRelativeDate("future", d[2], void 0, { special: d[6] }) },
|
|
679
|
+
{ "name": "relativeDate", "symbols": ["duration", "_", "fromConnector", "_", "now"], "postprocess": (d) => makeRelativeDate("future", d[0]) },
|
|
680
|
+
{ "name": "relativeDate", "symbols": ["duration", "_", "fromConnector", "_", "now", "_", "atConnector", "_", "time"], "postprocess": (d) => makeRelativeDate("future", d[0], void 0, d[8]) },
|
|
681
|
+
{ "name": "relativeDate", "symbols": ["duration", "_", "fromConnector", "_", "now", "_", "atConnector", "_", "timeWord"], "postprocess": (d) => makeRelativeDate("future", d[0], void 0, { special: d[8] }) },
|
|
682
|
+
{ "name": "relativeDate", "symbols": ["duration", "_", "fromConnector", "_", "today"], "postprocess": (d) => makeRelativeDate("future", d[0], makeDate({ special: "today" })) },
|
|
683
|
+
{ "name": "relativeDate", "symbols": ["duration", "_", "fromConnector", "_", "today", "_", "atConnector", "_", "time"], "postprocess": (d) => makeRelativeDate("future", d[0], makeDate({ special: "today" }), d[8]) },
|
|
684
|
+
{ "name": "relativeDate", "symbols": ["duration", "_", "fromConnector", "_", "tomorrow"], "postprocess": (d) => makeRelativeDate("future", d[0], makeDate({ special: "tomorrow" })) },
|
|
685
|
+
{ "name": "relativeDate", "symbols": ["duration", "_", "fromConnector", "_", "tomorrow", "_", "atConnector", "_", "time"], "postprocess": (d) => makeRelativeDate("future", d[0], makeDate({ special: "tomorrow" }), d[8]) },
|
|
686
|
+
{ "name": "relativeDate", "symbols": ["duration", "_", "fromConnector", "_", "yesterday"], "postprocess": (d) => makeRelativeDate("future", d[0], makeDate({ special: "yesterday" })) },
|
|
687
|
+
{ "name": "relativeDate", "symbols": ["duration", "_", "henceConnector"], "postprocess": (d) => makeRelativeDate("future", d[0]) },
|
|
688
|
+
{ "name": "relativeDate", "symbols": ["duration", "_", "laterConnector"], "postprocess": (d) => makeRelativeDate("future", d[0]) },
|
|
689
|
+
{ "name": "relativeDate", "symbols": ["duration", "_", "beforeConnector", "_", "date"], "postprocess": (d) => makeRelativeDate("past", d[0], d[4]) },
|
|
690
|
+
{ "name": "relativeDate", "symbols": ["duration", "_", "afterConnector", "_", "date"], "postprocess": (d) => makeRelativeDate("future", d[0], d[4]) },
|
|
691
|
+
{ "name": "relativeDate", "symbols": ["theConnector", "_", "dayUnit", "_", "beforeConnector", "_", "date"], "postprocess": (d) => makeRelativeDate("past", makeDuration(1, "day"), d[6]) },
|
|
692
|
+
{ "name": "relativeDate", "symbols": ["theConnector", "_", "dayUnit", "_", "afterConnector", "_", "date"], "postprocess": (d) => makeRelativeDate("future", makeDuration(1, "day"), d[6]) },
|
|
693
|
+
{ "name": "relativeDate", "symbols": ["dayUnit", "_", "beforeConnector", "_", "date"], "postprocess": (d) => makeRelativeDate("past", makeDuration(1, "day"), d[4]) },
|
|
694
|
+
{ "name": "relativeDate", "symbols": ["dayUnit", "_", "afterConnector", "_", "date"], "postprocess": (d) => makeRelativeDate("future", makeDuration(1, "day"), d[4]) },
|
|
695
|
+
{ "name": "relativeDate", "symbols": ["wordNumber", "_", "unit", "_", "beforeConnector", "_", "date"], "postprocess": (d) => makeRelativeDate("past", makeDuration(parseWordNumber(d[0]), d[2]), d[6]) },
|
|
696
|
+
{ "name": "relativeDate", "symbols": ["wordNumber", "_", "unit", "_", "afterConnector", "_", "date"], "postprocess": (d) => makeRelativeDate("future", makeDuration(parseWordNumber(d[0]), d[2]), d[6]) },
|
|
647
697
|
{ "name": "fuzzy", "symbols": ["quarter"], "postprocess": (d) => makeFuzzy({ period: "quarter", quarter: parseQuarter(d[0].value) }) },
|
|
648
698
|
{ "name": "fuzzy", "symbols": ["quarter", "_", "year"], "postprocess": (d) => makeFuzzy({ period: "quarter", quarter: parseQuarter(d[0].value), year: d[2] }) },
|
|
649
699
|
{ "name": "fuzzy", "symbols": ["half"], "postprocess": (d) => makeFuzzy({ period: "half", half: parseHalf(d[0].value) }) },
|
|
@@ -726,8 +776,29 @@ var grammar = {
|
|
|
726
776
|
{ "name": "fuzzy", "symbols": ["lateModifier", "_", "thisRelative", "_", "unit"], "postprocess": (d) => makeFuzzy({ period: d[4], modifier: "late", relative: "this" }) },
|
|
727
777
|
{ "name": "fuzzy", "symbols": ["beginningConnector", "_", "ofConnector", "_", "theConnector", "_", "unit"], "postprocess": (d) => makeFuzzy({ period: d[6], modifier: "beginning" }) },
|
|
728
778
|
{ "name": "fuzzy", "symbols": ["middleConnector", "_", "ofConnector", "_", "theConnector", "_", "unit"], "postprocess": (d) => makeFuzzy({ period: d[6], modifier: "middle" }) },
|
|
729
|
-
{ "name": "fuzzy", "symbols": ["lastRelative", "_", "unit", "_", "ofConnector", "_", "month"], "postprocess": (d
|
|
730
|
-
|
|
779
|
+
{ "name": "fuzzy", "symbols": ["lastRelative", "_", "unit", "_", "ofConnector", "_", "month"], "postprocess": (d, _, reject) => {
|
|
780
|
+
if (d[2].toLowerCase() === "day" || d[2].toLowerCase() === "days") return reject;
|
|
781
|
+
return makeFuzzy({ period: "month", month: d[6], modifier: "late" });
|
|
782
|
+
} },
|
|
783
|
+
{ "name": "fuzzy", "symbols": ["ordinalWord", "_", "unit", "_", "ofConnector", "_", "month"], "postprocess": (d, _, reject) => {
|
|
784
|
+
if (d[2].toLowerCase() === "day" || d[2].toLowerCase() === "days") return reject;
|
|
785
|
+
return makeFuzzy({ period: "month", month: d[6], modifier: parseOrdinalWord(d[0]) <= 2 ? "early" : parseOrdinalWord(d[0]) >= 4 ? "late" : "mid" });
|
|
786
|
+
} },
|
|
787
|
+
{ "name": "fuzzy", "symbols": ["weekendKeyword"], "postprocess": (d) => makeFuzzy({ period: "weekend", relative: "this" }) },
|
|
788
|
+
{ "name": "fuzzy", "symbols": ["theConnector", "_", "weekendKeyword"], "postprocess": (d) => makeFuzzy({ period: "weekend", relative: "this" }) },
|
|
789
|
+
{ "name": "fuzzy", "symbols": ["thisRelative", "_", "weekendKeyword"], "postprocess": (d) => makeFuzzy({ period: "weekend", relative: "this" }) },
|
|
790
|
+
{ "name": "fuzzy", "symbols": ["nextRelative", "_", "weekendKeyword"], "postprocess": (d) => makeFuzzy({ period: "weekend", relative: "next" }) },
|
|
791
|
+
{ "name": "fuzzy", "symbols": ["lastRelative", "_", "weekendKeyword"], "postprocess": (d) => makeFuzzy({ period: "weekend", relative: "last" }) },
|
|
792
|
+
{ "name": "fuzzy", "symbols": ["tonightKeyword"], "postprocess": (d) => makeFuzzy({ period: "tonight" }) },
|
|
793
|
+
{ "name": "fuzzy", "symbols": ["nightKeyword"], "postprocess": (d) => makeFuzzy({ period: "night" }) },
|
|
794
|
+
{ "name": "fuzzy", "symbols": ["lastRelative", "_", "nightKeyword"], "postprocess": (d) => makeFuzzy({ period: "night", relative: "last" }) },
|
|
795
|
+
{ "name": "fuzzy", "symbols": ["tomorrow", "_", "nightKeyword"], "postprocess": (d) => makeFuzzy({ period: "night", relative: "tomorrow" }) },
|
|
796
|
+
{ "name": "fuzzy", "symbols": ["weekday", "_", "nightKeyword"], "postprocess": (d) => makeFuzzy({ period: "night", weekday: d[0] }) },
|
|
797
|
+
{ "name": "fuzzy", "symbols": ["fortnightKeyword"], "postprocess": (d) => makeFuzzy({ period: "fortnight" }) },
|
|
798
|
+
{ "name": "fuzzy", "symbols": ["nextRelative", "_", "fortnightKeyword"], "postprocess": (d) => makeFuzzy({ period: "fortnight", relative: "next" }) },
|
|
799
|
+
{ "name": "fuzzy", "symbols": ["lastRelative", "_", "fortnightKeyword"], "postprocess": (d) => makeFuzzy({ period: "fortnight", relative: "last" }) },
|
|
800
|
+
{ "name": "fuzzy", "symbols": ["inConnector", "_", "wordNumber", "_", "fortnightKeyword"], "postprocess": (d) => makeFuzzy({ period: "fortnight", count: parseWordNumber(d[2]) }) },
|
|
801
|
+
{ "name": "fuzzy", "symbols": ["inConnector", "_", "number", "_", "fortnightKeyword"], "postprocess": (d) => makeFuzzy({ period: "fortnight", count: d[2] }) },
|
|
731
802
|
{ "name": "duration", "symbols": ["number", "_", "unit"], "postprocess": (d) => makeDuration(d[0], d[2]) },
|
|
732
803
|
{ "name": "duration", "symbols": ["wordNumber", "_", "unit"], "postprocess": (d) => makeDuration(parseWordNumber(d[0]), d[2]) },
|
|
733
804
|
{ "name": "duration", "symbols": ["abbreviatedDuration"], "postprocess": (d) => d[0] },
|
|
@@ -755,6 +826,7 @@ var grammar = {
|
|
|
755
826
|
return makeDuration(value, unitMap[match[2]]);
|
|
756
827
|
} },
|
|
757
828
|
{ "name": "date", "symbols": ["specialDay"], "postprocess": (d) => makeDate({ special: d[0] }) },
|
|
829
|
+
{ "name": "date", "symbols": ["ordinalWeekdayOfMonth"], "postprocess": first },
|
|
758
830
|
{ "name": "date", "symbols": ["relativeWeekday"], "postprocess": first },
|
|
759
831
|
{ "name": "date", "symbols": ["weekday"], "postprocess": (d) => makeDate({ weekday: d[0] }) },
|
|
760
832
|
{ "name": "date", "symbols": ["monthDayYear"], "postprocess": first },
|
|
@@ -769,6 +841,7 @@ var grammar = {
|
|
|
769
841
|
{ "name": "date", "symbols": ["monthOnly"], "postprocess": first },
|
|
770
842
|
{ "name": "date", "symbols": ["yearOnly"], "postprocess": first },
|
|
771
843
|
{ "name": "date", "symbols": ["timeOnly"], "postprocess": first },
|
|
844
|
+
{ "name": "date", "symbols": ["dayOnly"], "postprocess": first },
|
|
772
845
|
{ "name": "monthDayCompact", "symbols": [lexer.has("monthDayCompact") ? { type: "monthDayCompact" } : monthDayCompact], "postprocess": (d) => {
|
|
773
846
|
const parsed = parseMonthDayCompact(d[0].value);
|
|
774
847
|
return makeDate({ month: parsed.month, day: parsed.day });
|
|
@@ -785,6 +858,8 @@ var grammar = {
|
|
|
785
858
|
} },
|
|
786
859
|
{ "name": "timeOnly", "symbols": ["time"], "postprocess": (d) => makeDate({ time: d[0], timeOnly: true }) },
|
|
787
860
|
{ "name": "timeOnly", "symbols": ["timeWord"], "postprocess": (d) => makeDate({ time: { special: d[0] }, timeOnly: true }) },
|
|
861
|
+
{ "name": "dayOnly", "symbols": ["theConnector", "_", "dayNumber"], "postprocess": (d) => makeDate({ day: d[2], dayOnly: true }) },
|
|
862
|
+
{ "name": "dayOnly", "symbols": ["onConnector", "_", "theConnector", "_", "dayNumber"], "postprocess": (d) => makeDate({ day: d[4], dayOnly: true }) },
|
|
788
863
|
{ "name": "specialDay", "symbols": ["today"], "postprocess": (d) => "today" },
|
|
789
864
|
{ "name": "specialDay", "symbols": ["tomorrow"], "postprocess": (d) => "tomorrow" },
|
|
790
865
|
{ "name": "specialDay", "symbols": ["yesterday"], "postprocess": (d) => "yesterday" },
|
|
@@ -793,7 +868,7 @@ var grammar = {
|
|
|
793
868
|
{ "name": "specialDay", "symbols": ["dayUnit", "_", "afterConnector", "_", "tomorrow"], "postprocess": (d) => "dayAfterTomorrow" },
|
|
794
869
|
{ "name": "specialDay", "symbols": ["theConnector", "_", "dayUnit", "_", "beforeConnector", "_", "yesterday"], "postprocess": (d) => "dayBeforeYesterday" },
|
|
795
870
|
{ "name": "specialDay", "symbols": ["dayUnit", "_", "beforeConnector", "_", "yesterday"], "postprocess": (d) => "dayBeforeYesterday" },
|
|
796
|
-
{ "name": "dayUnit", "symbols": [lexer.has("unit") ? { type: "unit" } : unit], "postprocess": (d) => d[0].value === "day" ? d[0] :
|
|
871
|
+
{ "name": "dayUnit", "symbols": [lexer.has("unit") ? { type: "unit" } : unit], "postprocess": (d, _, reject) => d[0].value === "day" ? d[0] : reject },
|
|
797
872
|
{ "name": "relativeWeekday", "symbols": ["nextRelative", "_", "weekday"], "postprocess": (d) => makeDate({ weekday: d[2], relative: "next" }) },
|
|
798
873
|
{ "name": "relativeWeekday", "symbols": ["lastRelative", "_", "weekday"], "postprocess": (d) => makeDate({ weekday: d[2], relative: "last" }) },
|
|
799
874
|
{ "name": "relativeWeekday", "symbols": ["thisRelative", "_", "weekday"], "postprocess": (d) => makeDate({ weekday: d[2], relative: "this" }) },
|
|
@@ -808,6 +883,14 @@ var grammar = {
|
|
|
808
883
|
{ "name": "monthDay", "symbols": ["theConnector", "_", "dayNumber", "_", "ofConnector", "_", "month"], "postprocess": (d) => makeDate({ month: d[6], day: d[2] }) },
|
|
809
884
|
{ "name": "monthDay", "symbols": ["month", "_", "ordinalWord"], "postprocess": (d) => makeDate({ month: d[0], day: parseOrdinalWord(d[2]) }) },
|
|
810
885
|
{ "name": "monthDay", "symbols": ["month", "_", "theConnector", "_", "dayNumber"], "postprocess": (d) => makeDate({ month: d[0], day: d[4] }) },
|
|
886
|
+
{ "name": "ordinalWeekdayOfMonth", "symbols": ["ordinalWord", "_", "weekday", "_", "ofConnector", "_", "month"], "postprocess": (d) => makeDate({ ordinalWeekday: parseOrdinalWord(d[0]), weekday: d[2], month: d[6] }) },
|
|
887
|
+
{ "name": "ordinalWeekdayOfMonth", "symbols": ["lastRelative", "_", "weekday", "_", "ofConnector", "_", "month"], "postprocess": (d) => makeDate({ ordinalWeekday: -1, weekday: d[2], month: d[6] }) },
|
|
888
|
+
{ "name": "ordinalWeekdayOfMonth", "symbols": ["ordinalWord", "_", "weekday", "_", "ofConnector", "_", "theConnector", "_", "monthUnit"], "postprocess": (d) => makeDate({ ordinalWeekday: parseOrdinalWord(d[0]), weekday: d[2], monthFromRef: true }) },
|
|
889
|
+
{ "name": "ordinalWeekdayOfMonth", "symbols": ["lastRelative", "_", "weekday", "_", "ofConnector", "_", "theConnector", "_", "monthUnit"], "postprocess": (d) => makeDate({ ordinalWeekday: -1, weekday: d[2], monthFromRef: true }) },
|
|
890
|
+
{ "name": "ordinalWeekdayOfMonth", "symbols": ["ordinalWord", "_", "dayUnit", "_", "ofConnector", "_", "month"], "postprocess": (d) => makeDate({ month: d[6], day: parseOrdinalWord(d[0]) }) },
|
|
891
|
+
{ "name": "ordinalWeekdayOfMonth", "symbols": ["lastRelative", "_", "dayUnit", "_", "ofConnector", "_", "month"], "postprocess": (d) => makeDate({ month: d[6], day: -1, lastDayOfMonth: true }) },
|
|
892
|
+
{ "name": "ordinalWeekdayOfMonth", "symbols": ["lastRelative", "_", "dayUnit", "_", "ofConnector", "_", "theConnector", "_", "monthUnit"], "postprocess": (d) => makeDate({ lastDayOfMonth: true, monthFromRef: true }) },
|
|
893
|
+
{ "name": "ordinalWeekdayOfMonth", "symbols": ["ordinalWord", "_", "dayUnit", "_", "ofConnector", "_", "nextRelative", "_", "monthUnit"], "postprocess": (d) => makeDate({ ordinalWeekday: parseOrdinalWord(d[0]), dayOfMonth: true, nextMonth: true }) },
|
|
811
894
|
{ "name": "monthDayYear", "symbols": ["monthDay", "_", "year"], "postprocess": (d) => ({ ...d[0], year: d[2] }) },
|
|
812
895
|
{ "name": "monthDayYear", "symbols": ["monthDay", lexer.has("comma") ? { type: "comma" } : comma, "_", "year"], "postprocess": (d) => ({ ...d[0], year: d[3] }) },
|
|
813
896
|
{ "name": "dateFormat", "symbols": [lexer.has("integer") ? { type: "integer" } : integer, lexer.has("dash") ? { type: "dash" } : dash, lexer.has("integer") ? { type: "integer" } : integer, lexer.has("dash") ? { type: "dash" } : dash, lexer.has("integer") ? { type: "integer" } : integer], "postprocess": (d) => {
|
|
@@ -901,6 +984,11 @@ var grammar = {
|
|
|
901
984
|
if (val === "year" || val === "years" || val === "yr" || val === "yrs") return val;
|
|
902
985
|
return reject;
|
|
903
986
|
} },
|
|
987
|
+
{ "name": "monthUnit", "symbols": [lexer.has("unit") ? { type: "unit" } : unit], "postprocess": (d, _, reject) => {
|
|
988
|
+
const val = d[0].value.toLowerCase();
|
|
989
|
+
if (val === "month" || val === "months" || val === "mo" || val === "mos") return val;
|
|
990
|
+
return reject;
|
|
991
|
+
} },
|
|
904
992
|
{ "name": "wordNumber", "symbols": [lexer.has("wordNumber") ? { type: "wordNumber" } : wordNumber], "postprocess": (d) => d[0].value },
|
|
905
993
|
{ "name": "ordinalWord", "symbols": [lexer.has("ordinalWord") ? { type: "ordinalWord" } : ordinalWord], "postprocess": (d) => d[0].value },
|
|
906
994
|
{ "name": "ordinalWord", "symbols": [lexer.has("unit") ? { type: "unit" } : unit], "postprocess": (d, _, reject) => {
|
|
@@ -937,6 +1025,9 @@ var grammar = {
|
|
|
937
1025
|
{ "name": "beginningConnector", "symbols": [lexer.has("kw_beginning") ? { type: "kw_beginning" } : kw_beginning], "postprocess": first },
|
|
938
1026
|
{ "name": "startConnector", "symbols": [lexer.has("kw_start") ? { type: "kw_start" } : kw_start], "postprocess": first },
|
|
939
1027
|
{ "name": "middleConnector", "symbols": [lexer.has("kw_middle") ? { type: "kw_middle" } : kw_middle], "postprocess": first },
|
|
1028
|
+
{ "name": "agoConnector", "symbols": [lexer.has("kw_ago") ? { type: "kw_ago" } : kw_ago], "postprocess": first },
|
|
1029
|
+
{ "name": "henceConnector", "symbols": [lexer.has("otherKeyword") ? { type: "otherKeyword" } : otherKeyword], "postprocess": (d, _, reject) => d[0].value === "hence" ? d[0] : reject },
|
|
1030
|
+
{ "name": "laterConnector", "symbols": [lexer.has("otherKeyword") ? { type: "otherKeyword" } : otherKeyword], "postprocess": (d, _, reject) => d[0].value === "later" ? d[0] : reject },
|
|
940
1031
|
{ "name": "earlyModifier", "symbols": [lexer.has("kw_early") ? { type: "kw_early" } : kw_early], "postprocess": first },
|
|
941
1032
|
{ "name": "midModifier", "symbols": [lexer.has("kw_mid") ? { type: "kw_mid" } : kw_mid], "postprocess": first },
|
|
942
1033
|
{ "name": "lateModifier", "symbols": [lexer.has("kw_late") ? { type: "kw_late" } : kw_late], "postprocess": first },
|
|
@@ -953,6 +1044,10 @@ var grammar = {
|
|
|
953
1044
|
{ "name": "now", "symbols": [lexer.has("kw_now") ? { type: "kw_now" } : kw_now], "postprocess": first },
|
|
954
1045
|
{ "name": "noon", "symbols": [lexer.has("kw_noon") ? { type: "kw_noon" } : kw_noon], "postprocess": first },
|
|
955
1046
|
{ "name": "midnight", "symbols": [lexer.has("kw_midnight") ? { type: "kw_midnight" } : kw_midnight], "postprocess": first },
|
|
1047
|
+
{ "name": "weekendKeyword", "symbols": [lexer.has("kw_weekend") ? { type: "kw_weekend" } : kw_weekend], "postprocess": first },
|
|
1048
|
+
{ "name": "tonightKeyword", "symbols": [lexer.has("kw_tonight") ? { type: "kw_tonight" } : kw_tonight], "postprocess": first },
|
|
1049
|
+
{ "name": "nightKeyword", "symbols": [lexer.has("kw_night") ? { type: "kw_night" } : kw_night], "postprocess": first },
|
|
1050
|
+
{ "name": "fortnightKeyword", "symbols": [lexer.has("kw_fortnight") ? { type: "kw_fortnight" } : kw_fortnight], "postprocess": first },
|
|
956
1051
|
{ "name": "_$ebnf$1", "symbols": [] },
|
|
957
1052
|
{ "name": "_$ebnf$1", "symbols": ["_$ebnf$1", lexer.has("ws") ? { type: "ws" } : ws], "postprocess": (d) => d[0].concat([d[1]]) },
|
|
958
1053
|
{ "name": "_", "symbols": ["_$ebnf$1"], "postprocess": nuller }
|
|
@@ -1210,6 +1305,114 @@ function convertMonthDay(node, opts) {
|
|
|
1210
1305
|
}
|
|
1211
1306
|
return date;
|
|
1212
1307
|
}
|
|
1308
|
+
function convertOrdinalWeekdayOfMonth(node, opts) {
|
|
1309
|
+
const ref = opts.referenceDate;
|
|
1310
|
+
const ordinal2 = node.ordinalWeekday;
|
|
1311
|
+
const weekdayName = node.weekday.toLowerCase();
|
|
1312
|
+
const weekdayNum = WEEKDAY_MAP[weekdayName] ?? 0;
|
|
1313
|
+
let month2;
|
|
1314
|
+
let year;
|
|
1315
|
+
if (node.monthFromRef) {
|
|
1316
|
+
month2 = ref.getUTCMonth();
|
|
1317
|
+
year = ref.getUTCFullYear();
|
|
1318
|
+
} else if (node.nextMonth) {
|
|
1319
|
+
month2 = ref.getUTCMonth() + 1;
|
|
1320
|
+
year = ref.getUTCFullYear();
|
|
1321
|
+
if (month2 > 11) {
|
|
1322
|
+
month2 = 0;
|
|
1323
|
+
year++;
|
|
1324
|
+
}
|
|
1325
|
+
} else {
|
|
1326
|
+
month2 = typeof node.month === "number" ? node.month - 1 : ref.getUTCMonth();
|
|
1327
|
+
year = ref.getUTCFullYear();
|
|
1328
|
+
if (month2 < ref.getUTCMonth()) {
|
|
1329
|
+
year++;
|
|
1330
|
+
}
|
|
1331
|
+
}
|
|
1332
|
+
if (ordinal2 === -1) {
|
|
1333
|
+
const lastDay2 = new Date(Date.UTC(year, month2 + 1, 0));
|
|
1334
|
+
let day2 = lastDay2.getUTCDate();
|
|
1335
|
+
let date2 = new Date(Date.UTC(year, month2, day2));
|
|
1336
|
+
while (date2.getUTCDay() !== weekdayNum) {
|
|
1337
|
+
day2--;
|
|
1338
|
+
date2 = new Date(Date.UTC(year, month2, day2));
|
|
1339
|
+
}
|
|
1340
|
+
return date2;
|
|
1341
|
+
}
|
|
1342
|
+
let count = 0;
|
|
1343
|
+
for (let day2 = 1; day2 <= 31; day2++) {
|
|
1344
|
+
const date2 = new Date(Date.UTC(year, month2, day2));
|
|
1345
|
+
if (date2.getUTCMonth() !== month2) {
|
|
1346
|
+
break;
|
|
1347
|
+
}
|
|
1348
|
+
if (date2.getUTCDay() === weekdayNum) {
|
|
1349
|
+
count++;
|
|
1350
|
+
if (count === ordinal2) {
|
|
1351
|
+
return date2;
|
|
1352
|
+
}
|
|
1353
|
+
}
|
|
1354
|
+
}
|
|
1355
|
+
const lastDay = new Date(Date.UTC(year, month2 + 1, 0));
|
|
1356
|
+
let day = lastDay.getUTCDate();
|
|
1357
|
+
let date = new Date(Date.UTC(year, month2, day));
|
|
1358
|
+
while (date.getUTCDay() !== weekdayNum) {
|
|
1359
|
+
day--;
|
|
1360
|
+
date = new Date(Date.UTC(year, month2, day));
|
|
1361
|
+
}
|
|
1362
|
+
return date;
|
|
1363
|
+
}
|
|
1364
|
+
function convertLastDayOfMonth(node, opts) {
|
|
1365
|
+
const ref = opts.referenceDate;
|
|
1366
|
+
let month2;
|
|
1367
|
+
let year;
|
|
1368
|
+
if (node.monthFromRef) {
|
|
1369
|
+
month2 = ref.getUTCMonth();
|
|
1370
|
+
year = ref.getUTCFullYear();
|
|
1371
|
+
} else if (node.nextMonth) {
|
|
1372
|
+
month2 = ref.getUTCMonth() + 1;
|
|
1373
|
+
year = ref.getUTCFullYear();
|
|
1374
|
+
if (month2 > 11) {
|
|
1375
|
+
month2 = 0;
|
|
1376
|
+
year++;
|
|
1377
|
+
}
|
|
1378
|
+
} else {
|
|
1379
|
+
month2 = typeof node.month === "number" ? node.month - 1 : ref.getUTCMonth();
|
|
1380
|
+
year = ref.getUTCFullYear();
|
|
1381
|
+
if (month2 < ref.getUTCMonth()) {
|
|
1382
|
+
year++;
|
|
1383
|
+
}
|
|
1384
|
+
}
|
|
1385
|
+
return new Date(Date.UTC(year, month2 + 1, 0));
|
|
1386
|
+
}
|
|
1387
|
+
function convertDayOnly(node, opts) {
|
|
1388
|
+
const ref = opts.referenceDate;
|
|
1389
|
+
const day = node.day;
|
|
1390
|
+
const refDay = ref.getUTCDate();
|
|
1391
|
+
const refMonth = ref.getUTCMonth();
|
|
1392
|
+
const refYear = ref.getUTCFullYear();
|
|
1393
|
+
let month2 = refMonth;
|
|
1394
|
+
let year = refYear;
|
|
1395
|
+
if (day < refDay) {
|
|
1396
|
+
month2 = refMonth + 1;
|
|
1397
|
+
if (month2 > 11) {
|
|
1398
|
+
month2 = 0;
|
|
1399
|
+
year++;
|
|
1400
|
+
}
|
|
1401
|
+
}
|
|
1402
|
+
let date = new Date(Date.UTC(year, month2, day));
|
|
1403
|
+
while (date.getUTCDate() !== day) {
|
|
1404
|
+
month2++;
|
|
1405
|
+
if (month2 > 11) {
|
|
1406
|
+
month2 = 0;
|
|
1407
|
+
year++;
|
|
1408
|
+
}
|
|
1409
|
+
date = new Date(Date.UTC(year, month2, day));
|
|
1410
|
+
}
|
|
1411
|
+
if (node.time) {
|
|
1412
|
+
applyTime(date, node.time);
|
|
1413
|
+
}
|
|
1414
|
+
return date;
|
|
1415
|
+
}
|
|
1213
1416
|
function convertRelativePeriod(node, opts) {
|
|
1214
1417
|
const ref = opts.referenceDate;
|
|
1215
1418
|
const period = node.period.toLowerCase();
|
|
@@ -1269,6 +1472,9 @@ function convertDateNode(node, opts) {
|
|
|
1269
1472
|
if (node.timeOnly && node.time) {
|
|
1270
1473
|
return convertTimeOnly(node, opts);
|
|
1271
1474
|
}
|
|
1475
|
+
if (node.ordinalWeekday !== void 0 && node.weekday !== void 0) {
|
|
1476
|
+
return convertOrdinalWeekdayOfMonth(node, opts);
|
|
1477
|
+
}
|
|
1272
1478
|
if (node.weekday) {
|
|
1273
1479
|
return convertWeekday(node, opts);
|
|
1274
1480
|
}
|
|
@@ -1278,6 +1484,23 @@ function convertDateNode(node, opts) {
|
|
|
1278
1484
|
if (node.month !== void 0 && node.day !== void 0) {
|
|
1279
1485
|
return convertMonthDay(node, opts);
|
|
1280
1486
|
}
|
|
1487
|
+
if (node.dayOnly && node.day !== void 0) {
|
|
1488
|
+
return convertDayOnly(node, opts);
|
|
1489
|
+
}
|
|
1490
|
+
if (node.lastDayOfMonth) {
|
|
1491
|
+
return convertLastDayOfMonth(node, opts);
|
|
1492
|
+
}
|
|
1493
|
+
if (node.dayOfMonth && node.nextMonth) {
|
|
1494
|
+
const ref = opts.referenceDate;
|
|
1495
|
+
let month2 = ref.getUTCMonth() + 1;
|
|
1496
|
+
let year = ref.getUTCFullYear();
|
|
1497
|
+
if (month2 > 11) {
|
|
1498
|
+
month2 = 0;
|
|
1499
|
+
year++;
|
|
1500
|
+
}
|
|
1501
|
+
const day = node.ordinalWeekday || 1;
|
|
1502
|
+
return new Date(Date.UTC(year, month2, day));
|
|
1503
|
+
}
|
|
1281
1504
|
if (node.relative && node.period) {
|
|
1282
1505
|
return convertRelativePeriod(node, opts);
|
|
1283
1506
|
}
|
|
@@ -1349,7 +1572,7 @@ function getHalfDates(half2, year, fiscalYearStart) {
|
|
|
1349
1572
|
const start = new Date(Date.UTC(startYear, halfStartMonth, 1));
|
|
1350
1573
|
const endMonth = (halfStartMonth + 6) % 12;
|
|
1351
1574
|
let endYear = startYear;
|
|
1352
|
-
if (endMonth
|
|
1575
|
+
if (endMonth <= halfStartMonth) {
|
|
1353
1576
|
endYear++;
|
|
1354
1577
|
}
|
|
1355
1578
|
const end = new Date(Date.UTC(endYear, endMonth, 0));
|
|
@@ -1422,8 +1645,115 @@ function getModifiedPeriod(start, end, modifier) {
|
|
|
1422
1645
|
}
|
|
1423
1646
|
|
|
1424
1647
|
// src/converters/fuzzy.ts
|
|
1648
|
+
function getWeekendDates(ref, relative, opts) {
|
|
1649
|
+
const currentDay = ref.getUTCDay();
|
|
1650
|
+
const saturdayOffset = (6 - currentDay + 7) % 7;
|
|
1651
|
+
let saturday = new Date(
|
|
1652
|
+
Date.UTC(
|
|
1653
|
+
ref.getUTCFullYear(),
|
|
1654
|
+
ref.getUTCMonth(),
|
|
1655
|
+
ref.getUTCDate() + saturdayOffset
|
|
1656
|
+
)
|
|
1657
|
+
);
|
|
1658
|
+
if (relative === "next") {
|
|
1659
|
+
saturday = new Date(saturday.getTime() + MS_PER_WEEK);
|
|
1660
|
+
} else if (relative === "last") {
|
|
1661
|
+
if (currentDay === 6 || currentDay === 0) {
|
|
1662
|
+
saturday = new Date(saturday.getTime() - MS_PER_WEEK);
|
|
1663
|
+
}
|
|
1664
|
+
saturday = new Date(saturday.getTime() - MS_PER_WEEK);
|
|
1665
|
+
}
|
|
1666
|
+
const sunday = new Date(saturday.getTime() + MS_PER_DAY);
|
|
1667
|
+
const sundayEnd = new Date(
|
|
1668
|
+
Date.UTC(
|
|
1669
|
+
sunday.getUTCFullYear(),
|
|
1670
|
+
sunday.getUTCMonth(),
|
|
1671
|
+
sunday.getUTCDate(),
|
|
1672
|
+
23,
|
|
1673
|
+
59
|
|
1674
|
+
)
|
|
1675
|
+
);
|
|
1676
|
+
return { start: saturday, end: sundayEnd };
|
|
1677
|
+
}
|
|
1678
|
+
function getNightDates(ref, relative, weekday2) {
|
|
1679
|
+
let baseDate = new Date(ref);
|
|
1680
|
+
if (relative === "last") {
|
|
1681
|
+
baseDate = new Date(
|
|
1682
|
+
Date.UTC(
|
|
1683
|
+
ref.getUTCFullYear(),
|
|
1684
|
+
ref.getUTCMonth(),
|
|
1685
|
+
ref.getUTCDate() - 1
|
|
1686
|
+
)
|
|
1687
|
+
);
|
|
1688
|
+
} else if (relative === "tomorrow") {
|
|
1689
|
+
baseDate = new Date(
|
|
1690
|
+
Date.UTC(
|
|
1691
|
+
ref.getUTCFullYear(),
|
|
1692
|
+
ref.getUTCMonth(),
|
|
1693
|
+
ref.getUTCDate() + 1
|
|
1694
|
+
)
|
|
1695
|
+
);
|
|
1696
|
+
} else if (weekday2) {
|
|
1697
|
+
const targetDay = WEEKDAY_MAP[weekday2.toLowerCase()];
|
|
1698
|
+
if (targetDay !== void 0) {
|
|
1699
|
+
const currentDay = ref.getUTCDay();
|
|
1700
|
+
let daysToAdd = (targetDay - currentDay + 7) % 7;
|
|
1701
|
+
if (daysToAdd === 0) {
|
|
1702
|
+
daysToAdd = 7;
|
|
1703
|
+
}
|
|
1704
|
+
baseDate = new Date(
|
|
1705
|
+
Date.UTC(
|
|
1706
|
+
ref.getUTCFullYear(),
|
|
1707
|
+
ref.getUTCMonth(),
|
|
1708
|
+
ref.getUTCDate() + daysToAdd
|
|
1709
|
+
)
|
|
1710
|
+
);
|
|
1711
|
+
}
|
|
1712
|
+
}
|
|
1713
|
+
const start = new Date(
|
|
1714
|
+
Date.UTC(
|
|
1715
|
+
baseDate.getUTCFullYear(),
|
|
1716
|
+
baseDate.getUTCMonth(),
|
|
1717
|
+
baseDate.getUTCDate(),
|
|
1718
|
+
18,
|
|
1719
|
+
0
|
|
1720
|
+
)
|
|
1721
|
+
);
|
|
1722
|
+
const end = new Date(
|
|
1723
|
+
Date.UTC(
|
|
1724
|
+
baseDate.getUTCFullYear(),
|
|
1725
|
+
baseDate.getUTCMonth(),
|
|
1726
|
+
baseDate.getUTCDate(),
|
|
1727
|
+
23,
|
|
1728
|
+
59
|
|
1729
|
+
)
|
|
1730
|
+
);
|
|
1731
|
+
return { start, end };
|
|
1732
|
+
}
|
|
1425
1733
|
function getBasePeriodDates(node, opts, year) {
|
|
1426
1734
|
const ref = opts.referenceDate;
|
|
1735
|
+
if (node.period === "weekend") {
|
|
1736
|
+
return getWeekendDates(ref, node.relative || "this", opts);
|
|
1737
|
+
}
|
|
1738
|
+
if (node.period === "tonight") {
|
|
1739
|
+
return getNightDates(ref, void 0, void 0);
|
|
1740
|
+
}
|
|
1741
|
+
if (node.period === "night") {
|
|
1742
|
+
return getNightDates(ref, node.relative, node.weekday);
|
|
1743
|
+
}
|
|
1744
|
+
if (node.period === "fortnight") {
|
|
1745
|
+
const count = node.count || 1;
|
|
1746
|
+
const relative = node.relative;
|
|
1747
|
+
const twoWeeks = 14 * MS_PER_DAY;
|
|
1748
|
+
if (relative === "last") {
|
|
1749
|
+
const end2 = new Date(ref);
|
|
1750
|
+
const start2 = new Date(ref.getTime() - twoWeeks);
|
|
1751
|
+
return { start: start2, end: end2 };
|
|
1752
|
+
}
|
|
1753
|
+
const start = new Date(ref);
|
|
1754
|
+
const end = new Date(ref.getTime() + count * twoWeeks);
|
|
1755
|
+
return { start, end };
|
|
1756
|
+
}
|
|
1427
1757
|
if (node.period === "quarter" && node.quarter) {
|
|
1428
1758
|
return getQuarterDates(
|
|
1429
1759
|
node.quarter,
|
|
@@ -1586,7 +1916,7 @@ function convertASTToResult(ast, opts, originalInput) {
|
|
|
1586
1916
|
end = new Date(Date.UTC(year, month2 + 1, 0));
|
|
1587
1917
|
}
|
|
1588
1918
|
if (endNode.yearOnly) {
|
|
1589
|
-
const year = endNode.year;
|
|
1919
|
+
const year = endNode.year ?? opts.referenceDate.getUTCFullYear();
|
|
1590
1920
|
end = new Date(Date.UTC(year, 11, 31));
|
|
1591
1921
|
}
|
|
1592
1922
|
} else if (endNode.nodeType === "fuzzy") {
|
|
@@ -1617,6 +1947,7 @@ function convertASTToResult(ast, opts, originalInput) {
|
|
|
1617
1947
|
case "fuzzy": {
|
|
1618
1948
|
const { start, end } = convertFuzzyNode(expression, opts);
|
|
1619
1949
|
const mod = expression.modifier;
|
|
1950
|
+
const period = expression.period;
|
|
1620
1951
|
if (mod === "start" || mod === "beginning") {
|
|
1621
1952
|
const periodDates = convertFuzzyNodeWithoutModifier(expression, opts);
|
|
1622
1953
|
return { type: "date", date: periodDates.start, title };
|
|
@@ -1625,6 +1956,10 @@ function convertASTToResult(ast, opts, originalInput) {
|
|
|
1625
1956
|
const periodDates = convertFuzzyNodeWithoutModifier(expression, opts);
|
|
1626
1957
|
return { type: "date", date: periodDates.end, title };
|
|
1627
1958
|
}
|
|
1959
|
+
if (period === "weekend" || period === "night" || period === "tonight" || period === "fortnight") {
|
|
1960
|
+
const duration = end.getTime() - start.getTime();
|
|
1961
|
+
return { type: "span", start, end, duration, title };
|
|
1962
|
+
}
|
|
1628
1963
|
return { type: "fuzzy", start, end, approximate: true, title };
|
|
1629
1964
|
}
|
|
1630
1965
|
case "relative": {
|
|
@@ -1641,6 +1976,81 @@ function convertASTToResult(ast, opts, originalInput) {
|
|
|
1641
1976
|
}
|
|
1642
1977
|
return { type: "span", start, end, duration, title };
|
|
1643
1978
|
}
|
|
1979
|
+
case "relativeDate": {
|
|
1980
|
+
const durationNode = expression.duration;
|
|
1981
|
+
const baseNode = expression.baseDate;
|
|
1982
|
+
const timeSpec = expression.time;
|
|
1983
|
+
let baseDate;
|
|
1984
|
+
if (baseNode) {
|
|
1985
|
+
baseDate = convertDateNode(baseNode, opts);
|
|
1986
|
+
} else {
|
|
1987
|
+
baseDate = new Date(opts.referenceDate);
|
|
1988
|
+
}
|
|
1989
|
+
const durationValue = durationNode.value;
|
|
1990
|
+
const durationUnit = durationNode.unit;
|
|
1991
|
+
const direction = expression.direction === "past" ? -1 : 1;
|
|
1992
|
+
let resultDate;
|
|
1993
|
+
if (durationUnit === "month") {
|
|
1994
|
+
resultDate = new Date(
|
|
1995
|
+
Date.UTC(
|
|
1996
|
+
baseDate.getUTCFullYear(),
|
|
1997
|
+
baseDate.getUTCMonth() + direction * durationValue,
|
|
1998
|
+
baseDate.getUTCDate(),
|
|
1999
|
+
baseDate.getUTCHours(),
|
|
2000
|
+
baseDate.getUTCMinutes()
|
|
2001
|
+
)
|
|
2002
|
+
);
|
|
2003
|
+
} else if (durationUnit === "year") {
|
|
2004
|
+
resultDate = new Date(
|
|
2005
|
+
Date.UTC(
|
|
2006
|
+
baseDate.getUTCFullYear() + direction * durationValue,
|
|
2007
|
+
baseDate.getUTCMonth(),
|
|
2008
|
+
baseDate.getUTCDate(),
|
|
2009
|
+
baseDate.getUTCHours(),
|
|
2010
|
+
baseDate.getUTCMinutes()
|
|
2011
|
+
)
|
|
2012
|
+
);
|
|
2013
|
+
} else {
|
|
2014
|
+
const durationMs = convertDurationNode(durationNode);
|
|
2015
|
+
resultDate = new Date(baseDate.getTime() + direction * durationMs);
|
|
2016
|
+
}
|
|
2017
|
+
if (timeSpec) {
|
|
2018
|
+
if ("special" in timeSpec) {
|
|
2019
|
+
if (timeSpec.special === "noon") {
|
|
2020
|
+
resultDate = new Date(
|
|
2021
|
+
Date.UTC(
|
|
2022
|
+
resultDate.getUTCFullYear(),
|
|
2023
|
+
resultDate.getUTCMonth(),
|
|
2024
|
+
resultDate.getUTCDate(),
|
|
2025
|
+
12,
|
|
2026
|
+
0
|
|
2027
|
+
)
|
|
2028
|
+
);
|
|
2029
|
+
} else if (timeSpec.special === "midnight") {
|
|
2030
|
+
resultDate = new Date(
|
|
2031
|
+
Date.UTC(
|
|
2032
|
+
resultDate.getUTCFullYear(),
|
|
2033
|
+
resultDate.getUTCMonth(),
|
|
2034
|
+
resultDate.getUTCDate(),
|
|
2035
|
+
0,
|
|
2036
|
+
0
|
|
2037
|
+
)
|
|
2038
|
+
);
|
|
2039
|
+
}
|
|
2040
|
+
} else {
|
|
2041
|
+
resultDate = new Date(
|
|
2042
|
+
Date.UTC(
|
|
2043
|
+
resultDate.getUTCFullYear(),
|
|
2044
|
+
resultDate.getUTCMonth(),
|
|
2045
|
+
resultDate.getUTCDate(),
|
|
2046
|
+
timeSpec.hour,
|
|
2047
|
+
timeSpec.minute
|
|
2048
|
+
)
|
|
2049
|
+
);
|
|
2050
|
+
}
|
|
2051
|
+
}
|
|
2052
|
+
return { type: "date", date: resultDate, title };
|
|
2053
|
+
}
|
|
1644
2054
|
default:
|
|
1645
2055
|
return null;
|
|
1646
2056
|
}
|
|
@@ -1663,13 +2073,13 @@ function stripUnmatchedPunctuation(input) {
|
|
|
1663
2073
|
openParens = (result.match(/\(/g) || []).length;
|
|
1664
2074
|
closeParens = (result.match(/\)/g) || []).length;
|
|
1665
2075
|
while (openParens > closeParens) {
|
|
1666
|
-
result = result.replace(
|
|
2076
|
+
result = result.replace(/\(/, "");
|
|
1667
2077
|
openParens--;
|
|
1668
2078
|
}
|
|
1669
2079
|
openBrackets = (result.match(/\[/g) || []).length;
|
|
1670
2080
|
closeBrackets = (result.match(/]/g) || []).length;
|
|
1671
2081
|
while (openBrackets > closeBrackets) {
|
|
1672
|
-
result = result.replace(
|
|
2082
|
+
result = result.replace(/\[/, "");
|
|
1673
2083
|
openBrackets--;
|
|
1674
2084
|
}
|
|
1675
2085
|
return {
|