cronli5 0.1.4 → 0.1.5
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/CHANGELOG.md +25 -0
- package/cronli5.min.js +2 -2
- package/dist/cronli5.cjs +180 -36
- package/dist/cronli5.js +180 -36
- package/dist/lang/de.cjs +172 -8
- package/dist/lang/de.js +172 -8
- package/dist/lang/en.cjs +175 -29
- package/dist/lang/en.js +175 -29
- package/dist/lang/es.cjs +180 -25
- package/dist/lang/es.js +180 -25
- package/dist/lang/fi.cjs +188 -40
- package/dist/lang/fi.js +188 -40
- package/dist/lang/zh.cjs +165 -19
- package/dist/lang/zh.js +165 -19
- package/package.json +2 -1
- package/src/core/analyze.ts +7 -0
- package/src/core/ir.ts +1 -1
- package/src/core/util.ts +31 -1
- package/src/lang/de/index.ts +360 -16
- package/src/lang/en/index.ts +333 -33
- package/src/lang/es/index.ts +373 -40
- package/src/lang/fi/index.ts +404 -72
- package/src/lang/zh/index.ts +327 -35
- package/types/core/ir.d.ts +1 -1
- package/types/core/util.d.ts +6 -1
package/dist/cronli5.js
CHANGED
|
@@ -69,6 +69,21 @@ function isNonNegativeInteger(value) {
|
|
|
69
69
|
const digits = /^\d+$/;
|
|
70
70
|
return digits.test(value);
|
|
71
71
|
}
|
|
72
|
+
function arithmeticStep(values) {
|
|
73
|
+
if (values.length < 5) {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
const interval = values[1] - values[0];
|
|
77
|
+
if (interval < 2) {
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
for (let i = 2; i < values.length; i += 1) {
|
|
81
|
+
if (values[i] - values[i - 1] !== interval) {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return { start: values[0], interval, last: values[values.length - 1] };
|
|
86
|
+
}
|
|
72
87
|
function toFieldNumber(token, numberMap) {
|
|
73
88
|
return isNonNegativeInteger(token) ? +token : numberMap[token.toUpperCase()];
|
|
74
89
|
}
|
|
@@ -599,7 +614,7 @@ function planStandaloneSeconds(pattern, shapes) {
|
|
|
599
614
|
}
|
|
600
615
|
return { kind: "standaloneSeconds" };
|
|
601
616
|
}
|
|
602
|
-
function planMinutes(pattern, shapes, analyses,
|
|
617
|
+
function planMinutes(pattern, shapes, analyses, subMinuteSecond2 = false) {
|
|
603
618
|
if (shapes.minute === "step") {
|
|
604
619
|
return {
|
|
605
620
|
hours: planFrequencyHours(pattern, shapes, analyses),
|
|
@@ -622,7 +637,7 @@ function planMinutes(pattern, shapes, analyses, subMinuteSecond = false) {
|
|
|
622
637
|
return underStep;
|
|
623
638
|
}
|
|
624
639
|
if (pattern.hour === "*") {
|
|
625
|
-
return planMinutesUnderOpenHour(pattern, shapes,
|
|
640
|
+
return planMinutesUnderOpenHour(pattern, shapes, subMinuteSecond2);
|
|
626
641
|
}
|
|
627
642
|
}
|
|
628
643
|
function cleanHourStride(hourField) {
|
|
@@ -644,6 +659,9 @@ function planMinuteUnderHourStep(pattern, shapes) {
|
|
|
644
659
|
if (shapes.minute === "range") {
|
|
645
660
|
return { form: "range", kind: "minuteSpanAcrossHourStep" };
|
|
646
661
|
}
|
|
662
|
+
if (shapes.minute === "list" && cleanHourStride(pattern.hour)) {
|
|
663
|
+
return { form: "list", kind: "minuteSpanAcrossHourStep" };
|
|
664
|
+
}
|
|
647
665
|
return null;
|
|
648
666
|
}
|
|
649
667
|
function planFrequencyHours(pattern, shapes, analyses) {
|
|
@@ -692,7 +710,7 @@ function planMinutesAcrossHours(pattern, shapes) {
|
|
|
692
710
|
}
|
|
693
711
|
return null;
|
|
694
712
|
}
|
|
695
|
-
function planMinutesUnderOpenHour(pattern, shapes,
|
|
713
|
+
function planMinutesUnderOpenHour(pattern, shapes, subMinuteSecond2) {
|
|
696
714
|
if (shapes.minute === "range") {
|
|
697
715
|
return { kind: "rangeOfMinutes" };
|
|
698
716
|
}
|
|
@@ -702,16 +720,16 @@ function planMinutesUnderOpenHour(pattern, shapes, subMinuteSecond) {
|
|
|
702
720
|
if (pattern.minute === "*") {
|
|
703
721
|
return { kind: "everyMinute" };
|
|
704
722
|
}
|
|
705
|
-
if (pattern.minute !== "0" ||
|
|
723
|
+
if (pattern.minute !== "0" || subMinuteSecond2) {
|
|
706
724
|
return { kind: "singleMinute" };
|
|
707
725
|
}
|
|
708
726
|
}
|
|
709
|
-
function planHours(pattern, shapes, analyses,
|
|
710
|
-
const absorbsMinuteZero =
|
|
727
|
+
function planHours(pattern, shapes, analyses, subMinuteSecond2 = false) {
|
|
728
|
+
const absorbsMinuteZero = subMinuteSecond2 && pattern.minute === "0";
|
|
711
729
|
if (shapes.hour === "range" && !absorbsMinuteZero) {
|
|
712
730
|
return planHourRange(pattern, shapes, analyses);
|
|
713
731
|
}
|
|
714
|
-
if (shapes.hour === "step" && pattern.minute === "0" && !
|
|
732
|
+
if (shapes.hour === "step" && pattern.minute === "0" && !subMinuteSecond2) {
|
|
715
733
|
return { kind: "hourStep" };
|
|
716
734
|
}
|
|
717
735
|
if (pattern.hour === "*" && !absorbsMinuteZero) {
|
|
@@ -926,7 +944,15 @@ function renderSecondsWithinMinute(ir, plan, opts) {
|
|
|
926
944
|
}
|
|
927
945
|
return secondsLeadClause(ir, opts) + ", " + minuteWord + " " + minuteUnit + " past the hour, every hour" + trailingQualifier(ir, opts);
|
|
928
946
|
}
|
|
947
|
+
function composeHourCadence(ir, plan, opts) {
|
|
948
|
+
const clockRest = plan.rest.kind === "clockTimes" || plan.rest.kind === "compactClockTimes";
|
|
949
|
+
return clockRest && ir.shapes.minute === "single" ? hourCadence(ir, +ir.pattern.minute, opts) : null;
|
|
950
|
+
}
|
|
929
951
|
function renderComposeSeconds(ir, plan, opts) {
|
|
952
|
+
const cadence = composeHourCadence(ir, plan, opts);
|
|
953
|
+
if (cadence !== null) {
|
|
954
|
+
return cadence;
|
|
955
|
+
}
|
|
930
956
|
if (plan.rest.kind === "clockTimes" && (ir.shapes.second === "wildcard" || ir.shapes.second === "step")) {
|
|
931
957
|
const minute = plan.rest.times[0].minute;
|
|
932
958
|
if (+minute === 0) {
|
|
@@ -959,6 +985,9 @@ function clockTimesOf(ir, plan, opts) {
|
|
|
959
985
|
return joinList(times, opts) + (trail && ", " + trail);
|
|
960
986
|
}
|
|
961
987
|
function secondsLeadClause(ir, opts) {
|
|
988
|
+
return secondsClause(ir, "minute", opts);
|
|
989
|
+
}
|
|
990
|
+
function secondsClause(ir, anchor, opts) {
|
|
962
991
|
const secondField = ir.pattern.second;
|
|
963
992
|
const shape = ir.shapes.second;
|
|
964
993
|
if (secondField === "*") {
|
|
@@ -968,22 +997,27 @@ function secondsLeadClause(ir, opts) {
|
|
|
968
997
|
return stepCycle60(
|
|
969
998
|
ir.analyses.segments.second[0],
|
|
970
999
|
"second",
|
|
971
|
-
|
|
1000
|
+
anchor,
|
|
972
1001
|
opts
|
|
973
1002
|
);
|
|
974
1003
|
}
|
|
975
1004
|
if (shape === "range") {
|
|
976
1005
|
const bounds = secondField.split("-");
|
|
977
1006
|
const num = seriesNumber(bounds, opts);
|
|
978
|
-
return "every second from " + num(bounds[0]) + through(opts) + num(bounds[1]) + " past the
|
|
1007
|
+
return "every second from " + num(bounds[0]) + through(opts) + num(bounds[1]) + " past the " + anchor;
|
|
979
1008
|
}
|
|
980
1009
|
if (shape === "single") {
|
|
981
|
-
return "at " + getNumber(secondField, opts) + " " + pluralize(secondField, "second") + " past the
|
|
1010
|
+
return "at " + getNumber(secondField, opts) + " " + pluralize(secondField, "second") + " past the " + anchor;
|
|
982
1011
|
}
|
|
983
|
-
return
|
|
1012
|
+
return strideFromSegments(
|
|
1013
|
+
ir.analyses.segments.second,
|
|
1014
|
+
"second",
|
|
1015
|
+
anchor,
|
|
1016
|
+
opts
|
|
1017
|
+
) ?? listPastThe(
|
|
984
1018
|
segmentWords(ir.analyses.segments.second, opts),
|
|
985
1019
|
"second",
|
|
986
|
-
|
|
1020
|
+
anchor,
|
|
987
1021
|
opts
|
|
988
1022
|
);
|
|
989
1023
|
}
|
|
@@ -998,12 +1032,11 @@ function renderRangeOfMinutes(ir, plan, opts) {
|
|
|
998
1032
|
return minuteRangeLead(ir.pattern.minute, opts) + trailingQualifier(ir, opts);
|
|
999
1033
|
}
|
|
1000
1034
|
function renderMultipleMinutes(ir, plan, opts) {
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
"hour",
|
|
1035
|
+
const stride = strideFromSegments(ir.analyses.segments.minute, "minute", "hour", opts);
|
|
1036
|
+
return (stride ?? listPastThe(segmentWords(
|
|
1037
|
+
ir.analyses.segments.minute,
|
|
1005
1038
|
opts
|
|
1006
|
-
) + trailingQualifier(ir, opts);
|
|
1039
|
+
), "minute", "hour", opts)) + trailingQualifier(ir, opts);
|
|
1007
1040
|
}
|
|
1008
1041
|
function renderMinuteFrequency(ir, plan, opts) {
|
|
1009
1042
|
let phrase = stepCycle60(
|
|
@@ -1033,8 +1066,9 @@ function renderMinutesAcrossHours(ir, plan, opts) {
|
|
|
1033
1066
|
}
|
|
1034
1067
|
const times = hourTimesFromPlan(ir, plan.times, true, opts);
|
|
1035
1068
|
const lead = plan.form === "range" ? minuteRangeLead(ir.pattern.minute, opts) : (
|
|
1036
|
-
// The 'list' form is a minute list, which has segments
|
|
1037
|
-
|
|
1069
|
+
// The 'list' form is a minute list, which has segments; an offset/uneven
|
|
1070
|
+
// step enumerated to that list reads as a stride.
|
|
1071
|
+
strideFromSegments(ir.analyses.segments.minute, "minute", "hour", opts) ?? listPastThe(
|
|
1038
1072
|
segmentWords(ir.analyses.segments.minute, opts),
|
|
1039
1073
|
"minute",
|
|
1040
1074
|
"hour",
|
|
@@ -1061,7 +1095,13 @@ function renderMinuteSpanAcrossHourStep(ir, plan, opts) {
|
|
|
1061
1095
|
if (plan.form === "wildcard") {
|
|
1062
1096
|
return "every minute " + everyNthHour(segment, opts) + trailingQualifier(ir, opts);
|
|
1063
1097
|
}
|
|
1064
|
-
|
|
1098
|
+
const lead = plan.form === "list" ? strideFromSegments(ir.analyses.segments.minute, "minute", "hour", opts) ?? listPastThe(
|
|
1099
|
+
segmentWords(ir.analyses.segments.minute, opts),
|
|
1100
|
+
"minute",
|
|
1101
|
+
"hour",
|
|
1102
|
+
opts
|
|
1103
|
+
) : minuteRangeLead(ir.pattern.minute, opts);
|
|
1104
|
+
return lead + ", " + stepHours(segment, opts) + trailingQualifier(ir, opts);
|
|
1065
1105
|
}
|
|
1066
1106
|
function minuteRangeLead(minuteField, opts) {
|
|
1067
1107
|
const bounds = minuteField.split("-");
|
|
@@ -1085,7 +1125,12 @@ function rangeMinuteLead(ir, opts) {
|
|
|
1085
1125
|
if (ir.pattern.minute === "0") {
|
|
1086
1126
|
return "every hour";
|
|
1087
1127
|
}
|
|
1088
|
-
return
|
|
1128
|
+
return strideFromSegments(
|
|
1129
|
+
ir.analyses.segments.minute,
|
|
1130
|
+
"minute",
|
|
1131
|
+
"hour",
|
|
1132
|
+
opts
|
|
1133
|
+
) ?? listPastThe(
|
|
1089
1134
|
segmentWords(ir.analyses.segments.minute, opts),
|
|
1090
1135
|
"minute",
|
|
1091
1136
|
"hour",
|
|
@@ -1102,6 +1147,12 @@ function hourWindow(window, opts) {
|
|
|
1102
1147
|
return "from " + getTime({ hour: window.from, minute: 0 }, opts) + through(opts) + getTime({ hour: window.to, minute: window.last }, opts);
|
|
1103
1148
|
}
|
|
1104
1149
|
function renderClockTimes(ir, plan, opts) {
|
|
1150
|
+
if (ir.shapes.minute === "single") {
|
|
1151
|
+
const cadence = hourCadence(ir, +ir.pattern.minute, opts);
|
|
1152
|
+
if (cadence !== null) {
|
|
1153
|
+
return cadence;
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1105
1156
|
const plain = mixedTwelve(plan.times);
|
|
1106
1157
|
const times = plan.times.map(function clock(time) {
|
|
1107
1158
|
return getTime({
|
|
@@ -1115,6 +1166,10 @@ function renderClockTimes(ir, plan, opts) {
|
|
|
1115
1166
|
}
|
|
1116
1167
|
function renderCompactClockTimes(ir, plan, opts) {
|
|
1117
1168
|
if (plan.fold) {
|
|
1169
|
+
const cadence = hourCadence(ir, +plan.minute, opts);
|
|
1170
|
+
if (cadence !== null) {
|
|
1171
|
+
return cadence;
|
|
1172
|
+
}
|
|
1118
1173
|
const hasRange = ir.analyses.segments.hour.some(function range(segment) {
|
|
1119
1174
|
return segment.kind === "range";
|
|
1120
1175
|
});
|
|
@@ -1125,13 +1180,14 @@ function renderCompactClockTimes(ir, plan, opts) {
|
|
|
1125
1180
|
return interpretDayQualifier(ir, opts) + "at " + hourSegmentTimes(ir, fold, true, opts);
|
|
1126
1181
|
}
|
|
1127
1182
|
const phrase = (
|
|
1128
|
-
// The non-fold branch is a minute list, which has segments.
|
|
1129
|
-
|
|
1183
|
+
// The non-fold branch is a minute list, which has segments. An
|
|
1184
|
+
// offset/uneven step enumerated to that list reads as a stride.
|
|
1185
|
+
(strideFromSegments(ir.analyses.segments.minute, "minute", "hour", opts) ?? listPastThe(
|
|
1130
1186
|
segmentWords(ir.analyses.segments.minute, opts),
|
|
1131
1187
|
"minute",
|
|
1132
1188
|
"hour",
|
|
1133
1189
|
opts
|
|
1134
|
-
) + ", at " + hourSegmentTimes(ir, { minute: 0, second: null }, true, opts) + trailingQualifier(ir, opts)
|
|
1190
|
+
)) + ", at " + hourSegmentTimes(ir, { minute: 0, second: null }, true, opts) + trailingQualifier(ir, opts)
|
|
1135
1191
|
);
|
|
1136
1192
|
return ir.analyses.clockSecond ? secondsLeadClause(ir, opts) + ", " + phrase : phrase;
|
|
1137
1193
|
}
|
|
@@ -1179,24 +1235,50 @@ var renderers = {
|
|
|
1179
1235
|
singleMinute: renderSingleMinute,
|
|
1180
1236
|
standaloneSeconds: renderStandaloneSeconds
|
|
1181
1237
|
};
|
|
1238
|
+
function renderStride(stride, opts) {
|
|
1239
|
+
const { interval, start, last, cycle, unit, anchor } = stride;
|
|
1240
|
+
const cadence = "every " + getNumber(interval, opts) + " " + unit + "s";
|
|
1241
|
+
const tiles = cycle % interval === 0;
|
|
1242
|
+
if (start === 0 && tiles) {
|
|
1243
|
+
return cadence;
|
|
1244
|
+
}
|
|
1245
|
+
if (start < interval && tiles) {
|
|
1246
|
+
return cadence + " from " + getNumber(start, opts) + " " + pluralize(start, unit) + " past the " + anchor;
|
|
1247
|
+
}
|
|
1248
|
+
const num = seriesNumber([start, last], opts);
|
|
1249
|
+
return cadence + " from " + num(start) + through(opts) + num(last) + " " + pluralize(last, unit) + " past the " + anchor;
|
|
1250
|
+
}
|
|
1251
|
+
function singleValues(segments) {
|
|
1252
|
+
const values = [];
|
|
1253
|
+
for (const segment of segments) {
|
|
1254
|
+
if (segment.kind !== "single") {
|
|
1255
|
+
return null;
|
|
1256
|
+
}
|
|
1257
|
+
values.push(+segment.value);
|
|
1258
|
+
}
|
|
1259
|
+
return values;
|
|
1260
|
+
}
|
|
1261
|
+
function strideFromSegments(segments, unit, anchor, opts) {
|
|
1262
|
+
const values = singleValues(segments);
|
|
1263
|
+
const step = values && arithmeticStep(values);
|
|
1264
|
+
return step ? renderStride({ ...step, cycle: 60, unit, anchor }, opts) : null;
|
|
1265
|
+
}
|
|
1182
1266
|
function stepCycle60(segment, unit, anchor, opts) {
|
|
1183
1267
|
if (segment.startToken.indexOf("-") !== -1) {
|
|
1184
1268
|
return listPastThe(numberWords(segment.fires, opts), unit, anchor, opts);
|
|
1185
1269
|
}
|
|
1186
1270
|
const start = segment.startToken === "*" ? 0 : +segment.startToken;
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
if (segment.fires.length <= 3) {
|
|
1190
|
-
return listPastThe(
|
|
1191
|
-
numberWords(segment.fires, opts),
|
|
1192
|
-
unit,
|
|
1193
|
-
anchor,
|
|
1194
|
-
opts
|
|
1195
|
-
);
|
|
1196
|
-
}
|
|
1197
|
-
return "every " + getNumber(interval, opts) + " " + unit + "s from " + getNumber(start, opts) + " " + pluralize(start, unit) + " past the " + anchor;
|
|
1271
|
+
if (start !== 0 && segment.fires.length <= 3) {
|
|
1272
|
+
return listPastThe(numberWords(segment.fires, opts), unit, anchor, opts);
|
|
1198
1273
|
}
|
|
1199
|
-
return
|
|
1274
|
+
return renderStride({
|
|
1275
|
+
interval: segment.interval,
|
|
1276
|
+
start,
|
|
1277
|
+
last: segment.fires[segment.fires.length - 1],
|
|
1278
|
+
cycle: 60,
|
|
1279
|
+
unit,
|
|
1280
|
+
anchor
|
|
1281
|
+
}, opts);
|
|
1200
1282
|
}
|
|
1201
1283
|
function stepHours(segment, opts) {
|
|
1202
1284
|
if (segment.startToken.indexOf("-") !== -1) {
|
|
@@ -1212,6 +1294,68 @@ function stepHours(segment, opts) {
|
|
|
1212
1294
|
}
|
|
1213
1295
|
return "every " + getNumber(interval, opts) + " hours from " + getTime({ hour: start, minute: 0 }, opts);
|
|
1214
1296
|
}
|
|
1297
|
+
function hourStrideCadence(stride, opts) {
|
|
1298
|
+
const { start, interval, last } = stride;
|
|
1299
|
+
const cadence = "every " + getNumber(interval, opts) + " hours";
|
|
1300
|
+
const tiles = 24 % interval === 0;
|
|
1301
|
+
if (start === 0 && tiles) {
|
|
1302
|
+
return cadence;
|
|
1303
|
+
}
|
|
1304
|
+
if (start < interval && tiles) {
|
|
1305
|
+
return cadence + " from " + getTime({ hour: start, minute: 0 }, opts);
|
|
1306
|
+
}
|
|
1307
|
+
return cadence + " from " + getTime({ hour: start, minute: 0 }, opts) + through(opts) + getTime({ hour: last, minute: 0 }, opts);
|
|
1308
|
+
}
|
|
1309
|
+
function hourStride(ir) {
|
|
1310
|
+
const segments = ir.analyses.segments.hour;
|
|
1311
|
+
if (segments.length === 1 && segments[0].kind === "step") {
|
|
1312
|
+
const segment = segments[0];
|
|
1313
|
+
const start = segment.startToken === "*" ? 0 : +segment.startToken.split("-")[0];
|
|
1314
|
+
return { interval: segment.interval, last: segment.fires[segment.fires.length - 1], start };
|
|
1315
|
+
}
|
|
1316
|
+
const values = singleValues(segments);
|
|
1317
|
+
const step = values && arithmeticStep(values);
|
|
1318
|
+
return step || null;
|
|
1319
|
+
}
|
|
1320
|
+
function subMinuteSecond(ir) {
|
|
1321
|
+
return ir.pattern.second === "*" || ir.shapes.second === "step";
|
|
1322
|
+
}
|
|
1323
|
+
function hourCadenceLead(ir, minute, opts) {
|
|
1324
|
+
if (minute === 0) {
|
|
1325
|
+
if (subMinuteSecond(ir)) {
|
|
1326
|
+
return secondsClause(ir, "minute", opts) + " for one minute";
|
|
1327
|
+
}
|
|
1328
|
+
return secondsClause(ir, "hour", opts);
|
|
1329
|
+
}
|
|
1330
|
+
const minutePhrase = getNumber(minute, opts) + " " + pluralize(minute, "minute") + " past the hour";
|
|
1331
|
+
if (ir.pattern.second === "0") {
|
|
1332
|
+
return minutePhrase;
|
|
1333
|
+
}
|
|
1334
|
+
return secondsClause(ir, "minute", opts) + ", " + minutePhrase;
|
|
1335
|
+
}
|
|
1336
|
+
function hourCadence(ir, minute, opts) {
|
|
1337
|
+
const stride = hourStride(ir);
|
|
1338
|
+
if (!stride) {
|
|
1339
|
+
return null;
|
|
1340
|
+
}
|
|
1341
|
+
const fires = (stride.last - stride.start) / stride.interval + 1;
|
|
1342
|
+
if (ir.pattern.second === "0" && fires <= maxClockTimes) {
|
|
1343
|
+
return null;
|
|
1344
|
+
}
|
|
1345
|
+
const confinement = minute === 0 && subMinuteSecond(ir) && cleanStrideSegment(ir);
|
|
1346
|
+
if (confinement) {
|
|
1347
|
+
return secondsClause(ir, "minute", opts) + " for one minute " + everyNthHour(confinement, opts) + trailingQualifier(ir, opts);
|
|
1348
|
+
}
|
|
1349
|
+
return hourCadenceLead(ir, minute, opts) + ", " + hourStrideCadence(stride, opts) + trailingQualifier(ir, opts);
|
|
1350
|
+
}
|
|
1351
|
+
function cleanStrideSegment(ir) {
|
|
1352
|
+
const segments = ir.analyses.segments.hour;
|
|
1353
|
+
const segment = segments.length === 1 && segments[0];
|
|
1354
|
+
if (!segment || segment.kind !== "step" || segment.startToken.indexOf("-") !== -1 || !(segment.interval in stepOrdinals)) {
|
|
1355
|
+
return null;
|
|
1356
|
+
}
|
|
1357
|
+
return segment;
|
|
1358
|
+
}
|
|
1215
1359
|
function seriesNumber(values, opts) {
|
|
1216
1360
|
const anyBig = values.some(function big(v) {
|
|
1217
1361
|
return +v > 10;
|
package/dist/lang/de.cjs
CHANGED
|
@@ -40,12 +40,28 @@ var weekdayNumbers = {
|
|
|
40
40
|
FRI: 5,
|
|
41
41
|
SAT: 6
|
|
42
42
|
};
|
|
43
|
+
var maxClockTimes = 6;
|
|
43
44
|
|
|
44
45
|
// src/core/util.ts
|
|
45
46
|
function isNonNegativeInteger(value) {
|
|
46
47
|
const digits = /^\d+$/;
|
|
47
48
|
return digits.test(value);
|
|
48
49
|
}
|
|
50
|
+
function arithmeticStep(values) {
|
|
51
|
+
if (values.length < 5) {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
const interval = values[1] - values[0];
|
|
55
|
+
if (interval < 2) {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
for (let i = 2; i < values.length; i += 1) {
|
|
59
|
+
if (values[i] - values[i - 1] !== interval) {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return { start: values[0], interval, last: values[values.length - 1] };
|
|
64
|
+
}
|
|
49
65
|
function toFieldNumber(token, numberMap) {
|
|
50
66
|
return isNonNegativeInteger(token) ? +token : numberMap[token.toUpperCase()];
|
|
51
67
|
}
|
|
@@ -112,6 +128,49 @@ function stepSegment(segments) {
|
|
|
112
128
|
function cleanStep(segment, cycle) {
|
|
113
129
|
return (segment.startToken === "*" || +segment.startToken === 0) && cycle % segment.interval === 0;
|
|
114
130
|
}
|
|
131
|
+
function renderStride(stride) {
|
|
132
|
+
const { interval, start, last, cycle, unit, anchor } = stride;
|
|
133
|
+
const cadence = everyN(interval, unit);
|
|
134
|
+
const tiles = cycle % interval === 0;
|
|
135
|
+
if (start === 0 && tiles) {
|
|
136
|
+
return cadence;
|
|
137
|
+
}
|
|
138
|
+
const tail = anchor ? " " + anchor : "";
|
|
139
|
+
if (start < interval && tiles) {
|
|
140
|
+
return cadence + " ab " + unit.singular + " " + start + tail;
|
|
141
|
+
}
|
|
142
|
+
return cadence + " von " + unit.singular + " " + start + " bis " + last + tail;
|
|
143
|
+
}
|
|
144
|
+
function stepClause(segment, unit, anchor) {
|
|
145
|
+
const start = segment.startToken === "*" ? 0 : +segment.startToken;
|
|
146
|
+
const short = start !== 0 && segment.fires.length <= 3;
|
|
147
|
+
if (segment.startToken.indexOf("-") !== -1 || short) {
|
|
148
|
+
return "in den " + unit.plural + " " + joinList(segment.fires.map(String)) + " " + anchor;
|
|
149
|
+
}
|
|
150
|
+
return renderStride({
|
|
151
|
+
interval: segment.interval,
|
|
152
|
+
start,
|
|
153
|
+
last: segment.fires[segment.fires.length - 1],
|
|
154
|
+
cycle: 60,
|
|
155
|
+
unit,
|
|
156
|
+
anchor
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
function singleValues(segments) {
|
|
160
|
+
const values = [];
|
|
161
|
+
for (const segment of segments) {
|
|
162
|
+
if (segment.kind !== "single") {
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
values.push(+segment.value);
|
|
166
|
+
}
|
|
167
|
+
return values;
|
|
168
|
+
}
|
|
169
|
+
function strideFromSegments(segments, unit, anchor) {
|
|
170
|
+
const values = singleValues(segments);
|
|
171
|
+
const step = values && arithmeticStep(values);
|
|
172
|
+
return step ? renderStride({ ...step, cycle: 60, unit, anchor }) : null;
|
|
173
|
+
}
|
|
115
174
|
var weekdayNames = [
|
|
116
175
|
"sonntags",
|
|
117
176
|
"montags",
|
|
@@ -178,6 +237,13 @@ function everyNthHour(segment) {
|
|
|
178
237
|
const start = segment.startToken === "*" ? 0 : +segment.startToken;
|
|
179
238
|
return start === 0 ? base : base + " ab " + start + " Uhr";
|
|
180
239
|
}
|
|
240
|
+
function confinedHourStride(segment) {
|
|
241
|
+
if (segment.startToken.indexOf("-") !== -1) {
|
|
242
|
+
return false;
|
|
243
|
+
}
|
|
244
|
+
const start = segment.startToken === "*" ? 0 : +segment.startToken;
|
|
245
|
+
return 24 % segment.interval === 0 && start < segment.interval;
|
|
246
|
+
}
|
|
181
247
|
function weekdayNoun(token) {
|
|
182
248
|
return weekdayNouns[toFieldNumber(token, weekdayNumbers)];
|
|
183
249
|
}
|
|
@@ -281,14 +347,17 @@ function countedPhrase(ir, field, singular, plural) {
|
|
|
281
347
|
return "in den " + plural + " " + joinList(fieldValues(ir, field));
|
|
282
348
|
}
|
|
283
349
|
function secondsLead(ir) {
|
|
350
|
+
return secondsClause(ir, "jeder Minute");
|
|
351
|
+
}
|
|
352
|
+
function secondsClause(ir, anchor) {
|
|
284
353
|
if (ir.pattern.second === "*") {
|
|
285
354
|
return "jede Sekunde";
|
|
286
355
|
}
|
|
287
356
|
const segments = ir.analyses.segments.second;
|
|
288
|
-
if (ir.shapes.second === "step"
|
|
289
|
-
return
|
|
357
|
+
if (ir.shapes.second === "step") {
|
|
358
|
+
return stepClause(stepSegment(segments), UNITS.second, anchor);
|
|
290
359
|
}
|
|
291
|
-
return countedPhrase(ir, "second", "Sekunde", "Sekunden") + "
|
|
360
|
+
return strideFromSegments(segments, UNITS.second, anchor) ?? countedPhrase(ir, "second", "Sekunde", "Sekunden") + " " + anchor;
|
|
292
361
|
}
|
|
293
362
|
function spanTime(hour, minute, sep) {
|
|
294
363
|
return hour + sep + pad(minute);
|
|
@@ -357,8 +426,15 @@ function renderEveryHour() {
|
|
|
357
426
|
function renderSeconds(ir) {
|
|
358
427
|
return secondsLead(ir);
|
|
359
428
|
}
|
|
429
|
+
function minutePastClause(ir) {
|
|
430
|
+
return strideFromSegments(
|
|
431
|
+
fieldSegments(ir, "minute"),
|
|
432
|
+
UNITS.minute,
|
|
433
|
+
"jeder Stunde"
|
|
434
|
+
) ?? countedPhrase(ir, "minute", "Minute", "Minuten") + " jeder Stunde";
|
|
435
|
+
}
|
|
360
436
|
function renderMinutePast(ir) {
|
|
361
|
-
return
|
|
437
|
+
return minutePastClause(ir);
|
|
362
438
|
}
|
|
363
439
|
function renderSecondsWithinMinute(ir, plan) {
|
|
364
440
|
if (plan.singleSecond) {
|
|
@@ -383,9 +459,21 @@ function renderMinuteSpanInHour(ir, plan, opts) {
|
|
|
383
459
|
return "jede Minute von " + spanTime(plan.hour, plan.span[0], sep) + " bis " + spanTime(plan.hour, plan.span[1], sep) + " Uhr";
|
|
384
460
|
}
|
|
385
461
|
function renderComposeSeconds(ir, plan, opts) {
|
|
462
|
+
if ((plan.rest.kind === "clockTimes" || plan.rest.kind === "compactClockTimes") && ir.shapes.minute === "single") {
|
|
463
|
+
const cadence = hourCadence(ir, +ir.pattern.minute);
|
|
464
|
+
if (cadence !== null) {
|
|
465
|
+
return cadence;
|
|
466
|
+
}
|
|
467
|
+
}
|
|
386
468
|
if (composeMinuteZero(ir, plan)) {
|
|
387
469
|
return secondsLead(ir) + " " + clockMinuteGenitive(plan.rest.times, opts.style.sep);
|
|
388
470
|
}
|
|
471
|
+
if (plan.rest.kind === "minuteFrequency" && ir.shapes.second === "wildcard" && ir.shapes.hour === "wildcard") {
|
|
472
|
+
const minuteStep = stepSegment(ir.analyses.segments.minute);
|
|
473
|
+
if (minuteStep.startToken === "*" && minuteStep.interval === 2) {
|
|
474
|
+
return secondsLead(ir) + " jeder zweiten Minute";
|
|
475
|
+
}
|
|
476
|
+
}
|
|
389
477
|
return secondsLead(ir) + ", " + render(ir, plan.rest, opts);
|
|
390
478
|
}
|
|
391
479
|
function composeMinuteZero(ir, plan) {
|
|
@@ -403,29 +491,35 @@ function renderMinutesAcrossHours(ir, plan, opts) {
|
|
|
403
491
|
return "jede Minute " + duringHours(ir, plan.times, sep);
|
|
404
492
|
}
|
|
405
493
|
const hours = plan.times.kind === "fires" ? atHours(plan.times.fires) : joinList(hourSegmentParts(ir, 0, 0, sep));
|
|
406
|
-
return countedPhrase(ir, "minute", "Minute", "Minuten") + ", " + hours;
|
|
494
|
+
return (strideFromSegments(fieldSegments(ir, "minute"), UNITS.minute, "") ?? countedPhrase(ir, "minute", "Minute", "Minuten")) + ", " + hours;
|
|
407
495
|
}
|
|
408
496
|
function renderMinuteSpanAcrossHourStep(ir, plan) {
|
|
409
497
|
if (plan.form === "wildcard") {
|
|
410
498
|
return "jede Minute " + everyNthHour(stepSegment(ir.analyses.segments.hour));
|
|
411
499
|
}
|
|
412
|
-
|
|
500
|
+
const segment = stepSegment(ir.analyses.segments.hour);
|
|
501
|
+
const hours = confinedHourStride(segment) ? everyNthHour(segment) : atHours(segment.fires);
|
|
502
|
+
return (strideFromSegments(fieldSegments(ir, "minute"), UNITS.minute, "") ?? countedPhrase(ir, "minute", "Minute", "Minuten")) + ", " + hours;
|
|
413
503
|
}
|
|
414
504
|
function renderCompactClockTimes(ir, plan, opts) {
|
|
415
505
|
const sep = opts.style.sep;
|
|
416
506
|
if (plan.fold) {
|
|
507
|
+
const cadence = hourCadence(ir, plan.minute);
|
|
508
|
+
if (cadence !== null) {
|
|
509
|
+
return cadence;
|
|
510
|
+
}
|
|
417
511
|
const hourly = fieldSegments(ir, "hour").some((segment) => segment.kind === "range");
|
|
418
512
|
return (hourly ? "st\xFCndlich " : "t\xE4glich ") + joinList(hourSegmentParts(ir, plan.minute, ir.analyses.clockSecond, sep));
|
|
419
513
|
}
|
|
420
514
|
const hours = fieldSegments(ir, "hour").some((segment) => segment.kind === "range") ? joinList(hourSegmentParts(ir, 0, 0, sep)) : atHours(hourFires(ir));
|
|
421
515
|
const lead = ir.analyses.clockSecond ? countedPhrase(ir, "second", "Sekunde", "Sekunden") + ", " : "";
|
|
422
|
-
return lead + countedPhrase(ir, "minute", "Minute", "Minuten") + ", " + hours;
|
|
516
|
+
return lead + (strideFromSegments(fieldSegments(ir, "minute"), UNITS.minute, "") ?? countedPhrase(ir, "minute", "Minute", "Minuten")) + ", " + hours;
|
|
423
517
|
}
|
|
424
518
|
function renderMinuteFrequency(ir, plan, opts) {
|
|
425
519
|
const segment = stepSegment(ir.analyses.segments.minute);
|
|
426
520
|
const sep = opts.style.sep;
|
|
427
521
|
const clean = cleanStep(segment, 60);
|
|
428
|
-
const base =
|
|
522
|
+
const base = stepClause(segment, UNITS.minute, "jeder Stunde");
|
|
429
523
|
if (plan.hours.kind === "window") {
|
|
430
524
|
const window = hourWindow(
|
|
431
525
|
plan.hours.from,
|
|
@@ -447,6 +541,67 @@ function hourStepPhrase(ir) {
|
|
|
447
541
|
const segment = stepSegment(ir.analyses.segments.hour);
|
|
448
542
|
return cleanStep(segment, 24) ? everyN(segment.interval, UNITS.hour) : atHours(segment.fires);
|
|
449
543
|
}
|
|
544
|
+
function hourStrideCadence(stride) {
|
|
545
|
+
const { start, interval, last } = stride;
|
|
546
|
+
const cadence = everyN(interval, UNITS.hour);
|
|
547
|
+
const tiles = 24 % interval === 0;
|
|
548
|
+
if (start === 0 && tiles) {
|
|
549
|
+
return cadence;
|
|
550
|
+
}
|
|
551
|
+
if (start < interval && tiles) {
|
|
552
|
+
return cadence + " ab " + start + " Uhr";
|
|
553
|
+
}
|
|
554
|
+
return cadence + " von " + start + " bis " + last + " Uhr";
|
|
555
|
+
}
|
|
556
|
+
function hourStride(ir) {
|
|
557
|
+
const segments = fieldSegments(ir, "hour");
|
|
558
|
+
if (!segments) {
|
|
559
|
+
return null;
|
|
560
|
+
}
|
|
561
|
+
if (segments.length === 1 && segments[0].kind === "step") {
|
|
562
|
+
const segment = segments[0];
|
|
563
|
+
const start = segment.startToken === "*" ? 0 : +segment.startToken.split("-")[0];
|
|
564
|
+
return { interval: segment.interval, last: segment.fires[segment.fires.length - 1], start };
|
|
565
|
+
}
|
|
566
|
+
const values = singleValues(segments);
|
|
567
|
+
const step = values && arithmeticStep(values);
|
|
568
|
+
return step || null;
|
|
569
|
+
}
|
|
570
|
+
function subMinuteSecond(ir) {
|
|
571
|
+
return ir.pattern.second === "*" || ir.shapes.second === "step";
|
|
572
|
+
}
|
|
573
|
+
function hourCadenceLead(ir, minute) {
|
|
574
|
+
if (minute === 0) {
|
|
575
|
+
if (subMinuteSecond(ir)) {
|
|
576
|
+
return secondsClause(ir, "jeder Minute") + " f\xFCr eine Minute";
|
|
577
|
+
}
|
|
578
|
+
return secondsClause(ir, "jeder Stunde");
|
|
579
|
+
}
|
|
580
|
+
const minutePhrase = "in Minute " + minute;
|
|
581
|
+
if (ir.pattern.second === "0") {
|
|
582
|
+
return minutePhrase;
|
|
583
|
+
}
|
|
584
|
+
return secondsClause(ir, "jeder Minute") + ", " + minutePhrase;
|
|
585
|
+
}
|
|
586
|
+
function hourCadence(ir, minute) {
|
|
587
|
+
const stride = hourStride(ir);
|
|
588
|
+
if (!stride) {
|
|
589
|
+
return null;
|
|
590
|
+
}
|
|
591
|
+
const fires = (stride.last - stride.start) / stride.interval + 1;
|
|
592
|
+
if (ir.pattern.second === "0" && fires <= maxClockTimes) {
|
|
593
|
+
return null;
|
|
594
|
+
}
|
|
595
|
+
const segment = fieldSegments(ir, "hour")[0];
|
|
596
|
+
const confined = minute === 0 && subMinuteSecond(ir) && fieldSegments(ir, "hour").length === 1 && segment.kind === "step" && confinedHourStride(segment);
|
|
597
|
+
if (confined) {
|
|
598
|
+
return secondsClause(ir, "jeder Minute") + " f\xFCr eine Minute " + everyNthHour(segment);
|
|
599
|
+
}
|
|
600
|
+
return hourCadenceLead(ir, minute) + ", " + hourStrideCadence(stride);
|
|
601
|
+
}
|
|
602
|
+
function hourCadenceApplies(ir) {
|
|
603
|
+
return ir.shapes.minute === "single" && hourCadence(ir, +ir.pattern.minute) !== null;
|
|
604
|
+
}
|
|
450
605
|
function renderHourRange(ir, plan, opts) {
|
|
451
606
|
const window = hourWindow(
|
|
452
607
|
plan.from,
|
|
@@ -463,6 +618,12 @@ function renderHourRange(ir, plan, opts) {
|
|
|
463
618
|
return countedPhrase(ir, "minute", "Minute", "Minuten") + " jeder Stunde, " + window;
|
|
464
619
|
}
|
|
465
620
|
function renderClockTimes(ir, plan, opts) {
|
|
621
|
+
if (ir.shapes.minute === "single") {
|
|
622
|
+
const cadence = hourCadence(ir, +ir.pattern.minute);
|
|
623
|
+
if (cadence !== null) {
|
|
624
|
+
return cadence;
|
|
625
|
+
}
|
|
626
|
+
}
|
|
466
627
|
return "um " + timesPhrase(plan.times, opts.style.sep);
|
|
467
628
|
}
|
|
468
629
|
var renderers = {
|
|
@@ -512,6 +673,9 @@ function isComposeMinuteZero(ir) {
|
|
|
512
673
|
return ir.plan.kind === "composeSeconds" && composeMinuteZero(ir, ir.plan);
|
|
513
674
|
}
|
|
514
675
|
function needsDailyFrame(ir) {
|
|
676
|
+
if (hourCadenceApplies(ir)) {
|
|
677
|
+
return false;
|
|
678
|
+
}
|
|
515
679
|
if (ir.plan.kind === "clockTimes" || isComposeMinuteZero(ir)) {
|
|
516
680
|
return true;
|
|
517
681
|
}
|