chronolizer 0.2.0 → 0.4.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 +170 -167
- package/dist/ast/constructors.d.mts +3 -8
- package/dist/ast/fold.d.mts +2 -1
- package/dist/ast/fold.mjs +38 -31
- package/dist/ast/normalize.mjs +4 -2
- package/dist/ast/schemas.d.mts +18 -25
- package/dist/ast/schemas.mjs +8 -17
- package/dist/filter/expression.mjs +27 -38
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +2 -2
- package/dist/language/model.d.mts +33 -33
- package/dist/language/model.mjs +5 -8
- package/dist/language/registry.mjs +35 -33
- package/dist/locales/cs.mjs +253 -31
- package/dist/locales/de.mjs +366 -42
- package/dist/locales/en.mjs +215 -51
- package/dist/locales/es.mjs +498 -91
- package/dist/locales/fr.mjs +360 -65
- package/dist/locales/nl.mjs +302 -64
- package/dist/locales/pl.mjs +447 -135
- package/dist/locales/shared.mjs +192 -23
- package/dist/locales/tr.mjs +220 -41
- package/dist/natural/correction.d.mts +1 -1
- package/dist/natural/correction.mjs +31 -5
- package/dist/natural/format.mjs +1 -1
- package/dist/natural/parse.d.mts +1 -1
- package/dist/natural/parse.mjs +5 -4
- package/dist/natural/policy.mjs +2 -2
- package/dist/natural/suggest.mjs +19 -3
- package/dist/natural/suggestion.mjs +11 -5
- package/dist/resolve/resolve.mjs +2 -10
- package/package.json +1 -1
package/dist/locales/cs.mjs
CHANGED
|
@@ -4,7 +4,7 @@ import { normalizeNaturalText } from "../natural/text.mjs";
|
|
|
4
4
|
import { defineLanguagePlugin, languagePluginsLayer } from "../language/registry.mjs";
|
|
5
5
|
import { correctWhitespaceSeparatedText } from "../natural/correction.mjs";
|
|
6
6
|
import { completeNaturalPhrases, fixedCalendarPeriodPhrases, naturalCount, prefixNaturalPhrases } from "../natural/suggestion.mjs";
|
|
7
|
-
import { calendarPeriodOffset, candidate, datedPeriods, datedQuarterPeriods, fixedDatePeriod, fixedMonthPeriod, fixedQuarterPeriod, fixedYearPeriod, fromNowRange, futurePeriod, futureRange, isoDate, joinedNowCandidate, joinedPeriodCandidate, monthOfRelativeYear, namedDatePeriod, openBoundaryCandidate, parseTrailingCount, periodEndDay, periodRange, periodStartDay, periodToDateRange, periodsFromPhrases, quarterOfRelativeYear, relativePeriod, relativeWeekend, remainingPeriodRange, renderPeriodRange, textAt, trailingPeriod, trailingRange, untilNowRange, validYear } from "./shared.mjs";
|
|
7
|
+
import { absoluteDatePeriod, calendarPeriodOffset, candidate, compileCountAliasNormalizer, compoundCountAliases, countAliasVocabulary, currentYearDatePeriods, datedPeriods, datedQuarterPeriods, decimalTens, decomposeShiftedPeriodRange, fixedDatePeriod, fixedMonthPeriod, fixedQuarterPeriod, fixedYearPeriod, fromNowRange, futurePeriod, futureRange, isoDate, joinedNowCandidate, joinedPeriodCandidate, monthOfRelativeYear, namedCurrentYearDatePeriod, namedDatePeriod, openBoundaryCandidate, parseTrailingCount, periodEndDay, periodRange, periodStartDay, periodToDateRange, periodsFromPhrases, quarterOfRelativeYear, relativePeriod, relativeWeekday, relativeWeekend, remainingPeriodRange, renderPeriodRange, sequentialCountAliases, shiftPeriod, textAt, trailingPeriod, trailingRange, untilNowRange, validYear } from "./shared.mjs";
|
|
8
8
|
import { Effect, Option, String as String$1 } from "effect";
|
|
9
9
|
//#region src/locales/cs.ts
|
|
10
10
|
const months = [
|
|
@@ -21,6 +21,123 @@ const months = [
|
|
|
21
21
|
"listopad",
|
|
22
22
|
"prosinec"
|
|
23
23
|
];
|
|
24
|
+
const weekdays = [
|
|
25
|
+
"pondělí",
|
|
26
|
+
"úterý",
|
|
27
|
+
"středa",
|
|
28
|
+
"čtvrtek",
|
|
29
|
+
"pátek",
|
|
30
|
+
"sobota",
|
|
31
|
+
"neděle"
|
|
32
|
+
];
|
|
33
|
+
const weekdayGenitives = [
|
|
34
|
+
"pondělí",
|
|
35
|
+
"úterý",
|
|
36
|
+
"středy",
|
|
37
|
+
"čtvrtka",
|
|
38
|
+
"pátku",
|
|
39
|
+
"soboty",
|
|
40
|
+
"neděle"
|
|
41
|
+
];
|
|
42
|
+
const nextWeekdays = weekdays.flatMap((weekday, day) => [{
|
|
43
|
+
phrase: `příští ${weekday}`,
|
|
44
|
+
day,
|
|
45
|
+
canonical: `příští ${weekday}`
|
|
46
|
+
}, {
|
|
47
|
+
phrase: `příštího ${textAt(weekdayGenitives, day)}`,
|
|
48
|
+
day,
|
|
49
|
+
canonical: `příští ${weekday}`
|
|
50
|
+
}]);
|
|
51
|
+
const czechCountWords = [
|
|
52
|
+
[
|
|
53
|
+
"dva",
|
|
54
|
+
"dvě",
|
|
55
|
+
"dvou",
|
|
56
|
+
"dvěma"
|
|
57
|
+
],
|
|
58
|
+
[
|
|
59
|
+
"tři",
|
|
60
|
+
"tří",
|
|
61
|
+
"třemi"
|
|
62
|
+
],
|
|
63
|
+
[
|
|
64
|
+
"čtyři",
|
|
65
|
+
"čtyř",
|
|
66
|
+
"čtyřmi"
|
|
67
|
+
],
|
|
68
|
+
["pět", "pěti"],
|
|
69
|
+
["šest", "šesti"],
|
|
70
|
+
["sedm", "sedmi"],
|
|
71
|
+
["osm", "osmi"],
|
|
72
|
+
["devět", "devíti"],
|
|
73
|
+
["deset", "deseti"],
|
|
74
|
+
["jedenáct", "jedenácti"],
|
|
75
|
+
["dvanáct", "dvanácti"],
|
|
76
|
+
["třináct", "třinácti"],
|
|
77
|
+
["čtrnáct", "čtrnácti"],
|
|
78
|
+
["patnáct", "patnácti"],
|
|
79
|
+
["šestnáct", "šestnácti"],
|
|
80
|
+
["sedmnáct", "sedmnácti"],
|
|
81
|
+
["osmnáct", "osmnácti"],
|
|
82
|
+
["devatenáct", "devatenácti"],
|
|
83
|
+
["dvacet", "dvaceti"]
|
|
84
|
+
];
|
|
85
|
+
const czechCountOnes = [
|
|
86
|
+
[1, "jedna"],
|
|
87
|
+
[2, "dva"],
|
|
88
|
+
[3, "tři"],
|
|
89
|
+
[4, "čtyři"],
|
|
90
|
+
[5, "pět"],
|
|
91
|
+
[6, "šest"],
|
|
92
|
+
[7, "sedm"],
|
|
93
|
+
[8, "osm"],
|
|
94
|
+
[9, "devět"]
|
|
95
|
+
];
|
|
96
|
+
const czechObliqueCountOnes = [
|
|
97
|
+
[1, "jedním"],
|
|
98
|
+
[2, "dvěma"],
|
|
99
|
+
[3, "třemi"],
|
|
100
|
+
[4, "čtyřmi"],
|
|
101
|
+
[5, "pěti"],
|
|
102
|
+
[6, "šesti"],
|
|
103
|
+
[7, "sedmi"],
|
|
104
|
+
[8, "osmi"],
|
|
105
|
+
[9, "devíti"]
|
|
106
|
+
];
|
|
107
|
+
const czechCountAliases = [
|
|
108
|
+
...sequentialCountAliases([[
|
|
109
|
+
"jeden",
|
|
110
|
+
"jedna",
|
|
111
|
+
"jedno",
|
|
112
|
+
"jedním",
|
|
113
|
+
"jednou"
|
|
114
|
+
]], 1),
|
|
115
|
+
...sequentialCountAliases(czechCountWords, 2),
|
|
116
|
+
...compoundCountAliases(decimalTens([
|
|
117
|
+
"dvacet",
|
|
118
|
+
"třicet",
|
|
119
|
+
"čtyřicet",
|
|
120
|
+
"padesát",
|
|
121
|
+
"šedesát",
|
|
122
|
+
"sedmdesát",
|
|
123
|
+
"osmdesát",
|
|
124
|
+
"devadesát"
|
|
125
|
+
]), czechCountOnes, (ten, one) => [`${ten} ${one}`]),
|
|
126
|
+
...compoundCountAliases(decimalTens([
|
|
127
|
+
"dvaceti",
|
|
128
|
+
"třiceti",
|
|
129
|
+
"čtyřiceti",
|
|
130
|
+
"padesáti",
|
|
131
|
+
"šedesáti",
|
|
132
|
+
"sedmdesáti",
|
|
133
|
+
"osmdesáti",
|
|
134
|
+
"devadesáti"
|
|
135
|
+
]), czechObliqueCountOnes, (ten, one) => [`${ten} ${one}`])
|
|
136
|
+
];
|
|
137
|
+
const normalizeCzechCounts = compileCountAliasNormalizer(czechCountAliases);
|
|
138
|
+
const czechCountVocabulary = new Set(countAliasVocabulary(czechCountAliases));
|
|
139
|
+
const correctCzech = (input, vocabulary) => correctWhitespaceSeparatedText(input, vocabulary, czechCountVocabulary);
|
|
140
|
+
const normalizeCzech = (input, locale) => normalizeCzechCounts(normalizeNaturalText(input, locale));
|
|
24
141
|
const monthGenitives = [
|
|
25
142
|
"ledna",
|
|
26
143
|
"února",
|
|
@@ -85,6 +202,7 @@ const units = [
|
|
|
85
202
|
many: "dnů",
|
|
86
203
|
pastSingular: "dnem",
|
|
87
204
|
pastPlural: "dny",
|
|
205
|
+
durationGenitive: "dne",
|
|
88
206
|
current: "dnes",
|
|
89
207
|
previous: "včera",
|
|
90
208
|
next: "zítra",
|
|
@@ -98,6 +216,7 @@ const units = [
|
|
|
98
216
|
many: "týdnů",
|
|
99
217
|
pastSingular: "týdnem",
|
|
100
218
|
pastPlural: "týdny",
|
|
219
|
+
durationGenitive: "týdne",
|
|
101
220
|
current: "tento týden",
|
|
102
221
|
previous: "minulý týden",
|
|
103
222
|
next: "příští týden",
|
|
@@ -111,6 +230,7 @@ const units = [
|
|
|
111
230
|
many: "měsíců",
|
|
112
231
|
pastSingular: "měsícem",
|
|
113
232
|
pastPlural: "měsíci",
|
|
233
|
+
durationGenitive: "měsíce",
|
|
114
234
|
current: "tento měsíc",
|
|
115
235
|
previous: "minulý měsíc",
|
|
116
236
|
next: "příští měsíc",
|
|
@@ -124,6 +244,7 @@ const units = [
|
|
|
124
244
|
many: "čtvrtletí",
|
|
125
245
|
pastSingular: "čtvrtletím",
|
|
126
246
|
pastPlural: "čtvrtletími",
|
|
247
|
+
durationGenitive: "čtvrtletí",
|
|
127
248
|
current: "toto čtvrtletí",
|
|
128
249
|
previous: "minulé čtvrtletí",
|
|
129
250
|
next: "příští čtvrtletí",
|
|
@@ -137,6 +258,7 @@ const units = [
|
|
|
137
258
|
many: "let",
|
|
138
259
|
pastSingular: "rokem",
|
|
139
260
|
pastPlural: "lety",
|
|
261
|
+
durationGenitive: "roku",
|
|
140
262
|
current: "tento rok",
|
|
141
263
|
previous: "minulý rok",
|
|
142
264
|
next: "příští rok",
|
|
@@ -144,7 +266,6 @@ const units = [
|
|
|
144
266
|
remaining: "zbytek roku"
|
|
145
267
|
}
|
|
146
268
|
];
|
|
147
|
-
const title = (value) => `${value.slice(0, 1).toLocaleUpperCase("cs")}${value.slice(1)}`;
|
|
148
269
|
const unitAliases = [
|
|
149
270
|
["den", "day"],
|
|
150
271
|
["dny", "day"],
|
|
@@ -360,17 +481,22 @@ const monthNumber = (value) => {
|
|
|
360
481
|
return short === -1 ? void 0 : short + 1;
|
|
361
482
|
};
|
|
362
483
|
const dateLabel = (day, month, year) => `${day}. ${textAt(monthGenitives, month - 1)} ${year}`;
|
|
484
|
+
const currentDateLabel = (day, month) => `${day}. ${textAt(monthGenitives, month - 1)}`;
|
|
363
485
|
const parseNamedDate = (input) => {
|
|
364
486
|
const named = String$1.match(/^([0-3]?\d)\.?(?: )([a-záčďéěíňóřšťúůýž]+\.?) (\d{4})$/u)(input);
|
|
365
487
|
if (Option.isSome(named)) return namedDatePeriod(textAt(named.value, 3), textAt(named.value, 2), textAt(named.value, 1), monthNumber, dateLabel);
|
|
366
488
|
const numeric = String$1.match(/^([0-3]?\d)(?:\. ?|[/-])([01]?\d)(?:\. ?|[/-])(\d{4})$/u)(input);
|
|
367
|
-
if (Option.
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
489
|
+
if (Option.isSome(numeric)) {
|
|
490
|
+
const year = validYear(textAt(numeric.value, 3));
|
|
491
|
+
const month = Number(textAt(numeric.value, 2));
|
|
492
|
+
const day = Number(textAt(numeric.value, 1));
|
|
493
|
+
if (year !== void 0 && month >= 1 && month <= 12) {
|
|
494
|
+
const value = isoDate(year, month, day);
|
|
495
|
+
if (isIsoDate(value) && value !== "9999-12-31") return Option.some(fixedDatePeriod(value, dateLabel(day, month, year)));
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
const current = String$1.match(/^([0-3]?\d)\.? ([a-záčďéěíňóřšťúůýž]+\.?)$/u)(input);
|
|
499
|
+
return Option.isSome(current) ? namedCurrentYearDatePeriod(textAt(current.value, 2), textAt(current.value, 1), monthNumber, currentDateLabel) : Option.none();
|
|
374
500
|
};
|
|
375
501
|
const quarterNumber = (value) => {
|
|
376
502
|
if (value.startsWith("q") && value.length === 2) return Number(value.slice(1));
|
|
@@ -397,12 +523,13 @@ const parseQuarter = (input) => {
|
|
|
397
523
|
const quarter = quarterNumber(textAt(standalone.value, 1));
|
|
398
524
|
return quarter === void 0 ? Option.none() : Option.some(quarterOfRelativeYear(quarter, 0, `Q${quarter}`));
|
|
399
525
|
};
|
|
400
|
-
const
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
526
|
+
const parseDatedPeriod = (input) => {
|
|
527
|
+
const knownPeriod = Option.firstSomeOf([
|
|
528
|
+
absoluteDatePeriod(input, "cs"),
|
|
529
|
+
parseNamedDate(input),
|
|
530
|
+
parseQuarter(input)
|
|
531
|
+
]);
|
|
532
|
+
if (Option.isSome(knownPeriod)) return knownPeriod;
|
|
406
533
|
const yearMatch = String$1.match(/^(?:rok |roku )?(\d{4})$/u)(input);
|
|
407
534
|
if (Option.isSome(yearMatch)) {
|
|
408
535
|
const year = validYear(textAt(yearMatch.value, 1));
|
|
@@ -412,7 +539,21 @@ const parseBasePeriod = (input) => {
|
|
|
412
539
|
if (Option.isSome(monthYear)) {
|
|
413
540
|
const month = monthNumber(textAt(monthYear.value, 1));
|
|
414
541
|
const year = validYear(textAt(monthYear.value, 2));
|
|
415
|
-
if (month !== void 0 && year !== void 0) return Option.some(fixedMonthPeriod(year, month, `${
|
|
542
|
+
if (month !== void 0 && year !== void 0) return Option.some(fixedMonthPeriod(year, month, `${textAt(months, month - 1)} ${year}`));
|
|
543
|
+
}
|
|
544
|
+
return Option.none();
|
|
545
|
+
};
|
|
546
|
+
const parseBasePeriod = (input) => {
|
|
547
|
+
const datedPeriod = parseDatedPeriod(input);
|
|
548
|
+
if (Option.isSome(datedPeriod)) return datedPeriod;
|
|
549
|
+
const prefixedRelativeMonth = String$1.match(/^(minulý|tento|příští) ([a-záčďéěíňóřšťúůýž]+\.?)$/u)(input);
|
|
550
|
+
if (Option.isSome(prefixedRelativeMonth)) {
|
|
551
|
+
const month = monthNumber(textAt(prefixedRelativeMonth.value, 2));
|
|
552
|
+
if (month !== void 0) {
|
|
553
|
+
const modifier = textAt(prefixedRelativeMonth.value, 1);
|
|
554
|
+
const direction = relativeYearDirection(modifier);
|
|
555
|
+
return Option.some(monthOfRelativeYear(month, direction, `${modifier} ${textAt(months, month - 1)}`));
|
|
556
|
+
}
|
|
416
557
|
}
|
|
417
558
|
const relativeMonth = String$1.match(/^([a-záčďéěíňóřšťúůýž]+\.?) (minulého roku|příštího roku|tohoto roku)$/u)(input);
|
|
418
559
|
const relativeMonthYearFirst = String$1.match(/^(minulého roku|příštího roku|tohoto roku) ([a-záčďéěíňóřšťúůýž]+\.?)$/u)(input);
|
|
@@ -423,10 +564,10 @@ const parseBasePeriod = (input) => {
|
|
|
423
564
|
const yearText = textAt(relativeMatch.value, yearFirst ? 1 : 2);
|
|
424
565
|
const month = monthNumber(monthText);
|
|
425
566
|
const direction = relativeYearDirection(yearText);
|
|
426
|
-
if (month !== void 0) return Option.some(monthOfRelativeYear(month, direction, `${
|
|
567
|
+
if (month !== void 0) return Option.some(monthOfRelativeYear(month, direction, `${textAt(months, month - 1)} ${relativeYearName(direction)}`));
|
|
427
568
|
}
|
|
428
569
|
const standaloneMonth = monthNumber(input);
|
|
429
|
-
if (standaloneMonth !== void 0) return Option.some(monthOfRelativeYear(standaloneMonth, 0,
|
|
570
|
+
if (standaloneMonth !== void 0) return Option.some(monthOfRelativeYear(standaloneMonth, 0, textAt(months, standaloneMonth - 1)));
|
|
430
571
|
const alias = periodAliases.find((entry) => entry[0] === input);
|
|
431
572
|
if (alias !== void 0) return Option.some(relativePeriod(alias[1], alias[2], alias[3]));
|
|
432
573
|
if (["víkend", "tento víkend"].includes(input)) return Option.some(relativeWeekend(0, "tento víkend"));
|
|
@@ -434,12 +575,31 @@ const parseBasePeriod = (input) => {
|
|
|
434
575
|
if (["příští víkend", "následující víkend"].includes(input)) return Option.some(relativeWeekend(1, "příští víkend"));
|
|
435
576
|
if (input === "předminulý víkend") return Option.some(relativeWeekend(-2, input));
|
|
436
577
|
if (input === "přespříští víkend") return Option.some(relativeWeekend(2, input));
|
|
437
|
-
|
|
578
|
+
const weekday = nextWeekdays.find((entry) => entry.phrase === input);
|
|
579
|
+
return weekday === void 0 ? Option.none() : Option.some(relativeWeekday(weekday.day, 1, weekday.canonical));
|
|
438
580
|
};
|
|
439
581
|
const parsePeriod = (input) => {
|
|
582
|
+
const shifted = String$1.match(/^(.+) (před|za) ([1-9]\d*) (den|dny|dnů|dnem|týden|týdny|týdnů|týdnem|měsíc|měsíce|měsíců|měsícem|měsíci|čtvrtletí|čtvrtletím|čtvrtletími|rok|roky|let|rokem|lety)$/u)(input);
|
|
583
|
+
if (Option.isSome(shifted)) {
|
|
584
|
+
const amount = parseTrailingCount(textAt(shifted.value, 3));
|
|
585
|
+
const alias = unitAliases.find((unit) => unit[0] === textAt(shifted.value, 4));
|
|
586
|
+
const entry = alias === void 0 ? void 0 : units.find((unit) => unit.unit === alias[1]);
|
|
587
|
+
const period = parsePeriod(textAt(shifted.value, 1));
|
|
588
|
+
if (Option.isSome(amount) && entry !== void 0 && Option.isSome(period)) {
|
|
589
|
+
const past = textAt(shifted.value, 2) === "před";
|
|
590
|
+
const direction = past ? -amount.value : amount.value;
|
|
591
|
+
const pastNoun = amount.value === 1 ? entry.pastSingular : entry.pastPlural;
|
|
592
|
+
const noun = past ? pastNoun : countNoun(amount.value, entry);
|
|
593
|
+
const canonical = `${period.value.canonical} ${past ? "před" : "za"} ${amount.value} ${noun}`;
|
|
594
|
+
return Option.some(shiftPeriod(period.value, direction, entry.unit, canonical));
|
|
595
|
+
}
|
|
596
|
+
}
|
|
440
597
|
const edge = String$1.match(/^(začátek|počátek|konec) (.+)$/u)(input);
|
|
441
598
|
if (Option.isSome(edge)) {
|
|
442
|
-
const
|
|
599
|
+
const periodText = textAt(edge.value, 2);
|
|
600
|
+
const basePeriod = parseBasePeriod(periodText);
|
|
601
|
+
const implicit = units.find((entry) => entry.durationGenitive === periodText);
|
|
602
|
+
const period = Option.isSome(basePeriod) || implicit === void 0 ? basePeriod : Option.some(relativePeriod(implicit.unit, 0, implicit.current));
|
|
443
603
|
if (Option.isSome(period)) {
|
|
444
604
|
const isEnd = textAt(edge.value, 1) === "konec";
|
|
445
605
|
const canonical = `${isEnd ? "konec" : "začátek"} ${period.value.canonical}`;
|
|
@@ -452,7 +612,8 @@ const parsePeriod = (input) => {
|
|
|
452
612
|
"celý ",
|
|
453
613
|
"celé "
|
|
454
614
|
].find((prefix) => input.startsWith(prefix));
|
|
455
|
-
|
|
615
|
+
const base = parseBasePeriod(wrapper === void 0 ? input : input.slice(wrapper.length));
|
|
616
|
+
return Option.isSome(base) ? base : parseCalendarOffset(input);
|
|
456
617
|
};
|
|
457
618
|
const countedUnit = (value) => unitAliases.find((entry) => entry[0] === value)?.[1];
|
|
458
619
|
const countedUnitPattern = "den|dny|dnů|dnem|týden|týdny|týdnů|týdnem|měsíc|měsíce|měsíců|měsícem|měsíci|čtvrtletí|čtvrtletím|čtvrtletími|rok|roky|let|rokem|lety";
|
|
@@ -464,6 +625,24 @@ const rollingFuturePatterns = [countedPattern("^(?:příští|následující) ([
|
|
|
464
625
|
const rollingSincePattern = countedPattern("^za poslední ([1-9]\\d*) (UNIT)$");
|
|
465
626
|
const rollingBarePattern = countedPattern("^([1-9]\\d*) (UNIT)$");
|
|
466
627
|
const firstPatternMatch = (input, patterns) => Option.firstSomeOf(patterns.map((pattern) => String$1.match(pattern)(input)));
|
|
628
|
+
const singularRollingPhrases = units.flatMap((entry) => [
|
|
629
|
+
{
|
|
630
|
+
phrase: `poslední ${entry.singular}`,
|
|
631
|
+
entry,
|
|
632
|
+
future: false
|
|
633
|
+
},
|
|
634
|
+
{
|
|
635
|
+
phrase: `během posledního ${entry.durationGenitive}`,
|
|
636
|
+
entry,
|
|
637
|
+
future: false
|
|
638
|
+
},
|
|
639
|
+
{
|
|
640
|
+
phrase: `během následujícího ${entry.durationGenitive}`,
|
|
641
|
+
entry,
|
|
642
|
+
future: true
|
|
643
|
+
}
|
|
644
|
+
]);
|
|
645
|
+
const singularRollingCanonical = (entry, future) => `během ${future ? "následujícího" : "posledního"} ${entry.durationGenitive}`;
|
|
467
646
|
const countNoun = (amount, entry) => {
|
|
468
647
|
if (amount === 1) return entry.singular;
|
|
469
648
|
const lastTwo = amount % 100;
|
|
@@ -484,9 +663,14 @@ const parseCalendarOffset = (input) => {
|
|
|
484
663
|
const futureNoun = countNoun(amount.value, entry);
|
|
485
664
|
const pastNoun = amount.value === 1 ? entry.pastSingular : entry.pastPlural;
|
|
486
665
|
const canonical = direction < 0 ? `před ${amount.value} ${pastNoun}` : `za ${amount.value} ${futureNoun}`;
|
|
487
|
-
return Option.some(
|
|
666
|
+
return Option.some(relativePeriod(unit, direction, canonical));
|
|
488
667
|
};
|
|
489
668
|
const parseRollingPeriod = (input) => {
|
|
669
|
+
const singular = singularRollingPhrases.find((entry) => entry.phrase === input);
|
|
670
|
+
if (singular !== void 0) {
|
|
671
|
+
const range = singular.future ? futureRange(1, singular.entry.unit) : trailingRange(1, singular.entry.unit);
|
|
672
|
+
return Option.some(candidate(range, singularRollingCanonical(singular.entry, singular.future)));
|
|
673
|
+
}
|
|
490
674
|
const since = String$1.match(rollingSincePattern)(input);
|
|
491
675
|
const past = firstPatternMatch(input, rollingPastPatterns);
|
|
492
676
|
const bare = String$1.match(rollingBarePattern)(input);
|
|
@@ -505,9 +689,22 @@ const parseRollingPeriod = (input) => {
|
|
|
505
689
|
if (entry === void 0) return Option.none();
|
|
506
690
|
const isFuture = Option.isSome(future);
|
|
507
691
|
const range = isFuture ? futureRange(amount.value, unit) : trailingRange(amount.value, unit);
|
|
692
|
+
if (amount.value === 1) return Option.some(candidate(range, singularRollingCanonical(entry, isFuture)));
|
|
508
693
|
const modifier = isFuture ? "příští" : "poslední";
|
|
509
694
|
return Option.some(candidate(range, `${modifier} ${amount.value} ${countNoun(amount.value, entry)}`));
|
|
510
695
|
};
|
|
696
|
+
const parseElidedDateRange = (input) => {
|
|
697
|
+
const joined = String$1.match(/^od ([0-3]?\d)\.?(?: do) ([0-3]?\d)\.? ([a-záčďéěíňóřšťúůýž]+\.?)(?: (\d{4}))?$/u)(input);
|
|
698
|
+
const dashed = String$1.match(/^([0-3]?\d)\.?[–—-]([0-3]?\d)\.? ([a-záčďéěíňóřšťúůýž]+\.?)(?: (\d{4}))?$/u)(input);
|
|
699
|
+
const match = Option.firstSomeOf([joined, dashed]);
|
|
700
|
+
if (Option.isNone(match)) return Option.none();
|
|
701
|
+
const lowerDay = textAt(match.value, 1);
|
|
702
|
+
const upperDay = textAt(match.value, 2);
|
|
703
|
+
const month = textAt(match.value, 3);
|
|
704
|
+
const year = textAt(match.value, 4);
|
|
705
|
+
const suffix = year.length === 0 ? "" : ` ${year}`;
|
|
706
|
+
return joinedPeriodCandidate(`od ${lowerDay}. ${month}${suffix} do ${upperDay}. ${month}${suffix}`, [["od ", " do "]], parsePeriod, (lower, upper) => `od ${lower} do ${upper} včetně`);
|
|
707
|
+
};
|
|
511
708
|
const boundaryCandidate = (input) => {
|
|
512
709
|
const included = String$1.match(/^do (.+) včetně$/u)(input);
|
|
513
710
|
if (Option.isSome(included)) return openBoundaryCandidate(`do ${textAt(included.value, 1)}`, [["do ", "through"]], parsePeriod);
|
|
@@ -533,13 +730,17 @@ const parseCzech = (input) => {
|
|
|
533
730
|
"ode dneška",
|
|
534
731
|
"od teď"
|
|
535
732
|
].includes(input)) return Option.some(candidate(fromNowRange(), "od nynějška"));
|
|
536
|
-
const offset = parseCalendarOffset(input);
|
|
537
|
-
if (Option.isSome(offset)) return offset;
|
|
538
733
|
const rolling = parseRollingPeriod(input);
|
|
539
734
|
if (Option.isSome(rolling)) return rolling;
|
|
540
735
|
const toDate = toDatePhrases.find((entry) => entry.phrase === input);
|
|
541
736
|
if (toDate !== void 0) return Option.some(candidate(periodToDateRange(toDate.entry.unit), toDate.entry.toDate));
|
|
542
|
-
const
|
|
737
|
+
const elided = parseElidedDateRange(input);
|
|
738
|
+
if (Option.isSome(elided)) return elided;
|
|
739
|
+
const nowBounded = joinedNowCandidate(input, [["od ", " do dneška"], ["mezi ", " a dneškem"]], [
|
|
740
|
+
"od dneška do ",
|
|
741
|
+
"mezi dneškem a ",
|
|
742
|
+
"dnešek až "
|
|
743
|
+
], parsePeriod, (period) => `od ${period} do dneška`, (period) => `od dneška do ${period}`);
|
|
543
744
|
if (Option.isSome(nowBounded)) return nowBounded;
|
|
544
745
|
const bounded = joinedPeriodCandidate(input, [
|
|
545
746
|
["od ", " do "],
|
|
@@ -551,7 +752,7 @@ const parseCzech = (input) => {
|
|
|
551
752
|
if (Option.isSome(bounded)) return bounded;
|
|
552
753
|
const boundary = boundaryCandidate(input);
|
|
553
754
|
if (Option.isSome(boundary)) return boundary;
|
|
554
|
-
return Option.map(
|
|
755
|
+
return parsePeriod(input).pipe(Option.map((period) => candidate(periodRange(period), period.canonical)));
|
|
555
756
|
};
|
|
556
757
|
const staticPeriodPhrases = [
|
|
557
758
|
...periodAliases.map((entry) => entry[0]),
|
|
@@ -561,6 +762,8 @@ const staticPeriodPhrases = [
|
|
|
561
762
|
"předminulý víkend",
|
|
562
763
|
"přespříští víkend",
|
|
563
764
|
...periodAliases.flatMap((entry) => [`začátek ${entry[0]}`, `konec ${entry[0]}`]),
|
|
765
|
+
...nextWeekdays.map((entry) => entry.phrase),
|
|
766
|
+
...months.flatMap((month) => [`minulý ${month}`, `příští ${month}`]),
|
|
564
767
|
...[
|
|
565
768
|
1,
|
|
566
769
|
2,
|
|
@@ -606,6 +809,7 @@ const countedSuggestions = (input) => {
|
|
|
606
809
|
const czechSuggestionPhrases = [
|
|
607
810
|
...units.map((entry) => entry.toDate),
|
|
608
811
|
...units.map((entry) => entry.remaining),
|
|
812
|
+
...singularRollingPhrases.map((entry) => entry.phrase),
|
|
609
813
|
...staticPeriodPhrases,
|
|
610
814
|
...prefixNaturalPhrases(staticPeriodPhrases, boundaryPrefixes),
|
|
611
815
|
"dosud",
|
|
@@ -621,6 +825,18 @@ const suggestCzech = (input, limit) => {
|
|
|
621
825
|
], limit);
|
|
622
826
|
};
|
|
623
827
|
const renderCzech = (range) => {
|
|
828
|
+
const shifted = decomposeShiftedPeriodRange(range);
|
|
829
|
+
if (Option.isSome(shifted)) {
|
|
830
|
+
const base = renderCzech(shifted.value.baseRange);
|
|
831
|
+
const entry = units.find((unit) => unit.unit === shifted.value.unit);
|
|
832
|
+
if (Option.isSome(base) && entry !== void 0) {
|
|
833
|
+
const amount = Math.abs(shifted.value.amount);
|
|
834
|
+
const pastNoun = amount === 1 ? entry.pastSingular : entry.pastPlural;
|
|
835
|
+
const noun = shifted.value.amount < 0 ? pastNoun : countNoun(amount, entry);
|
|
836
|
+
const direction = shifted.value.amount < 0 ? "před" : "za";
|
|
837
|
+
return Option.some(`${base.value} ${direction} ${amount} ${noun}`);
|
|
838
|
+
}
|
|
839
|
+
}
|
|
624
840
|
const offset = calendarPeriodOffset(range);
|
|
625
841
|
if (Option.isSome(offset) && Math.abs(offset.value.amount) > 1) {
|
|
626
842
|
const entry = units.find((unit) => unit.unit === offset.value.unit);
|
|
@@ -634,20 +850,26 @@ const renderCzech = (range) => {
|
|
|
634
850
|
const future = futurePeriod(range);
|
|
635
851
|
if (Option.isSome(future)) {
|
|
636
852
|
const entry = units.find((unit) => unit.unit === future.value.unit);
|
|
637
|
-
if (entry !== void 0) return Option.some(`příští ${future.value.amount} ${countNoun(future.value.amount, entry)}`);
|
|
853
|
+
if (entry !== void 0) return Option.some(future.value.amount === 1 ? singularRollingCanonical(entry, true) : `příští ${future.value.amount} ${countNoun(future.value.amount, entry)}`);
|
|
638
854
|
}
|
|
639
855
|
const trailing = trailingPeriod(range);
|
|
640
856
|
if (Option.isSome(trailing)) {
|
|
641
857
|
const entry = units.find((unit) => unit.unit === trailing.value.unit);
|
|
642
|
-
if (entry !== void 0) return Option.some(`poslední ${trailing.value.amount} ${countNoun(trailing.value.amount, entry)}`);
|
|
858
|
+
if (entry !== void 0) return Option.some(trailing.value.amount === 1 ? singularRollingCanonical(entry, false) : `poslední ${trailing.value.amount} ${countNoun(trailing.value.amount, entry)}`);
|
|
643
859
|
}
|
|
644
|
-
const periods = [
|
|
860
|
+
const periods = [
|
|
861
|
+
...staticPeriods,
|
|
862
|
+
...currentYearDatePeriods(range, currentDateLabel),
|
|
863
|
+
...periodsFromPhrases([...datedPeriods(range, months), ...datedQuarterPeriods(range)], parsePeriod)
|
|
864
|
+
];
|
|
645
865
|
return renderPeriodRange(range, [...units.map((entry) => candidate(periodToDateRange(entry.unit), entry.toDate)), ...units.map((entry) => candidate(remainingPeriodRange(entry.unit), entry.remaining))], periods, (period) => `od ${period}`, (period) => `před ${period}`, (period) => `do ${period} včetně`, (period) => `po ${period}`, (lower, upper) => `od ${lower} do ${upper} včetně`, (period) => `od ${period} do dneška`, (period) => `od dneška do ${period}`, () => "dosud", () => "od nynějška");
|
|
646
866
|
};
|
|
647
867
|
const CzechContribution = new BaseLanguageContribution({
|
|
648
868
|
locale: "cs",
|
|
649
869
|
vocabulary: [
|
|
650
870
|
...months,
|
|
871
|
+
...weekdays,
|
|
872
|
+
...weekdayGenitives,
|
|
651
873
|
...monthAbbreviations.flatMap((aliases) => aliases),
|
|
652
874
|
...units.flatMap((entry) => [
|
|
653
875
|
entry.singular,
|
|
@@ -678,8 +900,8 @@ const CzechContribution = new BaseLanguageContribution({
|
|
|
678
900
|
"začátek",
|
|
679
901
|
"zbytek"
|
|
680
902
|
],
|
|
681
|
-
normalize:
|
|
682
|
-
correct:
|
|
903
|
+
normalize: normalizeCzech,
|
|
904
|
+
correct: correctCzech,
|
|
683
905
|
parseExact: parseCzech,
|
|
684
906
|
suggest: suggestCzech,
|
|
685
907
|
render: renderCzech
|