cronli5 0.1.5 → 0.1.7
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 +71 -0
- package/README.md +2 -2
- package/cronli5.min.js +2 -2
- package/dist/cronli5.cjs +156 -27
- package/dist/cronli5.js +156 -27
- package/dist/lang/de.cjs +157 -36
- package/dist/lang/de.js +157 -36
- package/dist/lang/en.cjs +156 -27
- package/dist/lang/en.js +156 -27
- package/dist/lang/es.cjs +156 -18
- package/dist/lang/es.js +156 -18
- package/dist/lang/fi.cjs +128 -20
- package/dist/lang/fi.js +128 -20
- package/dist/lang/zh.cjs +126 -58
- package/dist/lang/zh.js +126 -58
- package/package.json +2 -2
- package/src/core/util.ts +52 -1
- package/src/lang/de/index.ts +331 -74
- package/src/lang/en/index.ts +327 -62
- package/src/lang/es/index.ts +306 -39
- package/src/lang/fi/index.ts +251 -41
- package/src/lang/zh/index.ts +246 -105
- package/types/core/util.d.ts +10 -1
package/dist/cronli5.js
CHANGED
|
@@ -84,6 +84,26 @@ function arithmeticStep(values) {
|
|
|
84
84
|
}
|
|
85
85
|
return { start: values[0], interval, last: values[values.length - 1] };
|
|
86
86
|
}
|
|
87
|
+
function weekdayDisplayKey(value) {
|
|
88
|
+
return value === 0 ? 7 : value;
|
|
89
|
+
}
|
|
90
|
+
function orderWeekdaysForDisplay(segments) {
|
|
91
|
+
const flattened = segments.flatMap(function flat(segment) {
|
|
92
|
+
return segment.kind === "step" ? segment.fires.map(function single(value) {
|
|
93
|
+
return { kind: "single", value: "" + value };
|
|
94
|
+
}) : [segment];
|
|
95
|
+
});
|
|
96
|
+
function key(segment) {
|
|
97
|
+
return segment.kind === "range" ? weekdayDisplayKey(+segment.bounds[0]) : weekdayDisplayKey(+segment.value);
|
|
98
|
+
}
|
|
99
|
+
return flattened.map(function index(segment, position) {
|
|
100
|
+
return [segment, position];
|
|
101
|
+
}).sort(function byDisplayKey(a, b) {
|
|
102
|
+
return key(a[0]) - key(b[0]) || a[1] - b[1];
|
|
103
|
+
}).map(function unwrap(pair) {
|
|
104
|
+
return pair[0];
|
|
105
|
+
});
|
|
106
|
+
}
|
|
87
107
|
function toFieldNumber(token, numberMap) {
|
|
88
108
|
return isNonNegativeInteger(token) ? +token : numberMap[token.toUpperCase()];
|
|
89
109
|
}
|
|
@@ -946,7 +966,17 @@ function renderSecondsWithinMinute(ir, plan, opts) {
|
|
|
946
966
|
}
|
|
947
967
|
function composeHourCadence(ir, plan, opts) {
|
|
948
968
|
const clockRest = plan.rest.kind === "clockTimes" || plan.rest.kind === "compactClockTimes";
|
|
949
|
-
|
|
969
|
+
if (!clockRest || ir.shapes.minute !== "single") {
|
|
970
|
+
return null;
|
|
971
|
+
}
|
|
972
|
+
const minute = +ir.pattern.minute;
|
|
973
|
+
return hourCadence(ir, minute, opts) ?? hourRangeCadence(ir, minute, opts);
|
|
974
|
+
}
|
|
975
|
+
function clockTimesConfinement(ir, rest, opts) {
|
|
976
|
+
if (+rest.times[0].minute === 0 && ir.shapes.minute === "single") {
|
|
977
|
+
return secondsLeadClause(ir, opts) + " for one minute at " + durationHours(ir, rest, opts);
|
|
978
|
+
}
|
|
979
|
+
return secondsLeadClause(ir, opts) + " of " + clockTimesOf(ir, rest, opts);
|
|
950
980
|
}
|
|
951
981
|
function renderComposeSeconds(ir, plan, opts) {
|
|
952
982
|
const cadence = composeHourCadence(ir, plan, opts);
|
|
@@ -954,16 +984,14 @@ function renderComposeSeconds(ir, plan, opts) {
|
|
|
954
984
|
return cadence;
|
|
955
985
|
}
|
|
956
986
|
if (plan.rest.kind === "clockTimes" && (ir.shapes.second === "wildcard" || ir.shapes.second === "step")) {
|
|
957
|
-
|
|
958
|
-
if (+minute === 0) {
|
|
959
|
-
return secondsLeadClause(ir, opts) + " for one minute at " + durationHours(ir, plan.rest, opts);
|
|
960
|
-
}
|
|
961
|
-
return secondsLeadClause(ir, opts) + " of " + clockTimesOf(ir, plan.rest, opts);
|
|
987
|
+
return clockTimesConfinement(ir, plan.rest, opts);
|
|
962
988
|
}
|
|
963
989
|
if (ir.shapes.second === "wildcard" && plan.rest.kind === "minuteFrequency" && plan.rest.hours.kind === "none" && ir.pattern.minute === "*/2") {
|
|
964
990
|
return "every second of every other minute" + trailingQualifier(ir, opts);
|
|
965
991
|
}
|
|
966
|
-
|
|
992
|
+
const restOwnsLead = plan.rest.kind === "compactClockTimes" && ir.analyses.clockSecond;
|
|
993
|
+
const lead = restOwnsLead ? "" : secondsLeadClause(ir, opts) + ", ";
|
|
994
|
+
return lead + render(ir, plan.rest, opts);
|
|
967
995
|
}
|
|
968
996
|
function durationHours(ir, plan, opts) {
|
|
969
997
|
const hours = plan.times.map(function clock(time) {
|
|
@@ -1046,7 +1074,8 @@ function renderMinuteFrequency(ir, plan, opts) {
|
|
|
1046
1074
|
opts
|
|
1047
1075
|
);
|
|
1048
1076
|
if (plan.hours.kind === "during") {
|
|
1049
|
-
|
|
1077
|
+
const cadence = unevenHourCadence(ir, opts);
|
|
1078
|
+
phrase += cadence ? ", " + cadence : " during the " + hourTimesFromPlan(ir, plan.hours.times, false, opts) + " hours";
|
|
1050
1079
|
} else if (plan.hours.kind === "window") {
|
|
1051
1080
|
phrase += " " + hourWindow(plan.hours, opts);
|
|
1052
1081
|
} else if (plan.hours.kind === "step") {
|
|
@@ -1061,10 +1090,13 @@ function renderMinuteSpanInHour(ir, plan, opts) {
|
|
|
1061
1090
|
return "every minute from " + getTime({ hour: plan.hour, minute: plan.span[0] }, opts) + through(opts) + getTime({ hour: plan.hour, minute: plan.span[1] }, opts) + trailingQualifier(ir, opts);
|
|
1062
1091
|
}
|
|
1063
1092
|
function renderMinutesAcrossHours(ir, plan, opts) {
|
|
1093
|
+
const cadence = unevenHourCadence(ir, opts);
|
|
1064
1094
|
if (plan.form === "wildcard") {
|
|
1095
|
+
if (cadence !== null) {
|
|
1096
|
+
return "every minute, " + cadence + trailingQualifier(ir, opts);
|
|
1097
|
+
}
|
|
1065
1098
|
return "every minute during the " + hourTimesFromPlan(ir, plan.times, false, opts) + " hours" + trailingQualifier(ir, opts);
|
|
1066
1099
|
}
|
|
1067
|
-
const times = hourTimesFromPlan(ir, plan.times, true, opts);
|
|
1068
1100
|
const lead = plan.form === "range" ? minuteRangeLead(ir.pattern.minute, opts) : (
|
|
1069
1101
|
// The 'list' form is a minute list, which has segments; an offset/uneven
|
|
1070
1102
|
// step enumerated to that list reads as a stride.
|
|
@@ -1075,6 +1107,10 @@ function renderMinutesAcrossHours(ir, plan, opts) {
|
|
|
1075
1107
|
opts
|
|
1076
1108
|
)
|
|
1077
1109
|
);
|
|
1110
|
+
if (cadence !== null) {
|
|
1111
|
+
return lead + ", " + cadence + trailingQualifier(ir, opts);
|
|
1112
|
+
}
|
|
1113
|
+
const times = hourTimesFromPlan(ir, plan.times, true, opts);
|
|
1078
1114
|
return lead + ", at " + times + trailingQualifier(ir, opts);
|
|
1079
1115
|
}
|
|
1080
1116
|
var stepOrdinals = {
|
|
@@ -1101,7 +1137,8 @@ function renderMinuteSpanAcrossHourStep(ir, plan, opts) {
|
|
|
1101
1137
|
"hour",
|
|
1102
1138
|
opts
|
|
1103
1139
|
) : minuteRangeLead(ir.pattern.minute, opts);
|
|
1104
|
-
|
|
1140
|
+
const cadence = unevenHourCadence(ir, opts);
|
|
1141
|
+
return lead + ", " + (cadence ?? stepHours(segment, opts)) + trailingQualifier(ir, opts);
|
|
1105
1142
|
}
|
|
1106
1143
|
function minuteRangeLead(minuteField, opts) {
|
|
1107
1144
|
const bounds = minuteField.split("-");
|
|
@@ -1138,17 +1175,23 @@ function rangeMinuteLead(ir, opts) {
|
|
|
1138
1175
|
);
|
|
1139
1176
|
}
|
|
1140
1177
|
function renderHourStep(ir, plan, opts) {
|
|
1178
|
+
const cadence = unevenHourCadence(ir, opts);
|
|
1179
|
+
if (cadence !== null) {
|
|
1180
|
+
return cadence + trailingQualifier(ir, opts);
|
|
1181
|
+
}
|
|
1141
1182
|
return stepHours(ir.analyses.segments.hour[0], opts) + trailingQualifier(ir, opts);
|
|
1142
1183
|
}
|
|
1143
1184
|
function boundedWindow(plan) {
|
|
1144
|
-
|
|
1185
|
+
const last = plan.minuteForm === "wildcard" ? plan.boundMinute ?? 0 : 0;
|
|
1186
|
+
return { from: plan.from, last, to: plan.to };
|
|
1145
1187
|
}
|
|
1146
1188
|
function hourWindow(window, opts) {
|
|
1147
1189
|
return "from " + getTime({ hour: window.from, minute: 0 }, opts) + through(opts) + getTime({ hour: window.to, minute: window.last }, opts);
|
|
1148
1190
|
}
|
|
1149
1191
|
function renderClockTimes(ir, plan, opts) {
|
|
1150
1192
|
if (ir.shapes.minute === "single") {
|
|
1151
|
-
const
|
|
1193
|
+
const minute = +ir.pattern.minute;
|
|
1194
|
+
const cadence = hourCadence(ir, minute, opts) ?? hourRangeCadence(ir, minute, opts);
|
|
1152
1195
|
if (cadence !== null) {
|
|
1153
1196
|
return cadence;
|
|
1154
1197
|
}
|
|
@@ -1166,9 +1209,9 @@ function renderClockTimes(ir, plan, opts) {
|
|
|
1166
1209
|
}
|
|
1167
1210
|
function renderCompactClockTimes(ir, plan, opts) {
|
|
1168
1211
|
if (plan.fold) {
|
|
1169
|
-
const
|
|
1170
|
-
if (
|
|
1171
|
-
return
|
|
1212
|
+
const cadence2 = hourCadence(ir, +plan.minute, opts) ?? hourRangeCadence(ir, +plan.minute, opts);
|
|
1213
|
+
if (cadence2 !== null) {
|
|
1214
|
+
return cadence2;
|
|
1172
1215
|
}
|
|
1173
1216
|
const hasRange = ir.analyses.segments.hour.some(function range(segment) {
|
|
1174
1217
|
return segment.kind === "range";
|
|
@@ -1179,16 +1222,18 @@ function renderCompactClockTimes(ir, plan, opts) {
|
|
|
1179
1222
|
const fold = { minute: plan.minute, second: ir.analyses.clockSecond };
|
|
1180
1223
|
return interpretDayQualifier(ir, opts) + "at " + hourSegmentTimes(ir, fold, true, opts);
|
|
1181
1224
|
}
|
|
1182
|
-
const
|
|
1225
|
+
const minuteLead = (
|
|
1183
1226
|
// The non-fold branch is a minute list, which has segments. An
|
|
1184
1227
|
// offset/uneven step enumerated to that list reads as a stride.
|
|
1185
|
-
|
|
1228
|
+
strideFromSegments(ir.analyses.segments.minute, "minute", "hour", opts) ?? listPastThe(
|
|
1186
1229
|
segmentWords(ir.analyses.segments.minute, opts),
|
|
1187
1230
|
"minute",
|
|
1188
1231
|
"hour",
|
|
1189
1232
|
opts
|
|
1190
|
-
)
|
|
1233
|
+
)
|
|
1191
1234
|
);
|
|
1235
|
+
const cadence = unevenHourCadence(ir, opts);
|
|
1236
|
+
const phrase = cadence ? minuteLead + ", " + cadence + trailingQualifier(ir, opts) : minuteLead + ", at " + hourSegmentTimes(ir, { minute: 0, second: null }, true, opts) + trailingQualifier(ir, opts);
|
|
1192
1237
|
return ir.analyses.clockSecond ? secondsLeadClause(ir, opts) + ", " + phrase : phrase;
|
|
1193
1238
|
}
|
|
1194
1239
|
function foldedHourWindows(ir, plan, opts) {
|
|
@@ -1306,16 +1351,46 @@ function hourStrideCadence(stride, opts) {
|
|
|
1306
1351
|
}
|
|
1307
1352
|
return cadence + " from " + getTime({ hour: start, minute: 0 }, opts) + through(opts) + getTime({ hour: last, minute: 0 }, opts);
|
|
1308
1353
|
}
|
|
1354
|
+
function offsetCleanStride(stride) {
|
|
1355
|
+
return stride.start < stride.interval && 24 % stride.interval === 0;
|
|
1356
|
+
}
|
|
1357
|
+
function unevenHourCadence(ir, opts) {
|
|
1358
|
+
const stride = hourStride(ir);
|
|
1359
|
+
if (!stride || offsetCleanStride(stride)) {
|
|
1360
|
+
return null;
|
|
1361
|
+
}
|
|
1362
|
+
return hourStrideCadence(stride, opts);
|
|
1363
|
+
}
|
|
1364
|
+
function hourListStride(values) {
|
|
1365
|
+
if (values.length < 2) {
|
|
1366
|
+
return null;
|
|
1367
|
+
}
|
|
1368
|
+
const interval = values[1] - values[0];
|
|
1369
|
+
if (interval < 2) {
|
|
1370
|
+
return null;
|
|
1371
|
+
}
|
|
1372
|
+
for (let i = 2; i < values.length; i += 1) {
|
|
1373
|
+
if (values[i] - values[i - 1] !== interval) {
|
|
1374
|
+
return null;
|
|
1375
|
+
}
|
|
1376
|
+
}
|
|
1377
|
+
if (values[0] !== 0 && values.length < 5) {
|
|
1378
|
+
return null;
|
|
1379
|
+
}
|
|
1380
|
+
return { interval, last: values[values.length - 1], start: values[0] };
|
|
1381
|
+
}
|
|
1309
1382
|
function hourStride(ir) {
|
|
1310
1383
|
const segments = ir.analyses.segments.hour;
|
|
1311
1384
|
if (segments.length === 1 && segments[0].kind === "step") {
|
|
1312
1385
|
const segment = segments[0];
|
|
1386
|
+
if (segment.fires.length < 2) {
|
|
1387
|
+
return null;
|
|
1388
|
+
}
|
|
1313
1389
|
const start = segment.startToken === "*" ? 0 : +segment.startToken.split("-")[0];
|
|
1314
1390
|
return { interval: segment.interval, last: segment.fires[segment.fires.length - 1], start };
|
|
1315
1391
|
}
|
|
1316
1392
|
const values = singleValues(segments);
|
|
1317
|
-
|
|
1318
|
-
return step || null;
|
|
1393
|
+
return values && hourListStride(values);
|
|
1319
1394
|
}
|
|
1320
1395
|
function subMinuteSecond(ir) {
|
|
1321
1396
|
return ir.pattern.second === "*" || ir.shapes.second === "step";
|
|
@@ -1339,13 +1414,16 @@ function hourCadence(ir, minute, opts) {
|
|
|
1339
1414
|
return null;
|
|
1340
1415
|
}
|
|
1341
1416
|
const fires = (stride.last - stride.start) / stride.interval + 1;
|
|
1342
|
-
if (ir.pattern.second === "0" && fires <= maxClockTimes) {
|
|
1417
|
+
if (ir.pattern.second === "0" && fires <= maxClockTimes && offsetCleanStride(stride)) {
|
|
1343
1418
|
return null;
|
|
1344
1419
|
}
|
|
1345
1420
|
const confinement = minute === 0 && subMinuteSecond(ir) && cleanStrideSegment(ir);
|
|
1346
1421
|
if (confinement) {
|
|
1347
1422
|
return secondsClause(ir, "minute", opts) + " for one minute " + everyNthHour(confinement, opts) + trailingQualifier(ir, opts);
|
|
1348
1423
|
}
|
|
1424
|
+
if (minute === 0 && ir.pattern.second === "0") {
|
|
1425
|
+
return hourStrideCadence(stride, opts) + trailingQualifier(ir, opts);
|
|
1426
|
+
}
|
|
1349
1427
|
return hourCadenceLead(ir, minute, opts) + ", " + hourStrideCadence(stride, opts) + trailingQualifier(ir, opts);
|
|
1350
1428
|
}
|
|
1351
1429
|
function cleanStrideSegment(ir) {
|
|
@@ -1356,6 +1434,46 @@ function cleanStrideSegment(ir) {
|
|
|
1356
1434
|
}
|
|
1357
1435
|
return segment;
|
|
1358
1436
|
}
|
|
1437
|
+
function hasHourWindow(ir) {
|
|
1438
|
+
return ir.analyses.segments.hour.some(function range(segment) {
|
|
1439
|
+
return segment.kind === "range";
|
|
1440
|
+
});
|
|
1441
|
+
}
|
|
1442
|
+
function hourRangeWindowTail(ir, opts) {
|
|
1443
|
+
const windows = [];
|
|
1444
|
+
const singles = [];
|
|
1445
|
+
ir.analyses.segments.hour.forEach(function classify(segment) {
|
|
1446
|
+
if (segment.kind === "range") {
|
|
1447
|
+
windows.push("from " + getTime(
|
|
1448
|
+
{ hour: +segment.bounds[0], minute: 0 },
|
|
1449
|
+
opts
|
|
1450
|
+
) + through(opts) + getTime({ hour: +segment.bounds[1], minute: 0 }, opts));
|
|
1451
|
+
} else if (segment.kind === "step") {
|
|
1452
|
+
singles.push(...segment.fires);
|
|
1453
|
+
} else {
|
|
1454
|
+
singles.push(+segment.value);
|
|
1455
|
+
}
|
|
1456
|
+
});
|
|
1457
|
+
let phrase = "every hour " + joinList(windows, opts);
|
|
1458
|
+
if (singles.length) {
|
|
1459
|
+
phrase += " and at " + joinList(singles.map(function time(hour) {
|
|
1460
|
+
return getTime({ hour, minute: 0 }, opts);
|
|
1461
|
+
}), opts);
|
|
1462
|
+
}
|
|
1463
|
+
return phrase;
|
|
1464
|
+
}
|
|
1465
|
+
function hourRangeCadence(ir, minute, opts) {
|
|
1466
|
+
if (minute !== 0 || !hasHourWindow(ir)) {
|
|
1467
|
+
return null;
|
|
1468
|
+
}
|
|
1469
|
+
if (ir.pattern.second === "0") {
|
|
1470
|
+
return null;
|
|
1471
|
+
}
|
|
1472
|
+
if (subMinuteSecond(ir)) {
|
|
1473
|
+
return secondsClause(ir, "minute", opts) + " for one minute during the " + hourSegmentTimes(ir, { minute: 0, second: null }, false, opts) + " hours" + trailingQualifier(ir, opts);
|
|
1474
|
+
}
|
|
1475
|
+
return hourCadenceLead(ir, minute, opts) + ", " + hourRangeWindowTail(ir, opts) + trailingQualifier(ir, opts);
|
|
1476
|
+
}
|
|
1359
1477
|
function seriesNumber(values, opts) {
|
|
1360
1478
|
const anyBig = values.some(function big(v) {
|
|
1361
1479
|
return +v > 10;
|
|
@@ -1520,17 +1638,27 @@ function monthFoldsIntoDate(ir) {
|
|
|
1520
1638
|
function dateOrWeekday(ir, opts) {
|
|
1521
1639
|
const pattern = ir.pattern;
|
|
1522
1640
|
const weekdayPart = quartzWeekdayPhrase(pattern.weekday, opts) || "on " + weekdayPhrase(ir, opts);
|
|
1641
|
+
if (pattern.month !== "*" && monthFoldsIntoDate(ir) && !quartzDatePhrase(pattern.date, opts) && !isOpenStep(pattern.date)) {
|
|
1642
|
+
return "on " + monthDatePhrase(ir, opts) + " or " + weekdayPart + " in " + monthName(ir, opts);
|
|
1643
|
+
}
|
|
1644
|
+
return datePart(ir, opts) + " or " + weekdayPart + orMonthScope(ir, opts);
|
|
1645
|
+
}
|
|
1646
|
+
function datePart(ir, opts) {
|
|
1647
|
+
const pattern = ir.pattern;
|
|
1523
1648
|
const quartzDate = quartzDatePhrase(pattern.date, opts);
|
|
1524
1649
|
if (quartzDate) {
|
|
1525
|
-
return quartzDate
|
|
1650
|
+
return quartzDate;
|
|
1526
1651
|
}
|
|
1527
1652
|
if (isOpenStep(pattern.date)) {
|
|
1528
|
-
return stepDates(pattern.date)
|
|
1653
|
+
return stepDates(pattern.date);
|
|
1529
1654
|
}
|
|
1530
|
-
|
|
1531
|
-
|
|
1655
|
+
return "on the " + dateOrdinals(ir, opts);
|
|
1656
|
+
}
|
|
1657
|
+
function orMonthScope(ir, opts) {
|
|
1658
|
+
if (ir.pattern.month === "*") {
|
|
1659
|
+
return "";
|
|
1532
1660
|
}
|
|
1533
|
-
return "
|
|
1661
|
+
return ", in " + monthName(ir, opts);
|
|
1534
1662
|
}
|
|
1535
1663
|
function quartzDatePhrase(dateField, opts) {
|
|
1536
1664
|
if (dateField === "L") {
|
|
@@ -1612,7 +1740,8 @@ function oddEvenMonth(monthField) {
|
|
|
1612
1740
|
return start === "2" ? "every even-numbered month" : null;
|
|
1613
1741
|
}
|
|
1614
1742
|
function weekdayPhrase(ir, opts) {
|
|
1615
|
-
|
|
1743
|
+
const segments = orderWeekdaysForDisplay(ir.analyses.segments.weekday);
|
|
1744
|
+
return renderSegments(segments, function name(value) {
|
|
1616
1745
|
return getWeekday(value, opts);
|
|
1617
1746
|
}, opts);
|
|
1618
1747
|
}
|