chronolizer 0.1.0 → 0.3.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/README.md +184 -119
- package/dist/ast/constructors.d.mts +135 -0
- package/dist/ast/constructors.mjs +25 -0
- package/dist/ast/fold.d.mts +13 -0
- package/dist/ast/fold.mjs +58 -0
- package/dist/ast/normalize.d.mts +42 -0
- package/dist/ast/normalize.mjs +34 -0
- package/dist/ast/schemas.d.mts +80 -0
- package/dist/ast/schemas.mjs +65 -0
- package/dist/filter/codec.d.mts +92 -0
- package/dist/filter/codec.mjs +48 -0
- package/dist/filter/errors.d.mts +14 -0
- package/dist/filter/errors.mjs +10 -0
- package/dist/filter/expression.d.mts +8 -0
- package/dist/filter/expression.mjs +76 -0
- package/dist/filter/schema.d.mts +13 -0
- package/dist/filter/schema.mjs +11 -0
- package/dist/filter/transformation.d.mts +37 -0
- package/dist/filter/transformation.mjs +20 -0
- package/dist/index.d.mts +22 -969
- package/dist/index.mjs +22 -2305
- package/dist/language/errors.d.mts +38 -0
- package/dist/language/errors.mjs +30 -0
- package/dist/language/model.d.mts +239 -0
- package/dist/language/model.mjs +50 -0
- package/dist/language/registry.d.mts +17 -0
- package/dist/language/registry.mjs +116 -0
- package/dist/locales/cs.d.mts +10 -0
- package/dist/locales/cs.mjs +746 -0
- package/dist/locales/de.d.mts +10 -0
- package/dist/locales/de.mjs +1039 -0
- package/dist/locales/en.d.mts +10 -0
- package/dist/locales/en.mjs +598 -0
- package/dist/locales/es.d.mts +10 -0
- package/dist/locales/es.mjs +908 -0
- package/dist/locales/fr.d.mts +10 -0
- package/dist/locales/fr.mjs +901 -0
- package/dist/locales/nl.d.mts +10 -0
- package/dist/locales/nl.mjs +791 -0
- package/dist/locales/pl.d.mts +10 -0
- package/dist/locales/pl.mjs +885 -0
- package/dist/locales/shared.mjs +395 -0
- package/dist/locales/tr.d.mts +10 -0
- package/dist/locales/tr.mjs +725 -0
- package/dist/natural/correction.d.mts +13 -0
- package/dist/natural/correction.mjs +73 -0
- package/dist/natural/format.d.mts +47 -0
- package/dist/natural/format.mjs +14 -0
- package/dist/natural/parse.d.mts +99 -0
- package/dist/natural/parse.mjs +66 -0
- package/dist/natural/policy.mjs +6 -0
- package/dist/natural/suggest.d.mts +53 -0
- package/dist/natural/suggest.mjs +24 -0
- package/dist/natural/suggestion.d.mts +4 -0
- package/dist/natural/suggestion.mjs +79 -0
- package/dist/natural/text.d.mts +5 -0
- package/dist/natural/text.mjs +5 -0
- package/dist/resolve/resolve.d.mts +79 -0
- package/dist/resolve/resolve.mjs +58 -0
- package/dist/resolve/schema.d.mts +59 -0
- package/dist/resolve/schema.mjs +28 -0
- package/package.json +15 -3
|
@@ -0,0 +1,395 @@
|
|
|
1
|
+
import { GreaterThanOrEqual, InstantExpr, LessThan, LessThanOrEqual, Now, Shift, StartOf, Unit, daysInMonth, isIsoDate } from "../ast/schemas.mjs";
|
|
2
|
+
import { boundedRange, dateLiteral, greaterThanOrEqual, lessThan, lessThanOrEqual, lowerOpenRange, now, shift, startOf, upperOpenRange } from "../ast/constructors.mjs";
|
|
3
|
+
import { formatInstantExpression } from "../filter/expression.mjs";
|
|
4
|
+
import { formatFilter, rangeKey } from "../filter/codec.mjs";
|
|
5
|
+
import { NaturalCandidate } from "../language/model.mjs";
|
|
6
|
+
import { Match, Option, RegExp as RegExp$1, Schema, String as String$1 } from "effect";
|
|
7
|
+
//#region src/locales/shared.ts
|
|
8
|
+
const textAt = (values, index) => values[index] ?? "";
|
|
9
|
+
const Period = Schema.Struct({
|
|
10
|
+
start: InstantExpr,
|
|
11
|
+
end: InstantExpr,
|
|
12
|
+
canonical: Schema.String
|
|
13
|
+
});
|
|
14
|
+
const isGreaterThanOrEqual = Schema.is(GreaterThanOrEqual);
|
|
15
|
+
const isLessThan = Schema.is(LessThan);
|
|
16
|
+
const isLessThanOrEqual = Schema.is(LessThanOrEqual);
|
|
17
|
+
const isNow = Schema.is(Now);
|
|
18
|
+
const isShift = Schema.is(Shift);
|
|
19
|
+
const isStartOf = Schema.is(StartOf);
|
|
20
|
+
const periodRange = (period) => boundedRange(greaterThanOrEqual(period.start), lessThan(period.end));
|
|
21
|
+
const periodToDateRange = (unit) => boundedRange(greaterThanOrEqual(startOf(now(), unit)), lessThanOrEqual(now()));
|
|
22
|
+
const fromNowRange = () => lowerOpenRange(greaterThanOrEqual(now()));
|
|
23
|
+
const untilNowRange = () => upperOpenRange(lessThanOrEqual(now()));
|
|
24
|
+
const remainingPeriodRange = (unit) => {
|
|
25
|
+
const start = startOf(now(), unit);
|
|
26
|
+
return boundedRange(greaterThanOrEqual(now()), lessThan(shift(start, 1, unit)));
|
|
27
|
+
};
|
|
28
|
+
const periodStartDay = (period, canonical) => Period.make({
|
|
29
|
+
start: period.start,
|
|
30
|
+
end: shift(period.start, 1, "day"),
|
|
31
|
+
canonical
|
|
32
|
+
});
|
|
33
|
+
const periodEndDay = (period, canonical) => Period.make({
|
|
34
|
+
start: shift(period.end, -1, "day"),
|
|
35
|
+
end: period.end,
|
|
36
|
+
canonical
|
|
37
|
+
});
|
|
38
|
+
const periodDay = (period, day, canonical) => {
|
|
39
|
+
if (!Number.isInteger(day) || day < 1 || day > 28) return Option.none();
|
|
40
|
+
const start = day === 1 ? period.start : shift(period.start, day - 1, "day");
|
|
41
|
+
return Option.some(Period.make({
|
|
42
|
+
start,
|
|
43
|
+
end: shift(start, 1, "day"),
|
|
44
|
+
canonical
|
|
45
|
+
}));
|
|
46
|
+
};
|
|
47
|
+
const periodPreviousDay = (period, canonical) => Period.make({
|
|
48
|
+
start: shift(period.start, -1, "day"),
|
|
49
|
+
end: period.start,
|
|
50
|
+
canonical
|
|
51
|
+
});
|
|
52
|
+
const relativeWeekend = (direction, canonical) => {
|
|
53
|
+
const weekBase = direction === 0 ? now() : shift(now(), direction, "week");
|
|
54
|
+
const weekStart = startOf(weekBase, "week");
|
|
55
|
+
const start = shift(weekStart, 5, "day");
|
|
56
|
+
return Period.make({
|
|
57
|
+
start,
|
|
58
|
+
end: shift(start, 2, "day"),
|
|
59
|
+
canonical
|
|
60
|
+
});
|
|
61
|
+
};
|
|
62
|
+
const TrailingCount = Schema.Int.check(Schema.isBetween({
|
|
63
|
+
minimum: 1,
|
|
64
|
+
maximum: Number.MAX_SAFE_INTEGER
|
|
65
|
+
}));
|
|
66
|
+
const CountedPeriod = Schema.Struct({
|
|
67
|
+
amount: TrailingCount,
|
|
68
|
+
unit: Unit
|
|
69
|
+
});
|
|
70
|
+
const CalendarPeriodOffset = Schema.Struct({
|
|
71
|
+
amount: Schema.Int,
|
|
72
|
+
unit: Unit
|
|
73
|
+
});
|
|
74
|
+
const validYear = (value) => {
|
|
75
|
+
const year = Number(value);
|
|
76
|
+
return Number.isInteger(year) && year >= 1 && year <= 9998 ? year : void 0;
|
|
77
|
+
};
|
|
78
|
+
const parseTrailingCount = (value) => {
|
|
79
|
+
const amount = Number(value);
|
|
80
|
+
return Schema.is(TrailingCount)(amount) ? Option.some(amount) : Option.none();
|
|
81
|
+
};
|
|
82
|
+
const trailingRange = (amount, unit) => boundedRange(greaterThanOrEqual(shift(now(), -amount, unit)), lessThanOrEqual(now()));
|
|
83
|
+
const futureRange = (amount, unit) => boundedRange(greaterThanOrEqual(now()), lessThanOrEqual(shift(now(), amount, unit)));
|
|
84
|
+
const trailingPeriod = (range) => {
|
|
85
|
+
if (!isGreaterThanOrEqual(range.lower) || !isLessThanOrEqual(range.upper)) return Option.none();
|
|
86
|
+
if (!isShift(range.lower.value) || range.lower.value.amount >= 0 || !isNow(range.lower.value.base) || !isNow(range.upper.value)) return Option.none();
|
|
87
|
+
return Option.some(CountedPeriod.make({
|
|
88
|
+
amount: -range.lower.value.amount,
|
|
89
|
+
unit: range.lower.value.unit
|
|
90
|
+
}));
|
|
91
|
+
};
|
|
92
|
+
const futurePeriod = (range) => {
|
|
93
|
+
if (!isGreaterThanOrEqual(range.lower) || !isLessThanOrEqual(range.upper)) return Option.none();
|
|
94
|
+
if (!isNow(range.lower.value) || !isShift(range.upper.value) || range.upper.value.amount <= 0 || !isNow(range.upper.value.base)) return Option.none();
|
|
95
|
+
return Option.some(CountedPeriod.make({
|
|
96
|
+
amount: range.upper.value.amount,
|
|
97
|
+
unit: range.upper.value.unit
|
|
98
|
+
}));
|
|
99
|
+
};
|
|
100
|
+
const relativePeriod = (unit, direction, canonical) => {
|
|
101
|
+
const base = direction === 0 ? now() : shift(now(), direction, unit);
|
|
102
|
+
const start = startOf(base, unit);
|
|
103
|
+
return Period.make({
|
|
104
|
+
start,
|
|
105
|
+
end: shift(start, 1, unit),
|
|
106
|
+
canonical
|
|
107
|
+
});
|
|
108
|
+
};
|
|
109
|
+
const pad = (value) => String(value).padStart(2, "0");
|
|
110
|
+
const isoDate = (year, month, day) => `${String(year).padStart(4, "0")}-${pad(month)}-${pad(day)}`;
|
|
111
|
+
const nextDay = (year, month, day) => {
|
|
112
|
+
if (day < daysInMonth(year, month)) return isoDate(year, month, day + 1);
|
|
113
|
+
if (month < 12) return isoDate(year, month + 1, 1);
|
|
114
|
+
return isoDate(year + 1, 1, 1);
|
|
115
|
+
};
|
|
116
|
+
const previousDay = (year, month, day) => {
|
|
117
|
+
if (day > 1) return isoDate(year, month, day - 1);
|
|
118
|
+
if (month > 1) return isoDate(year, month - 1, daysInMonth(year, month - 1));
|
|
119
|
+
return isoDate(year - 1, 12, 31);
|
|
120
|
+
};
|
|
121
|
+
const absoluteDateProfiles = /* @__PURE__ */ new Map();
|
|
122
|
+
const absoluteDateProfile = (locale) => {
|
|
123
|
+
const cached = absoluteDateProfiles.get(locale);
|
|
124
|
+
if (cached !== void 0) return cached;
|
|
125
|
+
const formatter = new Intl.DateTimeFormat(locale, {
|
|
126
|
+
day: "numeric",
|
|
127
|
+
month: "numeric",
|
|
128
|
+
year: "numeric",
|
|
129
|
+
numberingSystem: "latn",
|
|
130
|
+
timeZone: "UTC"
|
|
131
|
+
});
|
|
132
|
+
const parts = [];
|
|
133
|
+
const pattern = formatter.formatToParts(/* @__PURE__ */ new Date("2006-11-22T00:00:00.000Z")).map((part) => {
|
|
134
|
+
if (part.type === "day" || part.type === "month" || part.type === "year") {
|
|
135
|
+
parts.push(part.type);
|
|
136
|
+
return part.type === "year" ? "([0-9]{4})" : "([0-9]{1,2})";
|
|
137
|
+
}
|
|
138
|
+
return RegExp$1.escape(part.value);
|
|
139
|
+
}).join("");
|
|
140
|
+
const profile = {
|
|
141
|
+
formatter,
|
|
142
|
+
pattern: new RegExp(`^${pattern}$`, "u"),
|
|
143
|
+
parts
|
|
144
|
+
};
|
|
145
|
+
absoluteDateProfiles.set(locale, profile);
|
|
146
|
+
return profile;
|
|
147
|
+
};
|
|
148
|
+
const formatAbsoluteDate = (value, locale) => absoluteDateProfile(locale).formatter.format(/* @__PURE__ */ new Date(`${value}T00:00:00.000Z`));
|
|
149
|
+
const parseLocalizedAbsoluteDate = (input, locale) => {
|
|
150
|
+
const profile = absoluteDateProfile(locale);
|
|
151
|
+
const match = String$1.match(profile.pattern)(input);
|
|
152
|
+
if (Option.isNone(match)) return Option.none();
|
|
153
|
+
let day = "";
|
|
154
|
+
let month = "";
|
|
155
|
+
let year = "";
|
|
156
|
+
for (const [index, part] of profile.parts.entries()) {
|
|
157
|
+
const value = textAt(match.value, index + 1);
|
|
158
|
+
if (part === "day") day = value;
|
|
159
|
+
if (part === "month") month = value;
|
|
160
|
+
if (part === "year") year = value;
|
|
161
|
+
}
|
|
162
|
+
const value = isoDate(Number(year), Number(month), Number(day));
|
|
163
|
+
return isIsoDate(value) ? Option.some(value) : Option.none();
|
|
164
|
+
};
|
|
165
|
+
const fixedDatePeriod = (value, canonical) => {
|
|
166
|
+
const year = Number(value.slice(0, 4));
|
|
167
|
+
const month = Number(value.slice(5, 7));
|
|
168
|
+
const day = Number(value.slice(8, 10));
|
|
169
|
+
return Period.make({
|
|
170
|
+
start: dateLiteral(value),
|
|
171
|
+
end: dateLiteral(nextDay(year, month, day)),
|
|
172
|
+
canonical
|
|
173
|
+
});
|
|
174
|
+
};
|
|
175
|
+
const absoluteDatePeriod = (input, locale) => {
|
|
176
|
+
return (isIsoDate(input) ? Option.some(input) : parseLocalizedAbsoluteDate(input, locale)).pipe(Option.filter((date) => date !== "9999-12-31"), Option.map((date) => fixedDatePeriod(date, formatAbsoluteDate(date, locale))));
|
|
177
|
+
};
|
|
178
|
+
const namedDatePeriod = (yearText, monthText, dayText, monthNumber, canonical) => {
|
|
179
|
+
const year = validYear(yearText);
|
|
180
|
+
const month = monthNumber(monthText);
|
|
181
|
+
const day = Number(dayText);
|
|
182
|
+
if (year === void 0 || month === void 0) return Option.none();
|
|
183
|
+
const value = isoDate(year, month, day);
|
|
184
|
+
if (!isIsoDate(value) || value === "9999-12-31") return Option.none();
|
|
185
|
+
return Option.some(fixedDatePeriod(value, canonical(day, month, year)));
|
|
186
|
+
};
|
|
187
|
+
const minimumDaysInMonth = (month) => daysInMonth(1, month);
|
|
188
|
+
const currentYearDatePeriod = (month, day, canonical) => {
|
|
189
|
+
const yearStart = startOf(now(), "year");
|
|
190
|
+
const monthStart = month === 1 ? yearStart : shift(yearStart, month - 1, "month");
|
|
191
|
+
const start = day === 1 ? monthStart : shift(monthStart, day - 1, "day");
|
|
192
|
+
return Period.make({
|
|
193
|
+
start,
|
|
194
|
+
end: shift(start, 1, "day"),
|
|
195
|
+
canonical
|
|
196
|
+
});
|
|
197
|
+
};
|
|
198
|
+
const namedCurrentYearDatePeriod = (monthText, dayText, monthNumber, canonical) => {
|
|
199
|
+
const month = monthNumber(monthText);
|
|
200
|
+
const day = Number(dayText);
|
|
201
|
+
if (month === void 0 || !Number.isInteger(day) || day < 1 || day > minimumDaysInMonth(month)) return Option.none();
|
|
202
|
+
return Option.some(currentYearDatePeriod(month, day, canonical(day, month)));
|
|
203
|
+
};
|
|
204
|
+
const currentYearDate = (expression) => {
|
|
205
|
+
const match = String$1.match(/^now\/y(?:\+([1-9]\d*)M)?(?:\+([1-9]\d*)d)?$/u)(expression);
|
|
206
|
+
if (Option.isNone(match)) return Option.none();
|
|
207
|
+
const month = Number(textAt(match.value, 1) || "0") + 1;
|
|
208
|
+
const offset = Number(textAt(match.value, 2) || "0");
|
|
209
|
+
return month >= 1 && month <= 12 ? Option.some([month, offset]) : Option.none();
|
|
210
|
+
};
|
|
211
|
+
const currentYearDatePeriods = (range, canonical) => {
|
|
212
|
+
const filter = formatFilter(range);
|
|
213
|
+
const expressions = [
|
|
214
|
+
filter.gt,
|
|
215
|
+
filter.gte,
|
|
216
|
+
filter.lt,
|
|
217
|
+
filter.lte
|
|
218
|
+
];
|
|
219
|
+
const dates = /* @__PURE__ */ new Map();
|
|
220
|
+
for (const expression of expressions) {
|
|
221
|
+
if (expression === void 0) continue;
|
|
222
|
+
const date = currentYearDate(expression);
|
|
223
|
+
if (Option.isNone(date)) continue;
|
|
224
|
+
const [month, offset] = date.value;
|
|
225
|
+
for (const day of [offset, offset + 1]) {
|
|
226
|
+
if (day < 1 || day > minimumDaysInMonth(month)) continue;
|
|
227
|
+
dates.set(`${month}-${day}`, [month, day]);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
return [...dates.values()].map(([month, day]) => currentYearDatePeriod(month, day, canonical(day, month)));
|
|
231
|
+
};
|
|
232
|
+
const fixedMonthPeriod = (year, month, canonical) => {
|
|
233
|
+
const nextYear = month === 12 ? year + 1 : year;
|
|
234
|
+
const nextMonth = month === 12 ? 1 : month + 1;
|
|
235
|
+
return Period.make({
|
|
236
|
+
start: dateLiteral(isoDate(year, month, 1)),
|
|
237
|
+
end: dateLiteral(isoDate(nextYear, nextMonth, 1)),
|
|
238
|
+
canonical
|
|
239
|
+
});
|
|
240
|
+
};
|
|
241
|
+
const fixedYearPeriod = (year, canonical) => Period.make({
|
|
242
|
+
start: dateLiteral(isoDate(year, 1, 1)),
|
|
243
|
+
end: dateLiteral(isoDate(year + 1, 1, 1)),
|
|
244
|
+
canonical
|
|
245
|
+
});
|
|
246
|
+
const fixedQuarterPeriod = (year, quarter, canonical) => {
|
|
247
|
+
const month = (quarter - 1) * 3 + 1;
|
|
248
|
+
const nextYear = quarter === 4 ? year + 1 : year;
|
|
249
|
+
const nextMonth = quarter === 4 ? 1 : month + 3;
|
|
250
|
+
return Period.make({
|
|
251
|
+
start: dateLiteral(isoDate(year, month, 1)),
|
|
252
|
+
end: dateLiteral(isoDate(nextYear, nextMonth, 1)),
|
|
253
|
+
canonical
|
|
254
|
+
});
|
|
255
|
+
};
|
|
256
|
+
const quarterOfRelativeYear = (quarter, direction, canonical) => {
|
|
257
|
+
const yearBase = direction === 0 ? now() : shift(now(), direction, "year");
|
|
258
|
+
const yearStart = startOf(yearBase, "year");
|
|
259
|
+
const start = quarter === 1 ? yearStart : shift(yearStart, (quarter - 1) * 3, "month");
|
|
260
|
+
return Period.make({
|
|
261
|
+
start,
|
|
262
|
+
end: shift(start, 1, "quarter"),
|
|
263
|
+
canonical
|
|
264
|
+
});
|
|
265
|
+
};
|
|
266
|
+
const monthOfRelativeYear = (month, direction, canonical) => {
|
|
267
|
+
const yearBase = direction === 0 ? now() : shift(now(), direction, "year");
|
|
268
|
+
const yearStart = startOf(yearBase, "year");
|
|
269
|
+
const start = month === 1 ? yearStart : shift(yearStart, month - 1, "month");
|
|
270
|
+
return Period.make({
|
|
271
|
+
start,
|
|
272
|
+
end: shift(start, 1, "month"),
|
|
273
|
+
canonical
|
|
274
|
+
});
|
|
275
|
+
};
|
|
276
|
+
const calendarPeriodOffset = (range) => {
|
|
277
|
+
if (!isGreaterThanOrEqual(range.lower) || !isLessThan(range.upper)) return Option.none();
|
|
278
|
+
const start = range.lower.value;
|
|
279
|
+
const end = range.upper.value;
|
|
280
|
+
if (!isStartOf(start) || !isShift(start.base) || start.base.amount === 0 || !isNow(start.base.base) || start.unit !== start.base.unit || !isShift(end) || end.amount !== 1 || end.unit !== start.unit || formatInstantExpression(end.base) !== formatInstantExpression(start)) return Option.none();
|
|
281
|
+
return Option.some(CalendarPeriodOffset.make({
|
|
282
|
+
amount: start.base.amount,
|
|
283
|
+
unit: start.unit
|
|
284
|
+
}));
|
|
285
|
+
};
|
|
286
|
+
const candidate = (range, canonical) => NaturalCandidate.make({
|
|
287
|
+
range,
|
|
288
|
+
canonical
|
|
289
|
+
});
|
|
290
|
+
const joinedNowCandidate = (input, periodToNow, nowToPeriod, parsePeriod, canonicalToNow, canonicalFromNow) => {
|
|
291
|
+
for (const [prefix, suffix] of periodToNow) {
|
|
292
|
+
if (!input.startsWith(prefix) || !input.endsWith(suffix)) continue;
|
|
293
|
+
const period = parsePeriod(input.slice(prefix.length, -suffix.length));
|
|
294
|
+
if (Option.isNone(period)) continue;
|
|
295
|
+
return Option.some(candidate(boundedRange(greaterThanOrEqual(period.value.start), lessThanOrEqual(now())), canonicalToNow(period.value.canonical)));
|
|
296
|
+
}
|
|
297
|
+
for (const prefix of nowToPeriod) {
|
|
298
|
+
if (!input.startsWith(prefix)) continue;
|
|
299
|
+
const period = parsePeriod(input.slice(prefix.length));
|
|
300
|
+
if (Option.isNone(period)) continue;
|
|
301
|
+
return Option.some(candidate(boundedRange(greaterThanOrEqual(now()), lessThan(period.value.end)), canonicalFromNow(period.value.canonical)));
|
|
302
|
+
}
|
|
303
|
+
return Option.none();
|
|
304
|
+
};
|
|
305
|
+
const joinedPeriodCandidate = (input, joins, parsePeriod, canonical) => {
|
|
306
|
+
for (const [prefix, separator] of joins) {
|
|
307
|
+
if (!input.startsWith(prefix)) continue;
|
|
308
|
+
const separatorIndex = input.indexOf(separator, prefix.length);
|
|
309
|
+
if (separatorIndex === -1) continue;
|
|
310
|
+
const lower = parsePeriod(input.slice(prefix.length, separatorIndex));
|
|
311
|
+
const upper = parsePeriod(input.slice(separatorIndex + separator.length));
|
|
312
|
+
if (Option.isNone(lower) || Option.isNone(upper)) continue;
|
|
313
|
+
return Option.some(candidate(boundedRange(greaterThanOrEqual(lower.value.start), lessThan(upper.value.end)), canonical(lower.value.canonical, upper.value.canonical)));
|
|
314
|
+
}
|
|
315
|
+
return Option.none();
|
|
316
|
+
};
|
|
317
|
+
const periodBoundaryCandidate = (period, boundary, canonical) => Match.value(boundary).pipe(Match.when("since", () => candidate(lowerOpenRange(greaterThanOrEqual(period.start)), canonical)), Match.when("before", () => candidate(upperOpenRange(lessThan(period.start)), canonical)), Match.when("through", () => candidate(upperOpenRange(lessThan(period.end)), canonical)), Match.when("after", () => candidate(lowerOpenRange(greaterThanOrEqual(period.end)), canonical)), Match.exhaustive);
|
|
318
|
+
const openBoundaryCandidate = (input, boundaries, parsePeriod) => {
|
|
319
|
+
for (const boundary of boundaries) {
|
|
320
|
+
if (!input.startsWith(boundary[0])) continue;
|
|
321
|
+
const period = parsePeriod(input.slice(boundary[0].length));
|
|
322
|
+
if (Option.isNone(period)) continue;
|
|
323
|
+
const canonical = `${boundary[0]}${period.value.canonical}`;
|
|
324
|
+
return Option.some(periodBoundaryCandidate(period.value, boundary[1], canonical));
|
|
325
|
+
}
|
|
326
|
+
return Option.none();
|
|
327
|
+
};
|
|
328
|
+
const expressionDates = (range) => {
|
|
329
|
+
const filter = formatFilter(range);
|
|
330
|
+
const expressions = [
|
|
331
|
+
filter.gt,
|
|
332
|
+
filter.gte,
|
|
333
|
+
filter.lt,
|
|
334
|
+
filter.lte
|
|
335
|
+
];
|
|
336
|
+
const dates = /* @__PURE__ */ new Set();
|
|
337
|
+
for (const expression of expressions) {
|
|
338
|
+
if (expression === void 0) continue;
|
|
339
|
+
const match = String$1.match(/^(\d{4})-(\d{2})-(\d{2})/u)(expression);
|
|
340
|
+
if (Option.isSome(match)) dates.add(match.value[0]);
|
|
341
|
+
}
|
|
342
|
+
return [...dates];
|
|
343
|
+
};
|
|
344
|
+
const datedQuarterPeriods = (range) => {
|
|
345
|
+
return [...new Set(expressionDates(range).map((date) => date.slice(0, 4)))].flatMap((year) => [
|
|
346
|
+
1,
|
|
347
|
+
2,
|
|
348
|
+
3,
|
|
349
|
+
4
|
|
350
|
+
].map((quarter) => `q${quarter} ${year}`));
|
|
351
|
+
};
|
|
352
|
+
const datedPeriods = (range, months) => {
|
|
353
|
+
const dates = expressionDates(range);
|
|
354
|
+
return [...[...new Set(dates.map((date) => date.slice(0, 4)))].flatMap((year) => [...months.map((month) => `${month} ${year}`), year]), ...dates.flatMap((date) => date === "0000-01-01" ? [date] : [date, previousDay(Number(date.slice(0, 4)), Number(date.slice(5, 7)), Number(date.slice(8, 10)))])];
|
|
355
|
+
};
|
|
356
|
+
const periodsFromPhrases = (phrases, parsePeriod) => phrases.flatMap((phrase) => Option.toArray(parsePeriod(phrase)));
|
|
357
|
+
const renderPeriodRange = (range, toDate, periods, since, before, through, after, between, toNow, fromNow, untilNow, afterNow) => {
|
|
358
|
+
const expected = rangeKey(range);
|
|
359
|
+
for (const entry of toDate) if (rangeKey(entry.range) === expected) return Option.some(entry.canonical);
|
|
360
|
+
const filter = formatFilter(range);
|
|
361
|
+
const startsAt = (expression) => periods.find((period) => formatInstantExpression(period.start) === expression);
|
|
362
|
+
const endsAt = (expression) => periods.find((period) => formatInstantExpression(period.end) === expression);
|
|
363
|
+
if (filter.lte === "now" && filter.gt === void 0 && filter.gte === void 0) return Option.some(untilNow());
|
|
364
|
+
if (filter.gte === "now" && filter.lt === void 0 && filter.lte === void 0) return Option.some(afterNow());
|
|
365
|
+
if (filter.gte !== void 0 && filter.lte === "now") {
|
|
366
|
+
const period = startsAt(filter.gte);
|
|
367
|
+
if (period !== void 0) return Option.some(toNow(period.canonical));
|
|
368
|
+
}
|
|
369
|
+
if (filter.gte === "now" && filter.lt !== void 0) {
|
|
370
|
+
const period = endsAt(filter.lt);
|
|
371
|
+
if (period !== void 0) return Option.some(fromNow(period.canonical));
|
|
372
|
+
}
|
|
373
|
+
if (filter.gte !== void 0 && filter.lt !== void 0) {
|
|
374
|
+
const exact = periods.find((period) => formatInstantExpression(period.start) === filter.gte && formatInstantExpression(period.end) === filter.lt);
|
|
375
|
+
if (exact !== void 0) return Option.some(exact.canonical);
|
|
376
|
+
const lower = startsAt(filter.gte)?.canonical;
|
|
377
|
+
const upper = endsAt(filter.lt)?.canonical;
|
|
378
|
+
return lower === void 0 || upper === void 0 ? Option.none() : Option.some(between(lower, upper));
|
|
379
|
+
}
|
|
380
|
+
if (filter.gte !== void 0 && filter.lt === void 0 && filter.lte === void 0) {
|
|
381
|
+
const start = startsAt(filter.gte);
|
|
382
|
+
if (start !== void 0) return Option.some(since(start.canonical));
|
|
383
|
+
const end = endsAt(filter.gte);
|
|
384
|
+
if (end !== void 0) return Option.some(after(end.canonical));
|
|
385
|
+
}
|
|
386
|
+
if (filter.lt !== void 0 && filter.gt === void 0 && filter.gte === void 0) {
|
|
387
|
+
const start = startsAt(filter.lt);
|
|
388
|
+
if (start !== void 0) return Option.some(before(start.canonical));
|
|
389
|
+
const end = endsAt(filter.lt);
|
|
390
|
+
if (end !== void 0) return Option.some(through(end.canonical));
|
|
391
|
+
}
|
|
392
|
+
return Option.none();
|
|
393
|
+
};
|
|
394
|
+
//#endregion
|
|
395
|
+
export { Period, absoluteDatePeriod, calendarPeriodOffset, candidate, currentYearDatePeriods, datedPeriods, datedQuarterPeriods, fixedDatePeriod, fixedMonthPeriod, fixedQuarterPeriod, fixedYearPeriod, formatAbsoluteDate, fromNowRange, futurePeriod, futureRange, isoDate, joinedNowCandidate, joinedPeriodCandidate, monthOfRelativeYear, namedCurrentYearDatePeriod, namedDatePeriod, openBoundaryCandidate, parseTrailingCount, periodBoundaryCandidate, periodDay, periodEndDay, periodPreviousDay, periodRange, periodStartDay, periodToDateRange, periodsFromPhrases, quarterOfRelativeYear, relativePeriod, relativeWeekend, remainingPeriodRange, renderPeriodRange, textAt, trailingPeriod, trailingRange, untilNowRange, validYear };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { LanguageConflictError, LanguageRegistrationError } from "../language/errors.mjs";
|
|
2
|
+
import { BaseLanguageContribution, LanguagePlugin } from "../language/model.mjs";
|
|
3
|
+
import { LanguageRegistry } from "../language/registry.mjs";
|
|
4
|
+
import "../index.mjs";
|
|
5
|
+
//#region src/locales/tr.d.ts
|
|
6
|
+
declare const TurkishContribution: BaseLanguageContribution;
|
|
7
|
+
declare const TurkishLanguage: LanguagePlugin;
|
|
8
|
+
declare const TurkishLanguageLayer: import("effect/Layer").Layer<LanguageRegistry, LanguageConflictError | LanguageRegistrationError, never>;
|
|
9
|
+
//#endregion
|
|
10
|
+
export { TurkishContribution, TurkishLanguage, TurkishLanguageLayer };
|