chronolizer 0.2.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 +169 -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 +3 -20
- 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 +4 -7
- package/dist/language/registry.mjs +3 -21
- package/dist/locales/cs.mjs +70 -17
- package/dist/locales/de.mjs +237 -26
- package/dist/locales/en.mjs +69 -21
- package/dist/locales/es.mjs +325 -77
- package/dist/locales/fr.mjs +215 -51
- package/dist/locales/nl.mjs +189 -50
- package/dist/locales/pl.mjs +295 -121
- package/dist/locales/shared.mjs +129 -23
- package/dist/locales/tr.mjs +86 -21
- package/dist/natural/parse.d.mts +1 -1
- package/dist/natural/policy.mjs +2 -2
- package/dist/resolve/resolve.mjs +1 -9
- package/package.json +1 -1
package/dist/locales/nl.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, currentYearDatePeriods, datedPeriods, datedQuarterPeriods, fixedDatePeriod, fixedMonthPeriod, fixedQuarterPeriod, fixedYearPeriod, fromNowRange, futurePeriod, futureRange, isoDate, joinedNowCandidate, joinedPeriodCandidate, monthOfRelativeYear, namedCurrentYearDatePeriod, namedDatePeriod, openBoundaryCandidate, parseTrailingCount, periodDay, periodEndDay, periodRange, periodStartDay, periodToDateRange, periodsFromPhrases, quarterOfRelativeYear, relativePeriod, relativeWeekend, remainingPeriodRange, renderPeriodRange, textAt, trailingPeriod, trailingRange, untilNowRange, validYear } from "./shared.mjs";
|
|
8
8
|
import { Effect, Option, String as String$1 } from "effect";
|
|
9
9
|
//#region src/locales/nl.ts
|
|
10
10
|
const months = [
|
|
@@ -40,6 +40,7 @@ const units = [
|
|
|
40
40
|
unit: "day",
|
|
41
41
|
singular: "dag",
|
|
42
42
|
plural: "dagen",
|
|
43
|
+
article: "de",
|
|
43
44
|
current: "vandaag",
|
|
44
45
|
previous: "gisteren",
|
|
45
46
|
next: "morgen",
|
|
@@ -50,6 +51,7 @@ const units = [
|
|
|
50
51
|
unit: "week",
|
|
51
52
|
singular: "week",
|
|
52
53
|
plural: "weken",
|
|
54
|
+
article: "de",
|
|
53
55
|
current: "deze week",
|
|
54
56
|
previous: "vorige week",
|
|
55
57
|
next: "volgende week",
|
|
@@ -60,6 +62,7 @@ const units = [
|
|
|
60
62
|
unit: "month",
|
|
61
63
|
singular: "maand",
|
|
62
64
|
plural: "maanden",
|
|
65
|
+
article: "de",
|
|
63
66
|
current: "deze maand",
|
|
64
67
|
previous: "vorige maand",
|
|
65
68
|
next: "volgende maand",
|
|
@@ -70,6 +73,7 @@ const units = [
|
|
|
70
73
|
unit: "quarter",
|
|
71
74
|
singular: "kwartaal",
|
|
72
75
|
plural: "kwartalen",
|
|
76
|
+
article: "het",
|
|
73
77
|
current: "dit kwartaal",
|
|
74
78
|
previous: "vorig kwartaal",
|
|
75
79
|
next: "volgend kwartaal",
|
|
@@ -80,6 +84,7 @@ const units = [
|
|
|
80
84
|
unit: "year",
|
|
81
85
|
singular: "jaar",
|
|
82
86
|
plural: "jaar",
|
|
87
|
+
article: "het",
|
|
83
88
|
current: "dit jaar",
|
|
84
89
|
previous: "vorig jaar",
|
|
85
90
|
next: "volgend jaar",
|
|
@@ -87,18 +92,58 @@ const units = [
|
|
|
87
92
|
remaining: "rest van het jaar"
|
|
88
93
|
}
|
|
89
94
|
];
|
|
90
|
-
const
|
|
95
|
+
const afterVan = (period) => period.startsWith("van ") ? period.slice(4) : period;
|
|
91
96
|
const unitAliases = [
|
|
92
|
-
[
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
[
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
97
|
+
[
|
|
98
|
+
"dag",
|
|
99
|
+
"day",
|
|
100
|
+
"singular"
|
|
101
|
+
],
|
|
102
|
+
[
|
|
103
|
+
"dagen",
|
|
104
|
+
"day",
|
|
105
|
+
"plural"
|
|
106
|
+
],
|
|
107
|
+
[
|
|
108
|
+
"week",
|
|
109
|
+
"week",
|
|
110
|
+
"singular"
|
|
111
|
+
],
|
|
112
|
+
[
|
|
113
|
+
"weken",
|
|
114
|
+
"week",
|
|
115
|
+
"plural"
|
|
116
|
+
],
|
|
117
|
+
[
|
|
118
|
+
"maand",
|
|
119
|
+
"month",
|
|
120
|
+
"singular"
|
|
121
|
+
],
|
|
122
|
+
[
|
|
123
|
+
"maanden",
|
|
124
|
+
"month",
|
|
125
|
+
"plural"
|
|
126
|
+
],
|
|
127
|
+
[
|
|
128
|
+
"kwartaal",
|
|
129
|
+
"quarter",
|
|
130
|
+
"singular"
|
|
131
|
+
],
|
|
132
|
+
[
|
|
133
|
+
"kwartalen",
|
|
134
|
+
"quarter",
|
|
135
|
+
"plural"
|
|
136
|
+
],
|
|
137
|
+
[
|
|
138
|
+
"jaar",
|
|
139
|
+
"year",
|
|
140
|
+
"both"
|
|
141
|
+
],
|
|
142
|
+
[
|
|
143
|
+
"jaren",
|
|
144
|
+
"year",
|
|
145
|
+
"plural"
|
|
146
|
+
]
|
|
102
147
|
];
|
|
103
148
|
const periodAliases = [
|
|
104
149
|
...units.flatMap((entry) => [
|
|
@@ -300,17 +345,30 @@ const monthNumber = (value) => {
|
|
|
300
345
|
return short === -1 ? void 0 : short + 1;
|
|
301
346
|
};
|
|
302
347
|
const dateLabel = (day, month, year) => `${day} ${textAt(months, month - 1)} ${year}`;
|
|
348
|
+
const currentDateLabel = (day, month) => `${day} ${textAt(months, month - 1)}`;
|
|
303
349
|
const parseNamedDate = (input) => {
|
|
304
350
|
const named = String$1.match(/^(?:de )?([0-3]?\d)(?:e|ste|de)?(?: van)? ([a-z]+\.?)(?: van)? (\d{4})$/u)(input);
|
|
305
351
|
if (Option.isSome(named)) return namedDatePeriod(textAt(named.value, 3), textAt(named.value, 2), textAt(named.value, 1), monthNumber, dateLabel);
|
|
306
352
|
const numeric = String$1.match(/^([0-3]?\d)[./-]([01]?\d)[./-](\d{4})$/u)(input);
|
|
307
|
-
if (Option.
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
353
|
+
if (Option.isSome(numeric)) {
|
|
354
|
+
const year = validYear(textAt(numeric.value, 3));
|
|
355
|
+
const month = Number(textAt(numeric.value, 2));
|
|
356
|
+
const day = Number(textAt(numeric.value, 1));
|
|
357
|
+
if (year !== void 0 && month >= 1 && month <= 12) {
|
|
358
|
+
const value = isoDate(year, month, day);
|
|
359
|
+
if (isIsoDate(value) && value !== "9999-12-31") return Option.some(fixedDatePeriod(value, dateLabel(day, month, year)));
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
const current = String$1.match(/^(?:de )?([0-3]?\d)(?:e|ste|de)?(?: van)? ([a-z]+\.?)$/u)(input);
|
|
363
|
+
if (Option.isSome(current)) return namedCurrentYearDatePeriod(textAt(current.value, 2), textAt(current.value, 1), monthNumber, currentDateLabel);
|
|
364
|
+
const relative = String$1.match(/^(?:de )?([0-3]?\d)(?:e|ste|de)? van (.+)$/u)(input);
|
|
365
|
+
if (Option.isNone(relative)) return Option.none();
|
|
366
|
+
const periodText = textAt(relative.value, 2);
|
|
367
|
+
const alias = periodAliases.find((entry) => entry[0] === periodText && entry[1] === "month");
|
|
368
|
+
if (alias === void 0) return Option.none();
|
|
369
|
+
const day = Number(textAt(relative.value, 1));
|
|
370
|
+
const month = relativePeriod(alias[1], alias[2], alias[3]);
|
|
371
|
+
return periodDay(month, day, `${day} van ${alias[3]}`);
|
|
314
372
|
};
|
|
315
373
|
const quarterNumber = (value) => {
|
|
316
374
|
if ((value.startsWith("q") || value.startsWith("k")) && value.length === 2) return Number(value.slice(1));
|
|
@@ -338,7 +396,8 @@ const parseQuarter = (input) => {
|
|
|
338
396
|
return quarter === void 0 ? Option.none() : Option.some(quarterOfRelativeYear(quarter, 0, `K${quarter}`));
|
|
339
397
|
};
|
|
340
398
|
const parseBasePeriod = (input) => {
|
|
341
|
-
|
|
399
|
+
const absoluteDate = absoluteDatePeriod(input, "nl");
|
|
400
|
+
if (Option.isSome(absoluteDate)) return absoluteDate;
|
|
342
401
|
const namedDate = parseNamedDate(input);
|
|
343
402
|
if (Option.isSome(namedDate)) return namedDate;
|
|
344
403
|
const quarter = parseQuarter(input);
|
|
@@ -352,7 +411,7 @@ const parseBasePeriod = (input) => {
|
|
|
352
411
|
if (Option.isSome(monthYear)) {
|
|
353
412
|
const month = monthNumber(textAt(monthYear.value, 1));
|
|
354
413
|
const year = validYear(textAt(monthYear.value, 2));
|
|
355
|
-
if (month !== void 0 && year !== void 0) return Option.some(fixedMonthPeriod(year, month, `${
|
|
414
|
+
if (month !== void 0 && year !== void 0) return Option.some(fixedMonthPeriod(year, month, `${textAt(months, month - 1)} ${year}`));
|
|
356
415
|
}
|
|
357
416
|
const relativeMonth = String$1.match(/^([a-z]+\.?)(?: van)? (vorig jaar|volgend jaar|dit jaar)$/u)(input);
|
|
358
417
|
const relativeMonthYearFirst = String$1.match(/^(vorig jaar|volgend jaar|dit jaar) ([a-z]+\.?)$/u)(input);
|
|
@@ -363,10 +422,10 @@ const parseBasePeriod = (input) => {
|
|
|
363
422
|
const yearText = textAt(relativeMatch.value, yearFirst ? 1 : 2);
|
|
364
423
|
const month = monthNumber(monthText);
|
|
365
424
|
const direction = relativeYearDirection(yearText);
|
|
366
|
-
if (month !== void 0) return Option.some(monthOfRelativeYear(month, direction, `${
|
|
425
|
+
if (month !== void 0) return Option.some(monthOfRelativeYear(month, direction, `${textAt(months, month - 1)} ${relativeYearName(direction)}`));
|
|
367
426
|
}
|
|
368
427
|
const standaloneMonth = monthNumber(input);
|
|
369
|
-
if (standaloneMonth !== void 0) return Option.some(monthOfRelativeYear(standaloneMonth, 0,
|
|
428
|
+
if (standaloneMonth !== void 0) return Option.some(monthOfRelativeYear(standaloneMonth, 0, textAt(months, standaloneMonth - 1)));
|
|
370
429
|
const alias = periodAliases.find((entry) => entry[0] === input);
|
|
371
430
|
if (alias !== void 0) return Option.some(relativePeriod(alias[1], alias[2], alias[3]));
|
|
372
431
|
if ([
|
|
@@ -408,32 +467,87 @@ const parsePeriod = (input) => {
|
|
|
408
467
|
].find((prefix) => input.startsWith(prefix));
|
|
409
468
|
return parseBasePeriod(wrapper === void 0 ? input : input.slice(wrapper.length));
|
|
410
469
|
};
|
|
411
|
-
const countedUnit = (value
|
|
470
|
+
const countedUnit = (value, amount) => {
|
|
471
|
+
const expected = amount === 1 ? "singular" : "plural";
|
|
472
|
+
const alias = unitAliases.find((entry) => entry[0] === value && (entry[2] === expected || entry[2] === "both"));
|
|
473
|
+
return alias === void 0 ? void 0 : units.find((entry) => entry.unit === alias[1]);
|
|
474
|
+
};
|
|
412
475
|
const countedUnitPattern = "dag|dagen|week|weken|maand|maanden|kwartaal|kwartalen|jaar|jaren";
|
|
413
476
|
const countedPattern = (source) => new RegExp(source.replace("UNIT", countedUnitPattern), "u");
|
|
414
477
|
const calendarPastPattern = countedPattern("^([1-9]\\d*) (UNIT) geleden$");
|
|
415
478
|
const calendarFuturePatterns = [countedPattern("^(?:over|binnen) ([1-9]\\d*) (UNIT)$"), countedPattern("^([1-9]\\d*) (UNIT) later$")];
|
|
416
|
-
const rollingPastPatterns = [countedPattern("^(?:de )?(?:afgelopen|laatste|vorige) ([1-9]\\d*) (UNIT)$"), countedPattern("^([1-9]\\d*) (?:afgelopen|laatste|vorige) (UNIT)$")];
|
|
417
|
-
const rollingFuturePatterns = [countedPattern("^(?:de )?(?:komende|volgende|aankomende) ([1-9]\\d*) (UNIT)$"), countedPattern("^([1-9]\\d*) (?:komende|volgende|aankomende) (UNIT)$")];
|
|
479
|
+
const rollingPastPatterns = [countedPattern("^(?:(?:de|in de) )?(?:afgelopen|laatste|vorige) ([1-9]\\d*) (UNIT)$"), countedPattern("^([1-9]\\d*) (?:afgelopen|laatste|vorige) (UNIT)$")];
|
|
480
|
+
const rollingFuturePatterns = [countedPattern("^(?:(?:de|in de|binnen de) )?(?:komende|volgende|aankomende) ([1-9]\\d*) (UNIT)$"), countedPattern("^([1-9]\\d*) (?:komende|volgende|aankomende) (UNIT)$")];
|
|
418
481
|
const rollingSincePattern = countedPattern("^(?:sinds|gedurende) ([1-9]\\d*) (UNIT)$");
|
|
419
482
|
const rollingBarePattern = countedPattern("^([1-9]\\d*) (UNIT)$");
|
|
420
483
|
const firstPatternMatch = (input, patterns) => Option.firstSomeOf(patterns.map((pattern) => String$1.match(pattern)(input)));
|
|
484
|
+
const singularRollingCanonical = (entry, future) => future ? `vanaf nu gedurende een ${entry.singular}` : `sinds een ${entry.singular}`;
|
|
485
|
+
const singularRollingPhrases = units.flatMap((entry) => [
|
|
486
|
+
{
|
|
487
|
+
phrase: `${entry.article} afgelopen ${entry.singular}`,
|
|
488
|
+
entry,
|
|
489
|
+
future: false
|
|
490
|
+
},
|
|
491
|
+
{
|
|
492
|
+
phrase: `${entry.article} laatste ${entry.singular}`,
|
|
493
|
+
entry,
|
|
494
|
+
future: false
|
|
495
|
+
},
|
|
496
|
+
{
|
|
497
|
+
phrase: `sinds een ${entry.singular}`,
|
|
498
|
+
entry,
|
|
499
|
+
future: false
|
|
500
|
+
},
|
|
501
|
+
{
|
|
502
|
+
phrase: `gedurende ${entry.article} komende ${entry.singular}`,
|
|
503
|
+
entry,
|
|
504
|
+
future: true
|
|
505
|
+
},
|
|
506
|
+
{
|
|
507
|
+
phrase: `vanaf nu gedurende een ${entry.singular}`,
|
|
508
|
+
entry,
|
|
509
|
+
future: true
|
|
510
|
+
}
|
|
511
|
+
]);
|
|
512
|
+
const singularCalendarOffsets = units.flatMap((entry) => [
|
|
513
|
+
{
|
|
514
|
+
phrase: `een ${entry.singular} geleden`,
|
|
515
|
+
entry,
|
|
516
|
+
direction: -1
|
|
517
|
+
},
|
|
518
|
+
{
|
|
519
|
+
phrase: `over een ${entry.singular}`,
|
|
520
|
+
entry,
|
|
521
|
+
direction: 1
|
|
522
|
+
},
|
|
523
|
+
{
|
|
524
|
+
phrase: `binnen een ${entry.singular}`,
|
|
525
|
+
entry,
|
|
526
|
+
direction: 1
|
|
527
|
+
}
|
|
528
|
+
]);
|
|
421
529
|
const parseCalendarOffset = (input) => {
|
|
530
|
+
const singular = singularCalendarOffsets.find((entry) => entry.phrase === input);
|
|
531
|
+
if (singular !== void 0) return Option.some(candidate(periodRange(relativePeriod(singular.entry.unit, singular.direction, singular.phrase)), singular.phrase));
|
|
422
532
|
const past = String$1.match(calendarPastPattern)(input);
|
|
423
533
|
const future = firstPatternMatch(input, calendarFuturePatterns);
|
|
424
534
|
const match = Option.firstSomeOf([past, future]);
|
|
425
535
|
if (Option.isNone(match)) return Option.none();
|
|
426
536
|
const amount = parseTrailingCount(textAt(match.value, 1));
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
const entry = units.find((item) => item.unit === unit);
|
|
537
|
+
if (Option.isNone(amount)) return Option.none();
|
|
538
|
+
const entry = countedUnit(textAt(match.value, 2), amount.value);
|
|
430
539
|
if (entry === void 0) return Option.none();
|
|
431
540
|
const direction = Option.isSome(past) ? -amount.value : amount.value;
|
|
432
541
|
const noun = amount.value === 1 ? entry.singular : entry.plural;
|
|
433
542
|
const canonical = direction < 0 ? `${amount.value} ${noun} geleden` : `over ${amount.value} ${noun}`;
|
|
434
|
-
return Option.some(candidate(periodRange(relativePeriod(unit, direction, canonical)), canonical));
|
|
543
|
+
return Option.some(candidate(periodRange(relativePeriod(entry.unit, direction, canonical)), canonical));
|
|
435
544
|
};
|
|
436
545
|
const parseRollingPeriod = (input) => {
|
|
546
|
+
const singular = singularRollingPhrases.find((entry) => entry.phrase === input);
|
|
547
|
+
if (singular !== void 0) {
|
|
548
|
+
const range = singular.future ? futureRange(1, singular.entry.unit) : trailingRange(1, singular.entry.unit);
|
|
549
|
+
return Option.some(candidate(range, singularRollingCanonical(singular.entry, singular.future)));
|
|
550
|
+
}
|
|
437
551
|
const since = String$1.match(rollingSincePattern)(input);
|
|
438
552
|
const past = firstPatternMatch(input, rollingPastPatterns);
|
|
439
553
|
const bare = String$1.match(rollingBarePattern)(input);
|
|
@@ -446,15 +560,26 @@ const parseRollingPeriod = (input) => {
|
|
|
446
560
|
]);
|
|
447
561
|
if (Option.isNone(match)) return Option.none();
|
|
448
562
|
const amount = parseTrailingCount(textAt(match.value, 1));
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
const entry = units.find((item) => item.unit === unit);
|
|
563
|
+
if (Option.isNone(amount)) return Option.none();
|
|
564
|
+
const entry = countedUnit(textAt(match.value, 2), amount.value);
|
|
452
565
|
if (entry === void 0) return Option.none();
|
|
453
566
|
const isFuture = Option.isSome(future);
|
|
454
|
-
const range = isFuture ? futureRange(amount.value, unit) : trailingRange(amount.value, unit);
|
|
567
|
+
const range = isFuture ? futureRange(amount.value, entry.unit) : trailingRange(amount.value, entry.unit);
|
|
568
|
+
if (amount.value === 1) return Option.some(candidate(range, singularRollingCanonical(entry, isFuture)));
|
|
455
569
|
const modifier = isFuture ? "komende" : "afgelopen";
|
|
456
|
-
|
|
457
|
-
|
|
570
|
+
return Option.some(candidate(range, `de ${modifier} ${amount.value} ${entry.plural}`));
|
|
571
|
+
};
|
|
572
|
+
const parseElidedDateRange = (input) => {
|
|
573
|
+
const joined = String$1.match(/^(?:van ([0-3]?\d) tot(?: en met)?|tussen (?:de )?([0-3]?\d)(?:e)? en(?: de)?) ([0-3]?\d)(?:e)? (.+)$/u)(input);
|
|
574
|
+
const dashed = String$1.match(/^([0-3]?\d)[–—-]([0-3]?\d) (.+)$/u)(input);
|
|
575
|
+
const match = Option.firstSomeOf([joined, dashed]);
|
|
576
|
+
if (Option.isNone(match)) return Option.none();
|
|
577
|
+
const isJoined = Option.isSome(joined);
|
|
578
|
+
const lowerDay = textAt(match.value, 1) || textAt(match.value, 2);
|
|
579
|
+
const upperDay = textAt(match.value, isJoined ? 3 : 2);
|
|
580
|
+
const period = afterVan(textAt(match.value, isJoined ? 4 : 3));
|
|
581
|
+
const suffix = periodAliases.some((entry) => entry[0] === period && entry[1] === "month") ? `van ${period}` : period;
|
|
582
|
+
return joinedPeriodCandidate(`van ${lowerDay} ${suffix} tot en met ${upperDay} ${suffix}`, [["van ", " tot en met "]], parsePeriod, (lower, upper) => `van ${lower} tot en met ${upper}`);
|
|
458
583
|
};
|
|
459
584
|
const boundaryCandidate = (input) => openBoundaryCandidate(input, [
|
|
460
585
|
["tot voor ", "before"],
|
|
@@ -485,6 +610,8 @@ const parseDutch = (input) => {
|
|
|
485
610
|
if (Option.isSome(rolling)) return rolling;
|
|
486
611
|
const toDate = toDatePhrases.find((entry) => entry.phrase === input);
|
|
487
612
|
if (toDate !== void 0) return Option.some(candidate(periodToDateRange(toDate.entry.unit), toDate.entry.toDate));
|
|
613
|
+
const elided = parseElidedDateRange(input);
|
|
614
|
+
if (Option.isSome(elided)) return elided;
|
|
488
615
|
const nowBounded = joinedNowCandidate(input, [
|
|
489
616
|
["vanaf ", " tot nu toe"],
|
|
490
617
|
["sinds ", " tot nu toe"],
|
|
@@ -508,16 +635,28 @@ const parseDutch = (input) => {
|
|
|
508
635
|
if (Option.isSome(bounded)) return bounded;
|
|
509
636
|
const boundary = boundaryCandidate(input);
|
|
510
637
|
if (Option.isSome(boundary)) return boundary;
|
|
511
|
-
return Option.map(
|
|
638
|
+
return parsePeriod(input).pipe(Option.map((period) => candidate(periodRange(period), period.canonical)));
|
|
512
639
|
};
|
|
513
|
-
const
|
|
514
|
-
...periodAliases.map((entry) => entry[0]),
|
|
640
|
+
const weekendPhrases = [
|
|
515
641
|
"dit weekend",
|
|
516
642
|
"vorig weekend",
|
|
517
643
|
"volgend weekend",
|
|
518
644
|
"het weekend voor het vorige",
|
|
519
|
-
"het weekend na het volgende"
|
|
520
|
-
|
|
645
|
+
"het weekend na het volgende"
|
|
646
|
+
];
|
|
647
|
+
const edgePeriodPhrases = [
|
|
648
|
+
...units.filter((entry) => entry.unit !== "day").flatMap((entry) => [
|
|
649
|
+
entry.current,
|
|
650
|
+
entry.previous,
|
|
651
|
+
entry.next
|
|
652
|
+
]),
|
|
653
|
+
...weekendPhrases,
|
|
654
|
+
...months
|
|
655
|
+
].flatMap((period) => [`begin van ${period}`, `eind van ${period}`]);
|
|
656
|
+
const staticPeriodPhrases = [
|
|
657
|
+
...periodAliases.map((entry) => entry[0]),
|
|
658
|
+
...weekendPhrases,
|
|
659
|
+
...edgePeriodPhrases,
|
|
521
660
|
...[
|
|
522
661
|
1,
|
|
523
662
|
2,
|
|
@@ -563,6 +702,8 @@ const countedSuggestions = (input) => {
|
|
|
563
702
|
const dutchSuggestionPhrases = [
|
|
564
703
|
...units.map((entry) => entry.toDate),
|
|
565
704
|
...units.map((entry) => entry.remaining),
|
|
705
|
+
...singularRollingPhrases.map((entry) => entry.phrase),
|
|
706
|
+
...singularCalendarOffsets.map((entry) => entry.phrase),
|
|
566
707
|
...staticPeriodPhrases,
|
|
567
708
|
...prefixNaturalPhrases(staticPeriodPhrases, boundaryPrefixes),
|
|
568
709
|
"tot nu toe",
|
|
@@ -590,20 +731,18 @@ const renderDutch = (range) => {
|
|
|
590
731
|
const future = futurePeriod(range);
|
|
591
732
|
if (Option.isSome(future)) {
|
|
592
733
|
const entry = units.find((unit) => unit.unit === future.value.unit);
|
|
593
|
-
if (entry !== void 0) {
|
|
594
|
-
const noun = future.value.amount === 1 ? entry.singular : entry.plural;
|
|
595
|
-
return Option.some(`de komende ${future.value.amount} ${noun}`);
|
|
596
|
-
}
|
|
734
|
+
if (entry !== void 0) return Option.some(future.value.amount === 1 ? singularRollingCanonical(entry, true) : `de komende ${future.value.amount} ${entry.plural}`);
|
|
597
735
|
}
|
|
598
736
|
const trailing = trailingPeriod(range);
|
|
599
737
|
if (Option.isSome(trailing)) {
|
|
600
738
|
const entry = units.find((unit) => unit.unit === trailing.value.unit);
|
|
601
|
-
if (entry !== void 0) {
|
|
602
|
-
const noun = trailing.value.amount === 1 ? entry.singular : entry.plural;
|
|
603
|
-
return Option.some(`de afgelopen ${trailing.value.amount} ${noun}`);
|
|
604
|
-
}
|
|
739
|
+
if (entry !== void 0) return Option.some(trailing.value.amount === 1 ? singularRollingCanonical(entry, false) : `de afgelopen ${trailing.value.amount} ${entry.plural}`);
|
|
605
740
|
}
|
|
606
|
-
const periods = [
|
|
741
|
+
const periods = [
|
|
742
|
+
...staticPeriods,
|
|
743
|
+
...currentYearDatePeriods(range, currentDateLabel),
|
|
744
|
+
...periodsFromPhrases([...datedPeriods(range, months), ...datedQuarterPeriods(range).map((phrase) => phrase.startsWith("Q") ? `K${phrase.slice(1)}` : phrase)], parsePeriod)
|
|
745
|
+
];
|
|
607
746
|
return renderPeriodRange(range, [...units.map((entry) => candidate(periodToDateRange(entry.unit), entry.toDate)), ...units.map((entry) => candidate(remainingPeriodRange(entry.unit), entry.remaining))], periods, (period) => `vanaf ${period}`, (period) => `voor ${period}`, (period) => `tot en met ${period}`, (period) => `na ${period}`, (lower, upper) => `van ${lower} tot en met ${upper}`, (period) => `vanaf ${period} tot nu toe`, (period) => `vanaf nu tot en met ${period}`, () => "tot nu toe", () => "vanaf nu");
|
|
608
747
|
};
|
|
609
748
|
const DutchContribution = new BaseLanguageContribution({
|