-
Notifications
You must be signed in to change notification settings - Fork 47
/
Copy pathparser.ts
133 lines (112 loc) · 3.44 KB
/
parser.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
import chrono, { Chrono, Parser } from "chrono-node";
import type { Moment } from "moment";
import { DayOfWeek } from "./settings";
import {
ORDINAL_NUMBER_PATTERN,
getLastDayOfMonth,
getLocaleWeekStart,
getWeekNumber,
parseOrdinalNumberPattern,
} from "./utils";
export interface NLDResult {
formattedString: string;
date: Date;
moment: Moment;
}
function getLocalizedChrono(): Chrono {
const locale = window.moment.locale();
switch (locale) {
case "en-gb":
return new Chrono(chrono.en.createCasualConfiguration(true));
default:
return new Chrono(chrono.en.createCasualConfiguration(false));
}
}
function getConfiguredChrono(): Chrono {
const localizedChrono = getLocalizedChrono();
localizedChrono.parsers.push({
pattern: () => {
return /\bChristmas\b/i;
},
extract: () => {
return {
day: 25,
month: 12,
};
},
});
localizedChrono.parsers.push({
pattern: () => new RegExp(ORDINAL_NUMBER_PATTERN),
extract: (_context, match) => {
return {
day: parseOrdinalNumberPattern(match[0]),
month: window.moment().month(),
};
},
} as Parser);
return localizedChrono;
}
export default class NLDParser {
chrono: Chrono;
constructor() {
this.chrono = getConfiguredChrono();
}
getParsedDate(selectedText: string, weekStartPreference: DayOfWeek): Date {
const parser = this.chrono;
const initialParse = parser.parse(selectedText);
const weekdayIsCertain = initialParse[0]?.start.isCertain("weekday");
const weekStart =
weekStartPreference === "locale-default"
? getLocaleWeekStart()
: weekStartPreference;
const locale = {
weekStart: getWeekNumber(weekStart),
};
const thisDateMatch = selectedText.match(/this\s([\w]+)/i);
const nextDateMatch = selectedText.match(/next\s([\w]+)/i);
const lastDayOfMatch = selectedText.match(/(last day of|end of)\s*([^\n\r]*)/i);
const midOf = selectedText.match(/mid\s([\w]+)/i);
const referenceDate = weekdayIsCertain
? window.moment().weekday(0).toDate()
: new Date();
if (thisDateMatch && thisDateMatch[1] === "week") {
return parser.parseDate(`this ${weekStart}`, referenceDate);
}
if (nextDateMatch && nextDateMatch[1] === "week") {
return parser.parseDate(`next ${weekStart}`, referenceDate, {
forwardDate: true,
});
}
if (nextDateMatch && nextDateMatch[1] === "month") {
const thisMonth = parser.parseDate("this month", new Date(), {
forwardDate: true,
});
return parser.parseDate(selectedText, thisMonth, {
forwardDate: true,
});
}
if (nextDateMatch && nextDateMatch[1] === "year") {
const thisYear = parser.parseDate("this year", new Date(), {
forwardDate: true,
});
return parser.parseDate(selectedText, thisYear, {
forwardDate: true,
});
}
if (lastDayOfMatch) {
const tempDate = parser.parse(lastDayOfMatch[2]);
const year = tempDate[0].start.get("year");
const month = tempDate[0].start.get("month");
const lastDay = getLastDayOfMonth(year, month);
return parser.parseDate(`${year}-${month}-${lastDay}`, new Date(), {
forwardDate: true,
});
}
if (midOf) {
return parser.parseDate(`${midOf[1]} 15th`, new Date(), {
forwardDate: true,
});
}
return parser.parseDate(selectedText, referenceDate, { locale });
}
}