cronli5 0.2.1 → 0.3.1
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 +65 -0
- package/cronli5.min.js +2 -2
- package/dist/cronli5.cjs +471 -383
- package/dist/cronli5.js +471 -383
- package/dist/lang/de.cjs +286 -215
- package/dist/lang/de.js +286 -215
- package/dist/lang/en.cjs +413 -327
- package/dist/lang/en.js +413 -327
- package/dist/lang/es.cjs +303 -265
- package/dist/lang/es.js +303 -265
- package/dist/lang/fi.cjs +311 -266
- package/dist/lang/fi.js +311 -266
- package/dist/lang/zh.cjs +308 -236
- package/dist/lang/zh.js +308 -236
- package/package.json +1 -1
- package/src/core/analyze.ts +12 -12
- package/src/core/cadence.ts +164 -0
- package/src/core/index.ts +3 -1
- package/src/core/normalize.ts +3 -3
- package/src/core/parse.ts +1 -1
- package/src/core/{ir.ts → schedule.ts} +17 -18
- package/src/core/specs.ts +1 -1
- package/src/core/util.ts +3 -165
- package/src/core/validate.ts +1 -1
- package/src/core/weekday.ts +54 -0
- package/src/cronli5.ts +5 -5
- package/src/lang/de/index.ts +329 -219
- package/src/lang/en/dialects.ts +1 -1
- package/src/lang/en/index.ts +521 -372
- package/src/lang/es/index.ts +338 -286
- package/src/lang/es/notes.md +1 -1
- package/src/lang/fi/dialects.ts +1 -1
- package/src/lang/fi/index.ts +365 -299
- package/src/lang/fi/notes.md +23 -8
- package/src/lang/fi/status.json +1 -1
- package/src/lang/zh/index.ts +344 -237
- package/src/types.ts +6 -6
- package/types/core/analyze.d.ts +3 -3
- package/types/core/cadence.d.ts +33 -0
- package/types/core/index.d.ts +3 -1
- package/types/core/normalize.d.ts +1 -1
- package/types/core/parse.d.ts +1 -1
- package/types/core/{ir.d.ts → schedule.d.ts} +11 -16
- package/types/core/specs.d.ts +1 -1
- package/types/core/util.d.ts +1 -30
- package/types/core/weekday.d.ts +10 -0
- package/types/lang/de/index.d.ts +1 -1
- package/types/lang/en/dialects.d.ts +1 -1
- package/types/lang/en/index.d.ts +1 -1
- package/types/lang/es/index.d.ts +1 -1
- package/types/lang/fi/dialects.d.ts +1 -1
- package/types/lang/fi/index.d.ts +1 -1
- package/types/lang/zh/index.d.ts +1 -1
- package/types/types.d.ts +5 -5
package/dist/cronli5.js
CHANGED
|
@@ -69,81 +69,9 @@ 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
|
-
}
|
|
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
|
-
}
|
|
107
72
|
function toFieldNumber(token, numberMap) {
|
|
108
73
|
return isNonNegativeInteger(token) ? +token : numberMap[token.toUpperCase()];
|
|
109
74
|
}
|
|
110
|
-
function segmentsOf(ir, field) {
|
|
111
|
-
return ir.analyses.segments[field] ?? [];
|
|
112
|
-
}
|
|
113
|
-
function stepSegment(ir, field) {
|
|
114
|
-
return segmentsOf(ir, field)[0];
|
|
115
|
-
}
|
|
116
|
-
function singleValues(segments) {
|
|
117
|
-
const values = [];
|
|
118
|
-
for (const segment of segments) {
|
|
119
|
-
if (segment.kind !== "single") {
|
|
120
|
-
return null;
|
|
121
|
-
}
|
|
122
|
-
values.push(+segment.value);
|
|
123
|
-
}
|
|
124
|
-
return values;
|
|
125
|
-
}
|
|
126
|
-
function offsetCleanStride(stride) {
|
|
127
|
-
return stride.start < stride.interval && 24 % stride.interval === 0;
|
|
128
|
-
}
|
|
129
|
-
function hourListStride(values) {
|
|
130
|
-
if (values.length < 2) {
|
|
131
|
-
return null;
|
|
132
|
-
}
|
|
133
|
-
const interval = values[1] - values[0];
|
|
134
|
-
if (interval < 2) {
|
|
135
|
-
return null;
|
|
136
|
-
}
|
|
137
|
-
for (let i = 2; i < values.length; i += 1) {
|
|
138
|
-
if (values[i] - values[i - 1] !== interval) {
|
|
139
|
-
return null;
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
if (values[0] !== 0 && values.length < 5) {
|
|
143
|
-
return null;
|
|
144
|
-
}
|
|
145
|
-
return { interval, last: values[values.length - 1], start: values[0] };
|
|
146
|
-
}
|
|
147
75
|
|
|
148
76
|
// src/core/validate.ts
|
|
149
77
|
function validateCronPattern(cronPattern) {
|
|
@@ -273,7 +201,7 @@ function normalizeField(value, field, spec) {
|
|
|
273
201
|
const cycle = timeFieldCycle[field];
|
|
274
202
|
const segments = stringValue.split(",").map(function canonical(segment) {
|
|
275
203
|
return canonicalizeTokens(collapseFullSpanRange(
|
|
276
|
-
|
|
204
|
+
enumerateIfNonUniform(
|
|
277
205
|
collapseFullSpanStep(
|
|
278
206
|
collapseDegenerateRange(
|
|
279
207
|
collapseOnceStep(collapseUnitStep(segment, spec), spec),
|
|
@@ -337,7 +265,7 @@ function collapseOnceStep(segment, spec) {
|
|
|
337
265
|
}
|
|
338
266
|
return start === "*" ? "" + spec.min : start;
|
|
339
267
|
}
|
|
340
|
-
function
|
|
268
|
+
function enumerateIfNonUniform(segment, spec, cycle) {
|
|
341
269
|
const parts = segment.split("/");
|
|
342
270
|
if (typeof cycle !== "number" || parts.length !== 2 || includes(parts[0], "-")) {
|
|
343
271
|
return segment;
|
|
@@ -476,6 +404,93 @@ function expandMacro(cronString) {
|
|
|
476
404
|
throw new Error("`cronli5` does not recognize the macro `" + trimmed + "`.");
|
|
477
405
|
}
|
|
478
406
|
|
|
407
|
+
// src/core/weekday.ts
|
|
408
|
+
function weekdayDisplayKey(value) {
|
|
409
|
+
return value === 0 ? 7 : value;
|
|
410
|
+
}
|
|
411
|
+
function orderWeekdaysForDisplay(segments) {
|
|
412
|
+
const flattened = segments.flatMap(function flat(segment) {
|
|
413
|
+
return segment.kind === "step" ? segment.fires.map(function single(value) {
|
|
414
|
+
return { kind: "single", value: "" + value };
|
|
415
|
+
}) : [segment];
|
|
416
|
+
});
|
|
417
|
+
function key(segment) {
|
|
418
|
+
return segment.kind === "range" ? weekdayDisplayKey(+segment.bounds[0]) : weekdayDisplayKey(+segment.value);
|
|
419
|
+
}
|
|
420
|
+
return flattened.map(function index(segment, position) {
|
|
421
|
+
return [segment, position];
|
|
422
|
+
}).sort(function byDisplayKey(a, b) {
|
|
423
|
+
return key(a[0]) - key(b[0]) || a[1] - b[1];
|
|
424
|
+
}).map(function unwrap(pair) {
|
|
425
|
+
return pair[0];
|
|
426
|
+
});
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
// src/core/cadence.ts
|
|
430
|
+
function arithmeticStep(values) {
|
|
431
|
+
if (values.length < 5) {
|
|
432
|
+
return null;
|
|
433
|
+
}
|
|
434
|
+
const interval = values[1] - values[0];
|
|
435
|
+
if (interval < 2) {
|
|
436
|
+
return null;
|
|
437
|
+
}
|
|
438
|
+
for (let i = 2; i < values.length; i += 1) {
|
|
439
|
+
if (values[i] - values[i - 1] !== interval) {
|
|
440
|
+
return null;
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
return { start: values[0], interval, last: values[values.length - 1] };
|
|
444
|
+
}
|
|
445
|
+
function segmentsOf(schedule, field) {
|
|
446
|
+
return schedule.analyses.segments[field] ?? [];
|
|
447
|
+
}
|
|
448
|
+
function stepSegment(schedule, field) {
|
|
449
|
+
return segmentsOf(schedule, field)[0];
|
|
450
|
+
}
|
|
451
|
+
function singleValues(segments) {
|
|
452
|
+
const values = [];
|
|
453
|
+
for (const segment of segments) {
|
|
454
|
+
if (segment.kind !== "single") {
|
|
455
|
+
return null;
|
|
456
|
+
}
|
|
457
|
+
values.push(+segment.value);
|
|
458
|
+
}
|
|
459
|
+
return values;
|
|
460
|
+
}
|
|
461
|
+
function offsetCleanStride(stride) {
|
|
462
|
+
return stride.start < stride.interval && 24 % stride.interval === 0;
|
|
463
|
+
}
|
|
464
|
+
function renderStride(spec, parts) {
|
|
465
|
+
const { start, interval, cycle } = spec;
|
|
466
|
+
const tiles = cycle % interval === 0;
|
|
467
|
+
if (start === 0 && tiles) {
|
|
468
|
+
return parts.bare();
|
|
469
|
+
}
|
|
470
|
+
if (start < interval && tiles) {
|
|
471
|
+
return parts.offset();
|
|
472
|
+
}
|
|
473
|
+
return parts.bounded();
|
|
474
|
+
}
|
|
475
|
+
function hourListStride(values) {
|
|
476
|
+
if (values.length < 2) {
|
|
477
|
+
return null;
|
|
478
|
+
}
|
|
479
|
+
const interval = values[1] - values[0];
|
|
480
|
+
if (interval < 2) {
|
|
481
|
+
return null;
|
|
482
|
+
}
|
|
483
|
+
for (let i = 2; i < values.length; i += 1) {
|
|
484
|
+
if (values[i] - values[i - 1] !== interval) {
|
|
485
|
+
return null;
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
if (values[0] !== 0 && values.length < 5) {
|
|
489
|
+
return null;
|
|
490
|
+
}
|
|
491
|
+
return { interval, last: values[values.length - 1], start: values[0] };
|
|
492
|
+
}
|
|
493
|
+
|
|
479
494
|
// src/core/shapes.ts
|
|
480
495
|
function isSingleValue(field) {
|
|
481
496
|
return field !== "*" && !includes(field, ",") && !includes(field, "-") && !includes(field, "/");
|
|
@@ -630,11 +645,11 @@ function analyze(pattern) {
|
|
|
630
645
|
minuteSpan: minuteSpan(pattern.minute),
|
|
631
646
|
segments
|
|
632
647
|
};
|
|
633
|
-
const
|
|
634
|
-
return { ...
|
|
648
|
+
const facts = { analyses, pattern, shapes };
|
|
649
|
+
return { ...facts, plan: selectPlan(facts) };
|
|
635
650
|
}
|
|
636
|
-
function selectPlan(
|
|
637
|
-
const { analyses, pattern, shapes } =
|
|
651
|
+
function selectPlan(facts) {
|
|
652
|
+
const { analyses, pattern, shapes } = facts;
|
|
638
653
|
if (pattern.second !== "0") {
|
|
639
654
|
const seconds = planSeconds(pattern, shapes, analyses);
|
|
640
655
|
if (seconds) {
|
|
@@ -978,72 +993,134 @@ function normalizeOptions(options) {
|
|
|
978
993
|
years: !!options.years
|
|
979
994
|
};
|
|
980
995
|
}
|
|
981
|
-
function describe(
|
|
982
|
-
const
|
|
983
|
-
|
|
984
|
-
|
|
996
|
+
function describe(schedule, opts) {
|
|
997
|
+
const dense = denseCadence(schedule, opts);
|
|
998
|
+
if (dense !== null) {
|
|
999
|
+
return applyYear(dense, schedule, opts);
|
|
1000
|
+
}
|
|
1001
|
+
const body = confinement(schedule, opts) ?? render(schedule, schedule.plan, opts);
|
|
1002
|
+
const lead = isDayUnion(schedule, opts) ? dayUnionMonthLead(schedule, opts) : "";
|
|
1003
|
+
return applyYear(lead + body, schedule, opts);
|
|
985
1004
|
}
|
|
986
|
-
function render(
|
|
1005
|
+
function render(schedule, plan, opts) {
|
|
987
1006
|
const renderer = renderers[plan.kind];
|
|
988
|
-
return renderer(
|
|
1007
|
+
return renderer(schedule, plan, opts);
|
|
989
1008
|
}
|
|
990
|
-
function
|
|
991
|
-
return "
|
|
1009
|
+
function isCadenceShape(shape) {
|
|
1010
|
+
return shape === "step" || shape === "range" || shape === "list";
|
|
992
1011
|
}
|
|
993
|
-
function
|
|
994
|
-
|
|
1012
|
+
function isDenseCadence(schedule, opts) {
|
|
1013
|
+
if (!opts.style.untilWindow || opts.short || schedule.plan.kind !== "composeSeconds" || schedule.plan.rest.kind === "clockTimes" || isDayUnion(schedule, opts)) {
|
|
1014
|
+
return false;
|
|
1015
|
+
}
|
|
1016
|
+
const { shapes } = schedule;
|
|
1017
|
+
return isCadenceShape(shapes.second) && isCadenceShape(shapes.minute) && isCadenceShape(shapes.hour);
|
|
995
1018
|
}
|
|
996
|
-
function
|
|
997
|
-
const
|
|
998
|
-
|
|
1019
|
+
function denseHourFragment(schedule, opts) {
|
|
1020
|
+
const stride = hourStride(schedule);
|
|
1021
|
+
if (stride) {
|
|
1022
|
+
return hourStrideCadence(stride, opts);
|
|
1023
|
+
}
|
|
1024
|
+
if (schedule.shapes.hour === "range") {
|
|
1025
|
+
const segment = segmentsOf(schedule, "hour").find(function range(part) {
|
|
1026
|
+
return part.kind === "range";
|
|
1027
|
+
});
|
|
1028
|
+
return rangeWindow({
|
|
1029
|
+
continuous: false,
|
|
1030
|
+
from: +segment.bounds[0],
|
|
1031
|
+
throughMinute: 0,
|
|
1032
|
+
to: +segment.bounds[1]
|
|
1033
|
+
}, opts);
|
|
1034
|
+
}
|
|
1035
|
+
return "during the " + hourSegmentTimes(schedule, { minute: 0, second: null }, false, opts) + " hours";
|
|
999
1036
|
}
|
|
1000
|
-
function
|
|
1001
|
-
|
|
1037
|
+
function denseMinuteFragment(schedule, opts) {
|
|
1038
|
+
if (schedule.shapes.minute === "step") {
|
|
1039
|
+
return stepCycle60(stepSegment(schedule, "minute"), "minute", "hour", opts);
|
|
1040
|
+
}
|
|
1041
|
+
if (schedule.shapes.minute === "range") {
|
|
1042
|
+
return minuteRangeLead(schedule.pattern.minute, opts);
|
|
1043
|
+
}
|
|
1044
|
+
return strideFromSegments(
|
|
1045
|
+
segmentsOf(schedule, "minute"),
|
|
1046
|
+
"minute",
|
|
1047
|
+
"hour",
|
|
1048
|
+
opts
|
|
1049
|
+
) ?? listPastThe(
|
|
1050
|
+
segmentWords(segmentsOf(schedule, "minute"), opts),
|
|
1051
|
+
"minute",
|
|
1052
|
+
"hour",
|
|
1053
|
+
opts
|
|
1054
|
+
);
|
|
1055
|
+
}
|
|
1056
|
+
function denseCadence(schedule, opts) {
|
|
1057
|
+
if (!isDenseCadence(schedule, opts)) {
|
|
1058
|
+
return null;
|
|
1059
|
+
}
|
|
1060
|
+
const hour = denseHourFragment(schedule, opts);
|
|
1061
|
+
const minute = denseMinuteFragment(schedule, opts);
|
|
1062
|
+
const second = secondsClause(schedule, "minute", opts);
|
|
1063
|
+
const nested = hour + ", " + minute + ", and within each of those minutes, " + second;
|
|
1064
|
+
const anchor = trailingQualifier(schedule, opts).trim();
|
|
1065
|
+
return anchor ? anchor + ", " + nested : nested;
|
|
1066
|
+
}
|
|
1067
|
+
function renderEverySecond(schedule, plan, opts) {
|
|
1068
|
+
return "every second" + trailingQualifier(schedule, opts);
|
|
1069
|
+
}
|
|
1070
|
+
function renderStandaloneSeconds(schedule, plan, opts) {
|
|
1071
|
+
return secondsLeadClause(schedule, opts) + trailingQualifier(schedule, opts);
|
|
1072
|
+
}
|
|
1073
|
+
function renderSecondPastMinute(schedule, plan, opts) {
|
|
1074
|
+
const secondField = schedule.pattern.second;
|
|
1075
|
+
return getNumber(secondField, opts) + " " + pluralize(secondField, "second") + " past the minute, every minute" + trailingQualifier(schedule, opts);
|
|
1076
|
+
}
|
|
1077
|
+
function renderSecondsWithinMinute(schedule, plan, opts) {
|
|
1078
|
+
const minuteField = schedule.pattern.minute;
|
|
1002
1079
|
const minuteWord = getNumber(minuteField, opts);
|
|
1003
1080
|
const minuteUnit = pluralize(minuteField, "minute");
|
|
1004
1081
|
if (plan.singleSecond) {
|
|
1005
|
-
const secondField =
|
|
1006
|
-
return minuteWord + " " + minuteUnit + " and " + getNumber(secondField, opts) + " " + pluralize(secondField, "second") + " past the hour, every hour" + trailingQualifier(
|
|
1082
|
+
const secondField = schedule.pattern.second;
|
|
1083
|
+
return minuteWord + " " + minuteUnit + " and " + getNumber(secondField, opts) + " " + pluralize(secondField, "second") + " past the hour, every hour" + trailingQualifier(schedule, opts);
|
|
1007
1084
|
}
|
|
1008
|
-
return secondsLeadClause(
|
|
1085
|
+
return secondsLeadClause(schedule, opts) + ", " + minuteWord + " " + minuteUnit + " past the hour, every hour" + trailingQualifier(schedule, opts);
|
|
1009
1086
|
}
|
|
1010
|
-
function composeHourCadence(
|
|
1087
|
+
function composeHourCadence(schedule, plan, opts) {
|
|
1011
1088
|
const clockRest = plan.rest.kind === "clockTimes" || plan.rest.kind === "compactClockTimes";
|
|
1012
|
-
if (!clockRest ||
|
|
1089
|
+
if (!clockRest || schedule.shapes.minute !== "single") {
|
|
1013
1090
|
return null;
|
|
1014
1091
|
}
|
|
1015
|
-
const minute = +
|
|
1016
|
-
return hourCadence(
|
|
1092
|
+
const minute = +schedule.pattern.minute;
|
|
1093
|
+
return hourCadence(schedule, minute, opts) ?? hourRangeCadence(schedule, minute, opts);
|
|
1017
1094
|
}
|
|
1018
|
-
function clockTimesConfinement(
|
|
1019
|
-
if (+rest.times[0].minute === 0 &&
|
|
1020
|
-
return secondsLeadClause(
|
|
1095
|
+
function clockTimesConfinement(schedule, rest, opts) {
|
|
1096
|
+
if (+rest.times[0].minute === 0 && schedule.shapes.minute === "single") {
|
|
1097
|
+
return secondsLeadClause(schedule, opts) + " for one minute at " + durationHours(schedule, rest, opts);
|
|
1021
1098
|
}
|
|
1022
|
-
return secondsLeadClause(
|
|
1099
|
+
return secondsLeadClause(schedule, opts) + " of " + clockTimesOf(schedule, rest, opts);
|
|
1023
1100
|
}
|
|
1024
|
-
function renderComposeSeconds(
|
|
1025
|
-
const cadence = composeHourCadence(
|
|
1101
|
+
function renderComposeSeconds(schedule, plan, opts) {
|
|
1102
|
+
const cadence = composeHourCadence(schedule, plan, opts);
|
|
1026
1103
|
if (cadence !== null) {
|
|
1027
1104
|
return cadence;
|
|
1028
1105
|
}
|
|
1029
|
-
if (plan.rest.kind === "clockTimes" && (
|
|
1030
|
-
return clockTimesConfinement(
|
|
1106
|
+
if (plan.rest.kind === "clockTimes" && (schedule.shapes.second === "wildcard" || schedule.shapes.second === "step")) {
|
|
1107
|
+
return clockTimesConfinement(schedule, plan.rest, opts);
|
|
1031
1108
|
}
|
|
1032
|
-
if (
|
|
1033
|
-
return "every second of every other minute" + trailingQualifier(
|
|
1109
|
+
if (schedule.shapes.second === "wildcard" && plan.rest.kind === "minuteFrequency" && plan.rest.hours.kind === "none" && schedule.pattern.minute === "*/2") {
|
|
1110
|
+
return "every second of every other minute" + trailingQualifier(schedule, opts);
|
|
1034
1111
|
}
|
|
1035
|
-
const restOwnsLead = plan.rest.kind === "compactClockTimes" &&
|
|
1036
|
-
const lead = restOwnsLead ? "" : secondsLeadClause(
|
|
1037
|
-
return lead + render(
|
|
1112
|
+
const restOwnsLead = plan.rest.kind === "compactClockTimes" && schedule.analyses.clockSecond;
|
|
1113
|
+
const lead = restOwnsLead ? "" : secondsLeadClause(schedule, opts) + ", ";
|
|
1114
|
+
return lead + render(schedule, plan.rest, opts);
|
|
1038
1115
|
}
|
|
1039
|
-
function durationHours(
|
|
1116
|
+
function durationHours(schedule, plan, opts) {
|
|
1040
1117
|
const hours = plan.times.map(function clock(time) {
|
|
1041
1118
|
return getTime({ hour: time.hour, minute: 0 }, opts);
|
|
1042
1119
|
});
|
|
1043
|
-
const trail = dayQualifier(
|
|
1120
|
+
const trail = dayQualifier(schedule, leadingWords, opts);
|
|
1044
1121
|
return joinList(hours, opts) + (trail && ", " + trail);
|
|
1045
1122
|
}
|
|
1046
|
-
function clockTimesOf(
|
|
1123
|
+
function clockTimesOf(schedule, plan, opts) {
|
|
1047
1124
|
const times = plan.times.map(function clock(time) {
|
|
1048
1125
|
return getTime({
|
|
1049
1126
|
hour: time.hour,
|
|
@@ -1052,21 +1129,21 @@ function clockTimesOf(ir, plan, opts) {
|
|
|
1052
1129
|
explicit: true
|
|
1053
1130
|
}, opts);
|
|
1054
1131
|
});
|
|
1055
|
-
const trail = dayQualifier(
|
|
1132
|
+
const trail = dayQualifier(schedule, leadingWords, opts);
|
|
1056
1133
|
return joinList(times, opts) + (trail && ", " + trail);
|
|
1057
1134
|
}
|
|
1058
|
-
function secondsLeadClause(
|
|
1059
|
-
return secondsClause(
|
|
1135
|
+
function secondsLeadClause(schedule, opts) {
|
|
1136
|
+
return secondsClause(schedule, "minute", opts);
|
|
1060
1137
|
}
|
|
1061
|
-
function secondsClause(
|
|
1062
|
-
const secondField =
|
|
1063
|
-
const shape =
|
|
1138
|
+
function secondsClause(schedule, anchor, opts) {
|
|
1139
|
+
const secondField = schedule.pattern.second;
|
|
1140
|
+
const shape = schedule.shapes.second;
|
|
1064
1141
|
if (secondField === "*") {
|
|
1065
1142
|
return "every second";
|
|
1066
1143
|
}
|
|
1067
1144
|
if (shape === "step") {
|
|
1068
1145
|
return stepCycle60(
|
|
1069
|
-
stepSegment(
|
|
1146
|
+
stepSegment(schedule, "second"),
|
|
1070
1147
|
"second",
|
|
1071
1148
|
anchor,
|
|
1072
1149
|
opts
|
|
@@ -1081,44 +1158,44 @@ function secondsClause(ir, anchor, opts) {
|
|
|
1081
1158
|
return "at " + getNumber(secondField, opts) + " " + pluralize(secondField, "second") + " past the " + anchor;
|
|
1082
1159
|
}
|
|
1083
1160
|
return strideFromSegments(
|
|
1084
|
-
segmentsOf(
|
|
1161
|
+
segmentsOf(schedule, "second"),
|
|
1085
1162
|
"second",
|
|
1086
1163
|
anchor,
|
|
1087
1164
|
opts
|
|
1088
1165
|
) ?? listPastThe(
|
|
1089
|
-
segmentWords(segmentsOf(
|
|
1166
|
+
segmentWords(segmentsOf(schedule, "second"), opts),
|
|
1090
1167
|
"second",
|
|
1091
1168
|
anchor,
|
|
1092
1169
|
opts
|
|
1093
1170
|
);
|
|
1094
1171
|
}
|
|
1095
|
-
function renderEveryMinute(
|
|
1096
|
-
return "every minute" + trailingQualifier(
|
|
1172
|
+
function renderEveryMinute(schedule, plan, opts) {
|
|
1173
|
+
return "every minute" + trailingQualifier(schedule, opts);
|
|
1097
1174
|
}
|
|
1098
|
-
function renderSingleMinute(
|
|
1099
|
-
const minuteField =
|
|
1100
|
-
return getNumber(minuteField, opts) + " " + pluralize(minuteField, "minute") + " past the hour, every hour" + trailingQualifier(
|
|
1175
|
+
function renderSingleMinute(schedule, plan, opts) {
|
|
1176
|
+
const minuteField = schedule.pattern.minute;
|
|
1177
|
+
return getNumber(minuteField, opts) + " " + pluralize(minuteField, "minute") + " past the hour, every hour" + trailingQualifier(schedule, opts);
|
|
1101
1178
|
}
|
|
1102
|
-
function renderRangeOfMinutes(
|
|
1103
|
-
return minuteRangeLead(
|
|
1179
|
+
function renderRangeOfMinutes(schedule, plan, opts) {
|
|
1180
|
+
return minuteRangeLead(schedule.pattern.minute, opts) + trailingQualifier(schedule, opts);
|
|
1104
1181
|
}
|
|
1105
|
-
function renderMultipleMinutes(
|
|
1106
|
-
const stride = strideFromSegments(segmentsOf(
|
|
1182
|
+
function renderMultipleMinutes(schedule, plan, opts) {
|
|
1183
|
+
const stride = strideFromSegments(segmentsOf(schedule, "minute"), "minute", "hour", opts);
|
|
1107
1184
|
return (stride ?? listPastThe(segmentWords(
|
|
1108
|
-
segmentsOf(
|
|
1185
|
+
segmentsOf(schedule, "minute"),
|
|
1109
1186
|
opts
|
|
1110
|
-
), "minute", "hour", opts)) + trailingQualifier(
|
|
1187
|
+
), "minute", "hour", opts)) + trailingQualifier(schedule, opts);
|
|
1111
1188
|
}
|
|
1112
|
-
function renderMinuteFrequency(
|
|
1189
|
+
function renderMinuteFrequency(schedule, plan, opts) {
|
|
1113
1190
|
let phrase = stepCycle60(
|
|
1114
|
-
stepSegment(
|
|
1191
|
+
stepSegment(schedule, "minute"),
|
|
1115
1192
|
"minute",
|
|
1116
1193
|
"hour",
|
|
1117
1194
|
opts
|
|
1118
1195
|
);
|
|
1119
1196
|
if (plan.hours.kind === "during") {
|
|
1120
|
-
const cadence = unevenHourCadence(
|
|
1121
|
-
phrase += cadence ? ", " + cadence : " during the " + hourTimesFromPlan(
|
|
1197
|
+
const cadence = unevenHourCadence(schedule, opts);
|
|
1198
|
+
phrase += cadence ? ", " + cadence : " during the " + hourTimesFromPlan(schedule, plan.hours.times, false, opts) + " hours";
|
|
1122
1199
|
} else if (plan.hours.kind === "window") {
|
|
1123
1200
|
phrase += " " + rangeWindow({
|
|
1124
1201
|
continuous: false,
|
|
@@ -1127,45 +1204,50 @@ function renderMinuteFrequency(ir, plan, opts) {
|
|
|
1127
1204
|
to: plan.hours.to
|
|
1128
1205
|
}, opts);
|
|
1129
1206
|
} else if (plan.hours.kind === "step") {
|
|
1130
|
-
phrase += " " + everyNthHour(stepSegment(
|
|
1207
|
+
phrase += " " + everyNthHour(stepSegment(schedule, "hour"), opts);
|
|
1131
1208
|
}
|
|
1132
|
-
return phrase + trailingQualifier(
|
|
1209
|
+
return phrase + trailingQualifier(schedule, opts);
|
|
1133
1210
|
}
|
|
1134
|
-
function renderMinuteSpanInHour(
|
|
1135
|
-
if (
|
|
1136
|
-
return "every minute of the " + getTime({ hour: plan.hour, minute: 0 }, opts) + " hour" + trailingQualifier(
|
|
1211
|
+
function renderMinuteSpanInHour(schedule, plan, opts) {
|
|
1212
|
+
if (schedule.pattern.minute === "*") {
|
|
1213
|
+
return "every minute of the " + getTime({ hour: plan.hour, minute: 0 }, opts) + " hour" + trailingQualifier(schedule, opts);
|
|
1137
1214
|
}
|
|
1138
|
-
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(
|
|
1215
|
+
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(schedule, opts);
|
|
1139
1216
|
}
|
|
1140
|
-
function renderMinutesAcrossHours(
|
|
1141
|
-
const cadence = unevenHourCadence(
|
|
1217
|
+
function renderMinutesAcrossHours(schedule, plan, opts) {
|
|
1218
|
+
const cadence = unevenHourCadence(schedule, opts);
|
|
1142
1219
|
if (plan.form === "wildcard") {
|
|
1143
1220
|
if (cadence !== null) {
|
|
1144
|
-
return "every minute, " + cadence + trailingQualifier(
|
|
1221
|
+
return "every minute, " + cadence + trailingQualifier(schedule, opts);
|
|
1145
1222
|
}
|
|
1146
|
-
return "every minute during the " + hourTimesFromPlan(
|
|
1223
|
+
return "every minute during the " + hourTimesFromPlan(schedule, plan.times, false, opts) + " hours" + trailingQualifier(schedule, opts);
|
|
1147
1224
|
}
|
|
1148
1225
|
if (plan.form === "range") {
|
|
1149
|
-
const lead2 = minuteRangeLead(
|
|
1226
|
+
const lead2 = minuteRangeLead(schedule.pattern.minute, opts);
|
|
1150
1227
|
if (cadence !== null) {
|
|
1151
|
-
return lead2 + ", " + cadence + trailingQualifier(
|
|
1228
|
+
return lead2 + ", " + cadence + trailingQualifier(schedule, opts);
|
|
1152
1229
|
}
|
|
1153
1230
|
if (singleHourFire(plan.times)) {
|
|
1154
|
-
return lead2 + ", at " + hourTimesFromPlan(
|
|
1231
|
+
return lead2 + ", at " + hourTimesFromPlan(schedule, plan.times, true, opts) + trailingQualifier(schedule, opts);
|
|
1155
1232
|
}
|
|
1156
|
-
return lead2 + " during the " + hourTimesFromPlan(
|
|
1233
|
+
return lead2 + " during the " + hourTimesFromPlan(schedule, plan.times, false, opts) + " hours" + trailingQualifier(schedule, opts);
|
|
1157
1234
|
}
|
|
1158
|
-
const lead = strideFromSegments(
|
|
1159
|
-
|
|
1235
|
+
const lead = strideFromSegments(
|
|
1236
|
+
segmentsOf(schedule, "minute"),
|
|
1237
|
+
"minute",
|
|
1238
|
+
"hour",
|
|
1239
|
+
opts
|
|
1240
|
+
) ?? listPastThe(
|
|
1241
|
+
segmentWords(segmentsOf(schedule, "minute"), opts),
|
|
1160
1242
|
"minute",
|
|
1161
1243
|
"hour",
|
|
1162
1244
|
opts
|
|
1163
1245
|
);
|
|
1164
1246
|
if (cadence !== null) {
|
|
1165
|
-
return lead + ", " + cadence + trailingQualifier(
|
|
1247
|
+
return lead + ", " + cadence + trailingQualifier(schedule, opts);
|
|
1166
1248
|
}
|
|
1167
|
-
const times = hourTimesFromPlan(
|
|
1168
|
-
return lead + ", at " + times + trailingQualifier(
|
|
1249
|
+
const times = hourTimesFromPlan(schedule, plan.times, true, opts);
|
|
1250
|
+
return lead + ", at " + times + trailingQualifier(schedule, opts);
|
|
1169
1251
|
}
|
|
1170
1252
|
var stepOrdinals = {
|
|
1171
1253
|
2: "other",
|
|
@@ -1180,60 +1262,65 @@ function everyNthHour(segment, opts) {
|
|
|
1180
1262
|
const start = segment.startToken === "*" ? 0 : +segment.startToken;
|
|
1181
1263
|
return start === 0 ? base : base + " starting at " + getTime({ hour: start, minute: 0 }, opts);
|
|
1182
1264
|
}
|
|
1183
|
-
function renderMinuteSpanAcrossHourStep(
|
|
1184
|
-
const segment = stepSegment(
|
|
1265
|
+
function renderMinuteSpanAcrossHourStep(schedule, plan, opts) {
|
|
1266
|
+
const segment = stepSegment(schedule, "hour");
|
|
1185
1267
|
if (plan.form === "wildcard") {
|
|
1186
|
-
return "every minute " + everyNthHour(segment, opts) + trailingQualifier(
|
|
1268
|
+
return "every minute " + everyNthHour(segment, opts) + trailingQualifier(schedule, opts);
|
|
1187
1269
|
}
|
|
1188
|
-
const lead = plan.form === "list" ? strideFromSegments(
|
|
1189
|
-
|
|
1270
|
+
const lead = plan.form === "list" ? strideFromSegments(
|
|
1271
|
+
segmentsOf(schedule, "minute"),
|
|
1272
|
+
"minute",
|
|
1273
|
+
"hour",
|
|
1274
|
+
opts
|
|
1275
|
+
) ?? listPastThe(
|
|
1276
|
+
segmentWords(segmentsOf(schedule, "minute"), opts),
|
|
1190
1277
|
"minute",
|
|
1191
1278
|
"hour",
|
|
1192
1279
|
opts
|
|
1193
|
-
) : minuteRangeLead(
|
|
1194
|
-
const cadence = unevenHourCadence(
|
|
1195
|
-
return lead + ", " + (cadence ?? stepHours(segment, opts)) + trailingQualifier(
|
|
1280
|
+
) : minuteRangeLead(schedule.pattern.minute, opts);
|
|
1281
|
+
const cadence = unevenHourCadence(schedule, opts);
|
|
1282
|
+
return lead + ", " + (cadence ?? stepHours(segment, opts)) + trailingQualifier(schedule, opts);
|
|
1196
1283
|
}
|
|
1197
1284
|
function minuteRangeLead(minuteField, opts) {
|
|
1198
1285
|
const bounds = minuteField.split("-");
|
|
1199
1286
|
const num = seriesNumber();
|
|
1200
1287
|
return "every minute from " + num(bounds[0]) + through(opts) + num(bounds[1]) + " past the hour";
|
|
1201
1288
|
}
|
|
1202
|
-
function renderEveryHour(
|
|
1203
|
-
return "every hour" + trailingQualifier(
|
|
1289
|
+
function renderEveryHour(schedule, plan, opts) {
|
|
1290
|
+
return "every hour" + trailingQualifier(schedule, opts);
|
|
1204
1291
|
}
|
|
1205
|
-
function renderHourRange(
|
|
1292
|
+
function renderHourRange(schedule, plan, opts) {
|
|
1206
1293
|
const window = hourWindow(boundedWindow(plan), opts);
|
|
1207
1294
|
if (plan.minuteForm === "wildcard") {
|
|
1208
|
-
return "every minute " + window + trailingQualifier(
|
|
1295
|
+
return "every minute " + window + trailingQualifier(schedule, opts);
|
|
1209
1296
|
}
|
|
1210
1297
|
if (plan.minuteForm === "range") {
|
|
1211
|
-
return minuteRangeLead(
|
|
1298
|
+
return minuteRangeLead(schedule.pattern.minute, opts) + ", " + window + trailingQualifier(schedule, opts);
|
|
1212
1299
|
}
|
|
1213
|
-
return rangeMinuteLead(
|
|
1300
|
+
return rangeMinuteLead(schedule, opts) + " " + window + trailingQualifier(schedule, opts);
|
|
1214
1301
|
}
|
|
1215
|
-
function rangeMinuteLead(
|
|
1216
|
-
if (
|
|
1302
|
+
function rangeMinuteLead(schedule, opts) {
|
|
1303
|
+
if (schedule.pattern.minute === "0") {
|
|
1217
1304
|
return "every hour";
|
|
1218
1305
|
}
|
|
1219
1306
|
return strideFromSegments(
|
|
1220
|
-
segmentsOf(
|
|
1307
|
+
segmentsOf(schedule, "minute"),
|
|
1221
1308
|
"minute",
|
|
1222
1309
|
"hour",
|
|
1223
1310
|
opts
|
|
1224
1311
|
) ?? listPastThe(
|
|
1225
|
-
segmentWords(segmentsOf(
|
|
1312
|
+
segmentWords(segmentsOf(schedule, "minute"), opts),
|
|
1226
1313
|
"minute",
|
|
1227
1314
|
"hour",
|
|
1228
1315
|
opts
|
|
1229
1316
|
);
|
|
1230
1317
|
}
|
|
1231
|
-
function renderHourStep(
|
|
1232
|
-
const cadence = unevenHourCadence(
|
|
1318
|
+
function renderHourStep(schedule, plan, opts) {
|
|
1319
|
+
const cadence = unevenHourCadence(schedule, opts);
|
|
1233
1320
|
if (cadence !== null) {
|
|
1234
|
-
return cadence + trailingQualifier(
|
|
1321
|
+
return cadence + trailingQualifier(schedule, opts);
|
|
1235
1322
|
}
|
|
1236
|
-
return stepHours(stepSegment(
|
|
1323
|
+
return stepHours(stepSegment(schedule, "hour"), opts) + trailingQualifier(schedule, opts);
|
|
1237
1324
|
}
|
|
1238
1325
|
function boundedWindow(plan) {
|
|
1239
1326
|
const continuous = plan.minuteForm === "wildcard";
|
|
@@ -1256,10 +1343,10 @@ function hourWindow(window, opts) {
|
|
|
1256
1343
|
to: window.to
|
|
1257
1344
|
}, opts);
|
|
1258
1345
|
}
|
|
1259
|
-
function renderClockTimes(
|
|
1260
|
-
if (
|
|
1261
|
-
const minute = +
|
|
1262
|
-
const cadence = hourCadence(
|
|
1346
|
+
function renderClockTimes(schedule, plan, opts) {
|
|
1347
|
+
if (schedule.shapes.minute === "single") {
|
|
1348
|
+
const minute = +schedule.pattern.minute;
|
|
1349
|
+
const cadence = hourCadence(schedule, minute, opts) ?? hourRangeCadence(schedule, minute, opts);
|
|
1263
1350
|
if (cadence !== null) {
|
|
1264
1351
|
return cadence;
|
|
1265
1352
|
}
|
|
@@ -1273,47 +1360,52 @@ function renderClockTimes(ir, plan, opts) {
|
|
|
1273
1360
|
plain
|
|
1274
1361
|
}, opts);
|
|
1275
1362
|
});
|
|
1276
|
-
return interpretDayQualifier(
|
|
1363
|
+
return interpretDayQualifier(schedule, opts) + "at " + joinList(times, opts) + dayUnionTrail(schedule, opts);
|
|
1277
1364
|
}
|
|
1278
|
-
function dayUnionTrail(
|
|
1279
|
-
return isDayUnion(
|
|
1365
|
+
function dayUnionTrail(schedule, opts) {
|
|
1366
|
+
return isDayUnion(schedule, opts) ? dayUnionCondition(schedule, opts) : "";
|
|
1280
1367
|
}
|
|
1281
|
-
function renderCompactClockTimes(
|
|
1368
|
+
function renderCompactClockTimes(schedule, plan, opts) {
|
|
1282
1369
|
if (plan.fold) {
|
|
1283
|
-
const cadence2 = hourCadence(
|
|
1370
|
+
const cadence2 = hourCadence(schedule, +plan.minute, opts) ?? hourRangeCadence(schedule, +plan.minute, opts);
|
|
1284
1371
|
if (cadence2 !== null) {
|
|
1285
1372
|
return cadence2;
|
|
1286
1373
|
}
|
|
1287
|
-
const hasRange = segmentsOf(
|
|
1374
|
+
const hasRange = segmentsOf(schedule, "hour").some(function range(segment) {
|
|
1288
1375
|
return segment.kind === "range";
|
|
1289
1376
|
});
|
|
1290
|
-
if (hasRange && !
|
|
1291
|
-
return foldedHourWindows(
|
|
1377
|
+
if (hasRange && !schedule.analyses.clockSecond) {
|
|
1378
|
+
return foldedHourWindows(schedule, plan, opts) + trailingQualifier(schedule, opts);
|
|
1292
1379
|
}
|
|
1293
|
-
const fold = { minute: plan.minute, second:
|
|
1294
|
-
return interpretDayQualifier(
|
|
1380
|
+
const fold = { minute: plan.minute, second: schedule.analyses.clockSecond };
|
|
1381
|
+
return interpretDayQualifier(schedule, opts) + "at " + hourSegmentTimes(schedule, fold, true, opts) + dayUnionTrail(schedule, opts);
|
|
1295
1382
|
}
|
|
1296
1383
|
const minuteLead = (
|
|
1297
1384
|
// The non-fold branch is a minute list, which has segments. An
|
|
1298
1385
|
// offset/uneven step enumerated to that list reads as a stride.
|
|
1299
|
-
strideFromSegments(
|
|
1300
|
-
|
|
1386
|
+
strideFromSegments(
|
|
1387
|
+
segmentsOf(schedule, "minute"),
|
|
1388
|
+
"minute",
|
|
1389
|
+
"hour",
|
|
1390
|
+
opts
|
|
1391
|
+
) ?? listPastThe(
|
|
1392
|
+
segmentWords(segmentsOf(schedule, "minute"), opts),
|
|
1301
1393
|
"minute",
|
|
1302
1394
|
"hour",
|
|
1303
1395
|
opts
|
|
1304
1396
|
)
|
|
1305
1397
|
);
|
|
1306
|
-
const cadence = unevenHourCadence(
|
|
1307
|
-
const phrase = cadence ? minuteLead + ", " + cadence + trailingQualifier(
|
|
1308
|
-
return
|
|
1398
|
+
const cadence = unevenHourCadence(schedule, opts);
|
|
1399
|
+
const phrase = cadence ? minuteLead + ", " + cadence + trailingQualifier(schedule, opts) : minuteLead + ", at " + hourSegmentTimes(schedule, { minute: 0, second: null }, true, opts) + trailingQualifier(schedule, opts);
|
|
1400
|
+
return schedule.analyses.clockSecond ? secondsLeadClause(schedule, opts) + ", " + phrase : phrase;
|
|
1309
1401
|
}
|
|
1310
|
-
function foldedHourWindows(
|
|
1402
|
+
function foldedHourWindows(schedule, plan, opts) {
|
|
1311
1403
|
const minute = plan.minute;
|
|
1312
1404
|
const windows = [];
|
|
1313
|
-
const times = collectHourOutliers(
|
|
1405
|
+
const times = collectHourOutliers(schedule).map(function time(hour) {
|
|
1314
1406
|
return getTime({ hour, minute }, opts);
|
|
1315
1407
|
});
|
|
1316
|
-
segmentsOf(
|
|
1408
|
+
segmentsOf(schedule, "hour").forEach(function classify(segment) {
|
|
1317
1409
|
if (segment.kind === "range") {
|
|
1318
1410
|
windows.push(rangeWindow({
|
|
1319
1411
|
continuous: false,
|
|
@@ -1323,12 +1415,12 @@ function foldedHourWindows(ir, plan, opts) {
|
|
|
1323
1415
|
}, opts));
|
|
1324
1416
|
}
|
|
1325
1417
|
});
|
|
1326
|
-
const phrase = rangeMinuteLead(
|
|
1418
|
+
const phrase = rangeMinuteLead(schedule, opts) + " " + joinList(windows, opts);
|
|
1327
1419
|
return phrase + outlierTail(times, opts);
|
|
1328
1420
|
}
|
|
1329
|
-
function collectHourOutliers(
|
|
1421
|
+
function collectHourOutliers(schedule) {
|
|
1330
1422
|
const hours = [];
|
|
1331
|
-
segmentsOf(
|
|
1423
|
+
segmentsOf(schedule, "hour").forEach(function classify(segment) {
|
|
1332
1424
|
if (segment.kind === "step") {
|
|
1333
1425
|
hours.push(...segment.fires);
|
|
1334
1426
|
} else if (segment.kind !== "range") {
|
|
@@ -1346,16 +1438,16 @@ function outlierTail(times, opts) {
|
|
|
1346
1438
|
function isCadenceField(token) {
|
|
1347
1439
|
return token === "*" || token.startsWith("*/") && token.indexOf("-") === -1;
|
|
1348
1440
|
}
|
|
1349
|
-
function leadingCadence(
|
|
1350
|
-
const { second, minute } =
|
|
1441
|
+
function leadingCadence(schedule, opts) {
|
|
1442
|
+
const { second, minute } = schedule.pattern;
|
|
1351
1443
|
if (isCadenceField(second)) {
|
|
1352
|
-
return { secondLead: true, text: secondsClause(
|
|
1444
|
+
return { secondLead: true, text: secondsClause(schedule, "minute", opts) };
|
|
1353
1445
|
}
|
|
1354
1446
|
if (second === "0" && isCadenceField(minute)) {
|
|
1355
1447
|
const text = minute === "*" ? "every minute" : (
|
|
1356
1448
|
// A clean minute step's first segment is a step segment.
|
|
1357
1449
|
stepCycle60(
|
|
1358
|
-
stepSegment(
|
|
1450
|
+
stepSegment(schedule, "minute"),
|
|
1359
1451
|
"minute",
|
|
1360
1452
|
"hour",
|
|
1361
1453
|
opts
|
|
@@ -1365,19 +1457,19 @@ function leadingCadence(ir, opts) {
|
|
|
1365
1457
|
}
|
|
1366
1458
|
return null;
|
|
1367
1459
|
}
|
|
1368
|
-
function minuteConfinement(
|
|
1369
|
-
const minute =
|
|
1460
|
+
function minuteConfinement(schedule, opts) {
|
|
1461
|
+
const minute = schedule.pattern.minute;
|
|
1370
1462
|
if (minute === "*") {
|
|
1371
1463
|
return "";
|
|
1372
1464
|
}
|
|
1373
1465
|
if (isCadenceField(minute)) {
|
|
1374
1466
|
return " of every other minute";
|
|
1375
1467
|
}
|
|
1376
|
-
const segments = segmentsOf(
|
|
1377
|
-
if (
|
|
1468
|
+
const segments = segmentsOf(schedule, "minute");
|
|
1469
|
+
if (schedule.shapes.minute === "single") {
|
|
1378
1470
|
return " during minute :" + pad(minute);
|
|
1379
1471
|
}
|
|
1380
|
-
if (
|
|
1472
|
+
if (schedule.shapes.minute === "range") {
|
|
1381
1473
|
const bounds = minute.split("-");
|
|
1382
1474
|
return " during minutes :" + pad(bounds[0]) + through(opts) + ":" + pad(bounds[1]);
|
|
1383
1475
|
}
|
|
@@ -1386,64 +1478,61 @@ function minuteConfinement(ir, opts) {
|
|
|
1386
1478
|
});
|
|
1387
1479
|
return " during minutes " + joinList(values, opts);
|
|
1388
1480
|
}
|
|
1389
|
-
function hourConfinement(
|
|
1390
|
-
const hour =
|
|
1481
|
+
function hourConfinement(schedule, opts) {
|
|
1482
|
+
const hour = schedule.pattern.hour;
|
|
1391
1483
|
if (hour === "*") {
|
|
1392
|
-
const minutePinned =
|
|
1484
|
+
const minutePinned = schedule.pattern.minute !== "*" && !isCadenceField(schedule.pattern.minute);
|
|
1393
1485
|
return minutePinned ? " of every hour" : "";
|
|
1394
1486
|
}
|
|
1395
1487
|
if (isCadenceField(hour)) {
|
|
1396
1488
|
return hour === "*/2" ? " of every other hour" : "";
|
|
1397
1489
|
}
|
|
1398
|
-
if (
|
|
1490
|
+
if (schedule.shapes.hour === "single") {
|
|
1399
1491
|
const h = +hour;
|
|
1400
|
-
if (
|
|
1492
|
+
if (schedule.shapes.minute === "step") {
|
|
1401
1493
|
return " from " + getTime({ hour: h, minute: 0 }, opts) + " until " + getTime({ hour: (h + 1) % 24, minute: 0 }, opts);
|
|
1402
1494
|
}
|
|
1403
|
-
if (
|
|
1495
|
+
if (schedule.pattern.minute !== "*" && !isCadenceField(schedule.pattern.minute)) {
|
|
1404
1496
|
return " at " + getTime({ hour: h, minute: 0 }, opts);
|
|
1405
1497
|
}
|
|
1406
1498
|
return " of the " + getTime({ hour: h, minute: 0 }, opts) + " hour";
|
|
1407
1499
|
}
|
|
1408
|
-
if (
|
|
1500
|
+
if (schedule.shapes.hour === "range") {
|
|
1409
1501
|
const bounds = hour.split("-");
|
|
1410
1502
|
return " " + rangeWindow({
|
|
1411
|
-
continuous:
|
|
1503
|
+
continuous: schedule.pattern.minute === "*",
|
|
1412
1504
|
from: +bounds[0],
|
|
1413
1505
|
throughMinute: 0,
|
|
1414
1506
|
to: +bounds[1]
|
|
1415
1507
|
}, opts);
|
|
1416
1508
|
}
|
|
1417
|
-
return " during the " + hourSegmentTimes(
|
|
1418
|
-
}
|
|
1419
|
-
function isContiguousHourRange(ir) {
|
|
1420
|
-
return ir.shapes.hour === "range";
|
|
1509
|
+
return " during the " + hourSegmentTimes(schedule, { minute: 0, second: null }, false, opts) + " hours";
|
|
1421
1510
|
}
|
|
1422
|
-
function confinableHour(
|
|
1423
|
-
if (
|
|
1511
|
+
function confinableHour(schedule) {
|
|
1512
|
+
if (schedule.shapes.hour !== "step") {
|
|
1424
1513
|
return true;
|
|
1425
1514
|
}
|
|
1426
|
-
const segment = stepSegment(
|
|
1427
|
-
return
|
|
1515
|
+
const segment = stepSegment(schedule, "hour");
|
|
1516
|
+
return schedule.pattern.hour === "*/2" || segment.startToken.indexOf("-") !== -1;
|
|
1428
1517
|
}
|
|
1429
|
-
function isMinuteStride(
|
|
1430
|
-
if (
|
|
1518
|
+
function isMinuteStride(schedule) {
|
|
1519
|
+
if (schedule.shapes.minute !== "list") {
|
|
1431
1520
|
return false;
|
|
1432
1521
|
}
|
|
1433
|
-
const values = singleValues(segmentsOf(
|
|
1522
|
+
const values = singleValues(segmentsOf(schedule, "minute"));
|
|
1434
1523
|
return values !== null && arithmeticStep(values) !== null;
|
|
1435
1524
|
}
|
|
1436
|
-
function confinementEligible(
|
|
1437
|
-
const { minute, hour } =
|
|
1525
|
+
function confinementEligible(schedule, lead) {
|
|
1526
|
+
const { minute, hour } = schedule.pattern;
|
|
1438
1527
|
const minuteStep = isCadenceField(minute) && minute !== "*";
|
|
1439
|
-
if (!confinableHour(
|
|
1528
|
+
if (!confinableHour(schedule)) {
|
|
1440
1529
|
return false;
|
|
1441
1530
|
}
|
|
1442
1531
|
if (lead.secondLead) {
|
|
1443
1532
|
if (minuteStep) {
|
|
1444
|
-
return minute === "*/2" &&
|
|
1533
|
+
return minute === "*/2" && schedule.shapes.hour !== "range";
|
|
1445
1534
|
}
|
|
1446
|
-
if (isMinuteStride(
|
|
1535
|
+
if (isMinuteStride(schedule) || schedule.shapes.minute === "list" && schedule.shapes.hour === "list") {
|
|
1447
1536
|
return false;
|
|
1448
1537
|
}
|
|
1449
1538
|
return true;
|
|
@@ -1451,21 +1540,21 @@ function confinementEligible(ir, lead) {
|
|
|
1451
1540
|
if (hour === "*/2") {
|
|
1452
1541
|
return true;
|
|
1453
1542
|
}
|
|
1454
|
-
return
|
|
1543
|
+
return schedule.shapes.hour === "single" && minute === "*/2";
|
|
1455
1544
|
}
|
|
1456
|
-
function confinement(
|
|
1545
|
+
function confinement(schedule, opts) {
|
|
1457
1546
|
if (!opts.style.untilWindow || opts.short) {
|
|
1458
1547
|
return null;
|
|
1459
1548
|
}
|
|
1460
|
-
if (
|
|
1549
|
+
if (schedule.pattern.minute === "*" && schedule.pattern.hour === "*") {
|
|
1461
1550
|
return null;
|
|
1462
1551
|
}
|
|
1463
|
-
const lead = leadingCadence(
|
|
1464
|
-
if (!lead || !confinementEligible(
|
|
1552
|
+
const lead = leadingCadence(schedule, opts);
|
|
1553
|
+
if (!lead || !confinementEligible(schedule, lead)) {
|
|
1465
1554
|
return null;
|
|
1466
1555
|
}
|
|
1467
|
-
const minutePart = lead.secondLead ? minuteConfinement(
|
|
1468
|
-
return lead.text + minutePart + hourConfinement(
|
|
1556
|
+
const minutePart = lead.secondLead ? minuteConfinement(schedule, opts) : "";
|
|
1557
|
+
return lead.text + minutePart + hourConfinement(schedule, opts) + trailingQualifier(schedule, opts);
|
|
1469
1558
|
}
|
|
1470
1559
|
var renderers = {
|
|
1471
1560
|
clockTimes: renderClockTimes,
|
|
@@ -1487,23 +1576,25 @@ var renderers = {
|
|
|
1487
1576
|
singleMinute: renderSingleMinute,
|
|
1488
1577
|
standaloneSeconds: renderStandaloneSeconds
|
|
1489
1578
|
};
|
|
1490
|
-
function
|
|
1579
|
+
function renderStride2(stride, opts) {
|
|
1491
1580
|
const { interval, start, last, cycle, unit, anchor } = stride;
|
|
1492
1581
|
const cadence = "every " + getNumber(interval, opts) + " " + unit + "s";
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1582
|
+
return renderStride({ start, interval, cycle }, {
|
|
1583
|
+
bare: () => cadence,
|
|
1584
|
+
// A clean wrap from a non-zero offset: name the start, no endpoint.
|
|
1585
|
+
offset: () => cadence + " from " + getNumber(start, opts) + " " + pluralize(start, unit) + " past the " + anchor,
|
|
1586
|
+
// A bounded, non-wrapping set: pin both endpoints. Each bound is a value,
|
|
1587
|
+
// so it reads as a digit, matching the range idiom ("from 0 through 30").
|
|
1588
|
+
bounded: () => {
|
|
1589
|
+
const num = seriesNumber();
|
|
1590
|
+
return cadence + " from " + num(start) + through(opts) + num(last) + " " + pluralize(last, unit) + " past the " + anchor;
|
|
1591
|
+
}
|
|
1592
|
+
});
|
|
1502
1593
|
}
|
|
1503
1594
|
function strideFromSegments(segments, unit, anchor, opts) {
|
|
1504
1595
|
const values = singleValues(segments);
|
|
1505
1596
|
const step = values && arithmeticStep(values);
|
|
1506
|
-
return step ?
|
|
1597
|
+
return step ? renderStride2({ ...step, cycle: 60, unit, anchor }, opts) : null;
|
|
1507
1598
|
}
|
|
1508
1599
|
function stepCycle60(segment, unit, anchor, opts) {
|
|
1509
1600
|
if (segment.startToken.indexOf("-") !== -1) {
|
|
@@ -1513,7 +1604,7 @@ function stepCycle60(segment, unit, anchor, opts) {
|
|
|
1513
1604
|
if (start !== 0 && segment.fires.length <= 3) {
|
|
1514
1605
|
return listPastThe(numberWords(segment.fires, opts), unit, anchor, opts);
|
|
1515
1606
|
}
|
|
1516
|
-
return
|
|
1607
|
+
return renderStride2({
|
|
1517
1608
|
interval: segment.interval,
|
|
1518
1609
|
start,
|
|
1519
1610
|
last: segment.fires[segment.fires.length - 1],
|
|
@@ -1539,24 +1630,21 @@ function stepHours(segment, opts) {
|
|
|
1539
1630
|
function hourStrideCadence(stride, opts) {
|
|
1540
1631
|
const { start, interval, last } = stride;
|
|
1541
1632
|
const cadence = "every " + getNumber(interval, opts) + " hours";
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
return cadence + " from " + getTime({ hour: start, minute: 0 }, opts);
|
|
1548
|
-
}
|
|
1549
|
-
return cadence + " from " + getTime({ hour: start, minute: 0 }, opts) + through(opts) + getTime({ hour: last, minute: 0 }, opts);
|
|
1633
|
+
return renderStride({ start, interval, cycle: 24 }, {
|
|
1634
|
+
bare: () => cadence,
|
|
1635
|
+
offset: () => cadence + " from " + getTime({ hour: start, minute: 0 }, opts),
|
|
1636
|
+
bounded: () => cadence + " from " + getTime({ hour: start, minute: 0 }, opts) + through(opts) + getTime({ hour: last, minute: 0 }, opts)
|
|
1637
|
+
});
|
|
1550
1638
|
}
|
|
1551
|
-
function unevenHourCadence(
|
|
1552
|
-
const stride = hourStride(
|
|
1639
|
+
function unevenHourCadence(schedule, opts) {
|
|
1640
|
+
const stride = hourStride(schedule);
|
|
1553
1641
|
if (!stride || offsetCleanStride(stride)) {
|
|
1554
1642
|
return null;
|
|
1555
1643
|
}
|
|
1556
1644
|
return hourStrideCadence(stride, opts);
|
|
1557
1645
|
}
|
|
1558
|
-
function hourStride(
|
|
1559
|
-
const segments = segmentsOf(
|
|
1646
|
+
function hourStride(schedule) {
|
|
1647
|
+
const segments = segmentsOf(schedule, "hour");
|
|
1560
1648
|
if (segments.length === 1 && segments[0].kind === "step") {
|
|
1561
1649
|
const segment = segments[0];
|
|
1562
1650
|
if (segment.fires.length < 2) {
|
|
@@ -1568,57 +1656,57 @@ function hourStride(ir) {
|
|
|
1568
1656
|
const values = singleValues(segments);
|
|
1569
1657
|
return values && hourListStride(values);
|
|
1570
1658
|
}
|
|
1571
|
-
function subMinuteSecond(
|
|
1572
|
-
return
|
|
1659
|
+
function subMinuteSecond(schedule) {
|
|
1660
|
+
return schedule.pattern.second === "*" || schedule.shapes.second === "step";
|
|
1573
1661
|
}
|
|
1574
|
-
function hourCadenceLead(
|
|
1662
|
+
function hourCadenceLead(schedule, minute, opts) {
|
|
1575
1663
|
if (minute === 0) {
|
|
1576
|
-
if (subMinuteSecond(
|
|
1577
|
-
return secondsClause(
|
|
1664
|
+
if (subMinuteSecond(schedule)) {
|
|
1665
|
+
return secondsClause(schedule, "minute", opts) + " for one minute";
|
|
1578
1666
|
}
|
|
1579
|
-
return secondsClause(
|
|
1667
|
+
return secondsClause(schedule, "hour", opts);
|
|
1580
1668
|
}
|
|
1581
1669
|
const minutePhrase = getNumber(minute, opts) + " " + pluralize(minute, "minute") + " past the hour";
|
|
1582
|
-
if (
|
|
1670
|
+
if (schedule.pattern.second === "0") {
|
|
1583
1671
|
return minutePhrase;
|
|
1584
1672
|
}
|
|
1585
|
-
return secondsClause(
|
|
1673
|
+
return secondsClause(schedule, "minute", opts) + ", " + minutePhrase;
|
|
1586
1674
|
}
|
|
1587
|
-
function hourCadence(
|
|
1588
|
-
const stride = hourStride(
|
|
1675
|
+
function hourCadence(schedule, minute, opts) {
|
|
1676
|
+
const stride = hourStride(schedule);
|
|
1589
1677
|
if (!stride) {
|
|
1590
1678
|
return null;
|
|
1591
1679
|
}
|
|
1592
1680
|
const fires = (stride.last - stride.start) / stride.interval + 1;
|
|
1593
|
-
if (
|
|
1681
|
+
if (schedule.pattern.second === "0" && fires <= maxClockTimes && offsetCleanStride(stride)) {
|
|
1594
1682
|
return null;
|
|
1595
1683
|
}
|
|
1596
|
-
const minuteZeroStride = minute === 0 && subMinuteSecond(
|
|
1684
|
+
const minuteZeroStride = minute === 0 && subMinuteSecond(schedule) && cleanStrideSegment(schedule);
|
|
1597
1685
|
if (minuteZeroStride) {
|
|
1598
|
-
return secondsClause(
|
|
1686
|
+
return secondsClause(schedule, "minute", opts) + " for one minute " + everyNthHour(minuteZeroStride, opts) + trailingQualifier(schedule, opts);
|
|
1599
1687
|
}
|
|
1600
|
-
if (minute === 0 &&
|
|
1601
|
-
return hourStrideCadence(stride, opts) + trailingQualifier(
|
|
1688
|
+
if (minute === 0 && schedule.pattern.second === "0") {
|
|
1689
|
+
return hourStrideCadence(stride, opts) + trailingQualifier(schedule, opts);
|
|
1602
1690
|
}
|
|
1603
|
-
return hourCadenceLead(
|
|
1691
|
+
return hourCadenceLead(schedule, minute, opts) + ", " + hourStrideCadence(stride, opts) + trailingQualifier(schedule, opts);
|
|
1604
1692
|
}
|
|
1605
|
-
function cleanStrideSegment(
|
|
1606
|
-
const segments = segmentsOf(
|
|
1693
|
+
function cleanStrideSegment(schedule) {
|
|
1694
|
+
const segments = segmentsOf(schedule, "hour");
|
|
1607
1695
|
const segment = segments.length === 1 && segments[0];
|
|
1608
1696
|
if (!segment || segment.kind !== "step" || segment.startToken.indexOf("-") !== -1 || !(segment.interval in stepOrdinals)) {
|
|
1609
1697
|
return null;
|
|
1610
1698
|
}
|
|
1611
1699
|
return segment;
|
|
1612
1700
|
}
|
|
1613
|
-
function hasHourWindow(
|
|
1614
|
-
return segmentsOf(
|
|
1701
|
+
function hasHourWindow(schedule) {
|
|
1702
|
+
return segmentsOf(schedule, "hour").some(function range(segment) {
|
|
1615
1703
|
return segment.kind === "range";
|
|
1616
1704
|
});
|
|
1617
1705
|
}
|
|
1618
|
-
function hourRangeWindowTail(
|
|
1706
|
+
function hourRangeWindowTail(schedule, opts) {
|
|
1619
1707
|
const windows = [];
|
|
1620
|
-
const outlierHours = collectHourOutliers(
|
|
1621
|
-
segmentsOf(
|
|
1708
|
+
const outlierHours = collectHourOutliers(schedule);
|
|
1709
|
+
segmentsOf(schedule, "hour").forEach(function classify(segment) {
|
|
1622
1710
|
if (segment.kind === "range") {
|
|
1623
1711
|
windows.push(rangeWindow({
|
|
1624
1712
|
continuous: false,
|
|
@@ -1634,17 +1722,17 @@ function hourRangeWindowTail(ir, opts) {
|
|
|
1634
1722
|
});
|
|
1635
1723
|
return phrase + outlierTail(times, opts);
|
|
1636
1724
|
}
|
|
1637
|
-
function hourRangeCadence(
|
|
1638
|
-
if (minute !== 0 || !hasHourWindow(
|
|
1725
|
+
function hourRangeCadence(schedule, minute, opts) {
|
|
1726
|
+
if (minute !== 0 || !hasHourWindow(schedule)) {
|
|
1639
1727
|
return null;
|
|
1640
1728
|
}
|
|
1641
|
-
if (
|
|
1729
|
+
if (schedule.pattern.second === "0") {
|
|
1642
1730
|
return null;
|
|
1643
1731
|
}
|
|
1644
|
-
if (subMinuteSecond(
|
|
1645
|
-
return secondsClause(
|
|
1732
|
+
if (subMinuteSecond(schedule)) {
|
|
1733
|
+
return secondsClause(schedule, "minute", opts) + " for one minute during the " + hourSegmentTimes(schedule, { minute: 0, second: null }, false, opts) + " hours" + trailingQualifier(schedule, opts);
|
|
1646
1734
|
}
|
|
1647
|
-
return hourCadenceLead(
|
|
1735
|
+
return hourCadenceLead(schedule, minute, opts) + ", " + hourRangeWindowTail(schedule, opts) + trailingQualifier(schedule, opts);
|
|
1648
1736
|
}
|
|
1649
1737
|
function seriesNumber() {
|
|
1650
1738
|
return function format(n) {
|
|
@@ -1703,11 +1791,11 @@ function hourTimes(hours, opts) {
|
|
|
1703
1791
|
function singleHourFire(times) {
|
|
1704
1792
|
return times.kind === "fires" && times.fires.length === 1;
|
|
1705
1793
|
}
|
|
1706
|
-
function hourTimesFromPlan(
|
|
1794
|
+
function hourTimesFromPlan(schedule, times, atContext, opts) {
|
|
1707
1795
|
if (times.kind === "fires") {
|
|
1708
1796
|
return hourTimes(times.fires, opts);
|
|
1709
1797
|
}
|
|
1710
|
-
return hourSegmentTimes(
|
|
1798
|
+
return hourSegmentTimes(schedule, { minute: 0, second: null }, atContext, opts);
|
|
1711
1799
|
}
|
|
1712
1800
|
function segmentHours(segment) {
|
|
1713
1801
|
if (segment.kind === "range") {
|
|
@@ -1715,9 +1803,9 @@ function segmentHours(segment) {
|
|
|
1715
1803
|
}
|
|
1716
1804
|
return segment.kind === "step" ? segment.fires : [segment.value];
|
|
1717
1805
|
}
|
|
1718
|
-
function hourSegmentTimes(
|
|
1806
|
+
function hourSegmentTimes(schedule, fold, atContext, opts) {
|
|
1719
1807
|
const { minute, second } = fold;
|
|
1720
|
-
const segments = segmentsOf(
|
|
1808
|
+
const segments = segmentsOf(schedule, "hour");
|
|
1721
1809
|
const plain = mixedTwelve(segments.flatMap(function entries(segment) {
|
|
1722
1810
|
return segmentHours(segment).map(function entry(hour) {
|
|
1723
1811
|
return { hour: +hour, minute, second };
|
|
@@ -1780,85 +1868,85 @@ var leadingWords = {
|
|
|
1780
1868
|
stepDate: "",
|
|
1781
1869
|
weekday: "every "
|
|
1782
1870
|
};
|
|
1783
|
-
function trailingQualifier(
|
|
1784
|
-
if (isDayUnion(
|
|
1785
|
-
return dayUnionCondition(
|
|
1871
|
+
function trailingQualifier(schedule, opts) {
|
|
1872
|
+
if (isDayUnion(schedule, opts)) {
|
|
1873
|
+
return dayUnionCondition(schedule, opts);
|
|
1786
1874
|
}
|
|
1787
|
-
const phrase = dayQualifier(
|
|
1875
|
+
const phrase = dayQualifier(schedule, trailingWords, opts);
|
|
1788
1876
|
return phrase && " " + phrase;
|
|
1789
1877
|
}
|
|
1790
|
-
function interpretDayQualifier(
|
|
1791
|
-
if (isDayUnion(
|
|
1878
|
+
function interpretDayQualifier(schedule, opts) {
|
|
1879
|
+
if (isDayUnion(schedule, opts)) {
|
|
1792
1880
|
return "";
|
|
1793
1881
|
}
|
|
1794
|
-
return dayQualifier(
|
|
1882
|
+
return dayQualifier(schedule, leadingWords, opts) + " ";
|
|
1795
1883
|
}
|
|
1796
|
-
function dayQualifier(
|
|
1797
|
-
const pattern =
|
|
1884
|
+
function dayQualifier(schedule, words, opts) {
|
|
1885
|
+
const pattern = schedule.pattern;
|
|
1798
1886
|
if (pattern.date !== "*" && pattern.weekday !== "*") {
|
|
1799
|
-
return dateOrWeekday(
|
|
1887
|
+
return dateOrWeekday(schedule, opts);
|
|
1800
1888
|
}
|
|
1801
1889
|
if (pattern.date !== "*") {
|
|
1802
|
-
return datePhrase(
|
|
1890
|
+
return datePhrase(schedule, words, opts);
|
|
1803
1891
|
}
|
|
1804
1892
|
if (pattern.weekday !== "*") {
|
|
1805
1893
|
const quartzWeekday = quartzWeekdayPhrase(pattern.weekday, opts);
|
|
1806
1894
|
if (quartzWeekday) {
|
|
1807
|
-
return monthScopeForRecurrence(quartzWeekday,
|
|
1895
|
+
return monthScopeForRecurrence(quartzWeekday, schedule, opts);
|
|
1808
1896
|
}
|
|
1809
|
-
const weekdays = words.weekday + weekdayPhrase(
|
|
1810
|
-
return weekdays + monthScope(
|
|
1897
|
+
const weekdays = words.weekday + weekdayPhrase(schedule, words.recurringWeekday, opts);
|
|
1898
|
+
return weekdays + monthScope(schedule, opts);
|
|
1811
1899
|
}
|
|
1812
1900
|
if (pattern.month !== "*") {
|
|
1813
|
-
return words.month + monthName(
|
|
1901
|
+
return words.month + monthName(schedule, opts);
|
|
1814
1902
|
}
|
|
1815
1903
|
return words.all;
|
|
1816
1904
|
}
|
|
1817
|
-
function datePhrase(
|
|
1818
|
-
const pattern =
|
|
1905
|
+
function datePhrase(schedule, words, opts) {
|
|
1906
|
+
const pattern = schedule.pattern;
|
|
1819
1907
|
const quartzDate = quartzDatePhrase(pattern.date, opts);
|
|
1820
1908
|
if (quartzDate) {
|
|
1821
|
-
return monthScopeForRecurrence(quartzDate,
|
|
1909
|
+
return monthScopeForRecurrence(quartzDate, schedule, opts);
|
|
1822
1910
|
}
|
|
1823
1911
|
if (isOpenStep(pattern.date)) {
|
|
1824
1912
|
return monthScopeForRecurrence(
|
|
1825
1913
|
words.stepDate + stepDates(pattern.date),
|
|
1826
|
-
|
|
1914
|
+
schedule,
|
|
1827
1915
|
opts
|
|
1828
1916
|
);
|
|
1829
1917
|
}
|
|
1830
|
-
if (pattern.month !== "*" && !monthFoldsIntoDate(
|
|
1831
|
-
return "on the " + dateOrdinals(
|
|
1918
|
+
if (pattern.month !== "*" && !monthFoldsIntoDate(schedule)) {
|
|
1919
|
+
return "on the " + dateOrdinals(schedule, opts) + monthScope(schedule, opts);
|
|
1832
1920
|
}
|
|
1833
1921
|
if (pattern.month !== "*") {
|
|
1834
|
-
return "on " + monthDatePhrase(
|
|
1922
|
+
return "on " + monthDatePhrase(schedule, opts);
|
|
1835
1923
|
}
|
|
1836
|
-
return "on the " + dateOrdinals(
|
|
1924
|
+
return "on the " + dateOrdinals(schedule, opts);
|
|
1837
1925
|
}
|
|
1838
|
-
function monthFoldsIntoDate(
|
|
1839
|
-
return !oddEvenMonth(
|
|
1840
|
-
segmentsOf(
|
|
1926
|
+
function monthFoldsIntoDate(schedule) {
|
|
1927
|
+
return !oddEvenMonth(schedule.pattern.month) && // Reached only with a restricted month, which has segments.
|
|
1928
|
+
segmentsOf(schedule, "month").every(function flat(segment) {
|
|
1841
1929
|
return segment.kind !== "range";
|
|
1842
1930
|
});
|
|
1843
1931
|
}
|
|
1844
|
-
function isDayUnion(
|
|
1845
|
-
return
|
|
1932
|
+
function isDayUnion(schedule, opts) {
|
|
1933
|
+
return schedule.pattern.date !== "*" && schedule.pattern.weekday !== "*" && !!opts.style.untilWindow && !opts.short;
|
|
1846
1934
|
}
|
|
1847
|
-
function dayUnionCondition(
|
|
1935
|
+
function dayUnionCondition(schedule, opts) {
|
|
1848
1936
|
const pieces = [
|
|
1849
|
-
...dayUnionDatePieces(
|
|
1850
|
-
...dayUnionWeekdayPieces(
|
|
1937
|
+
...dayUnionDatePieces(schedule, opts),
|
|
1938
|
+
...dayUnionWeekdayPieces(schedule, opts)
|
|
1851
1939
|
];
|
|
1852
1940
|
return " whenever the day is " + joinOr(pieces, opts);
|
|
1853
1941
|
}
|
|
1854
|
-
function dayUnionMonthLead(
|
|
1855
|
-
if (
|
|
1942
|
+
function dayUnionMonthLead(schedule, opts) {
|
|
1943
|
+
if (schedule.pattern.month === "*") {
|
|
1856
1944
|
return "";
|
|
1857
1945
|
}
|
|
1858
|
-
return "in " + monthName(
|
|
1946
|
+
return "in " + monthName(schedule, opts) + " ";
|
|
1859
1947
|
}
|
|
1860
|
-
function dayUnionDatePieces(
|
|
1861
|
-
const dateField =
|
|
1948
|
+
function dayUnionDatePieces(schedule, opts) {
|
|
1949
|
+
const dateField = schedule.pattern.date;
|
|
1862
1950
|
const quartz = quartzDatePhrase(dateField, opts);
|
|
1863
1951
|
if (quartz) {
|
|
1864
1952
|
return [quartz.replace(/^on /, "")];
|
|
@@ -1868,7 +1956,7 @@ function dayUnionDatePieces(ir, opts) {
|
|
|
1868
1956
|
return [oddEven];
|
|
1869
1957
|
}
|
|
1870
1958
|
const pieces = [];
|
|
1871
|
-
segmentsOf(
|
|
1959
|
+
segmentsOf(schedule, "date").forEach(function expand(segment) {
|
|
1872
1960
|
if (segment.kind === "range") {
|
|
1873
1961
|
pieces.push("from the " + getOrdinal(segment.bounds[0]) + through(opts) + "the " + getOrdinal(segment.bounds[1]));
|
|
1874
1962
|
} else if (segment.kind === "step") {
|
|
@@ -1881,14 +1969,14 @@ function dayUnionDatePieces(ir, opts) {
|
|
|
1881
1969
|
});
|
|
1882
1970
|
return pieces;
|
|
1883
1971
|
}
|
|
1884
|
-
function dayUnionWeekdayPieces(
|
|
1885
|
-
const weekdayField =
|
|
1972
|
+
function dayUnionWeekdayPieces(schedule, opts) {
|
|
1973
|
+
const weekdayField = schedule.pattern.weekday;
|
|
1886
1974
|
const quartz = quartzWeekdayPhrase(weekdayField, opts);
|
|
1887
1975
|
if (quartz) {
|
|
1888
1976
|
return [quartz.replace(/^on /, "")];
|
|
1889
1977
|
}
|
|
1890
1978
|
const pieces = [];
|
|
1891
|
-
segmentsOf(
|
|
1979
|
+
segmentsOf(schedule, "weekday").forEach(function expand(segment) {
|
|
1892
1980
|
if (segment.kind === "range" && segment.bounds[0] === "1" && segment.bounds[1] === "5") {
|
|
1893
1981
|
pieces.push("a weekday");
|
|
1894
1982
|
} else if (segment.kind === "range") {
|
|
@@ -1916,16 +2004,16 @@ function oddEvenDay(dateField) {
|
|
|
1916
2004
|
}
|
|
1917
2005
|
return start === "2" ? "an even-numbered day" : null;
|
|
1918
2006
|
}
|
|
1919
|
-
function dateOrWeekday(
|
|
1920
|
-
const pattern =
|
|
1921
|
-
const weekdayPart = quartzWeekdayPhrase(pattern.weekday, opts) || "on " + weekdayPhrase(
|
|
1922
|
-
if (pattern.month !== "*" && monthFoldsIntoDate(
|
|
1923
|
-
return "on " + monthDatePhrase(
|
|
2007
|
+
function dateOrWeekday(schedule, opts) {
|
|
2008
|
+
const pattern = schedule.pattern;
|
|
2009
|
+
const weekdayPart = quartzWeekdayPhrase(pattern.weekday, opts) || "on " + weekdayPhrase(schedule, false, opts);
|
|
2010
|
+
if (pattern.month !== "*" && monthFoldsIntoDate(schedule) && !quartzDatePhrase(pattern.date, opts) && !isOpenStep(pattern.date)) {
|
|
2011
|
+
return "on " + monthDatePhrase(schedule, opts) + " or " + weekdayPart + " in " + monthName(schedule, opts);
|
|
1924
2012
|
}
|
|
1925
|
-
return datePart(
|
|
2013
|
+
return datePart(schedule, opts) + " or " + weekdayPart + orMonthScope(schedule, opts);
|
|
1926
2014
|
}
|
|
1927
|
-
function datePart(
|
|
1928
|
-
const pattern =
|
|
2015
|
+
function datePart(schedule, opts) {
|
|
2016
|
+
const pattern = schedule.pattern;
|
|
1929
2017
|
const quartzDate = quartzDatePhrase(pattern.date, opts);
|
|
1930
2018
|
if (quartzDate) {
|
|
1931
2019
|
return quartzDate;
|
|
@@ -1933,13 +2021,13 @@ function datePart(ir, opts) {
|
|
|
1933
2021
|
if (isOpenStep(pattern.date)) {
|
|
1934
2022
|
return stepDates(pattern.date);
|
|
1935
2023
|
}
|
|
1936
|
-
return "on the " + dateOrdinals(
|
|
2024
|
+
return "on the " + dateOrdinals(schedule, opts);
|
|
1937
2025
|
}
|
|
1938
|
-
function orMonthScope(
|
|
1939
|
-
if (
|
|
2026
|
+
function orMonthScope(schedule, opts) {
|
|
2027
|
+
if (schedule.pattern.month === "*") {
|
|
1940
2028
|
return "";
|
|
1941
2029
|
}
|
|
1942
|
-
return ", in " + monthName(
|
|
2030
|
+
return ", in " + monthName(schedule, opts);
|
|
1943
2031
|
}
|
|
1944
2032
|
function quartzDatePhrase(dateField, opts) {
|
|
1945
2033
|
if (dateField === "L") {
|
|
@@ -1966,39 +2054,39 @@ function quartzWeekdayPhrase(weekdayField, opts) {
|
|
|
1966
2054
|
return "on the last " + getWeekday(weekdayField.slice(0, -1), opts) + " of the month";
|
|
1967
2055
|
}
|
|
1968
2056
|
}
|
|
1969
|
-
function monthDatePhrase(
|
|
1970
|
-
const month = monthName(
|
|
2057
|
+
function monthDatePhrase(schedule, opts) {
|
|
2058
|
+
const month = monthName(schedule, opts);
|
|
1971
2059
|
const days = renderSegments(
|
|
1972
|
-
segmentsOf(
|
|
2060
|
+
segmentsOf(schedule, "date"),
|
|
1973
2061
|
opts.style.ordinals ? getOrdinal : cardinalDay,
|
|
1974
2062
|
opts
|
|
1975
2063
|
);
|
|
1976
|
-
if (opts.style.dayFirst &&
|
|
1977
|
-
return "the " + getOrdinal(
|
|
2064
|
+
if (opts.style.dayFirst && schedule.shapes.date === "single" && schedule.shapes.month !== "single") {
|
|
2065
|
+
return "the " + getOrdinal(schedule.pattern.date) + " of " + month;
|
|
1978
2066
|
}
|
|
1979
2067
|
return opts.style.dayFirst ? days + " " + month : month + " " + days;
|
|
1980
2068
|
}
|
|
1981
2069
|
function cardinalDay(value) {
|
|
1982
2070
|
return "" + value;
|
|
1983
2071
|
}
|
|
1984
|
-
function monthScope(
|
|
1985
|
-
if (
|
|
2072
|
+
function monthScope(schedule, opts) {
|
|
2073
|
+
if (schedule.pattern.month === "*") {
|
|
1986
2074
|
return "";
|
|
1987
2075
|
}
|
|
1988
|
-
return " in " + monthName(
|
|
2076
|
+
return " in " + monthName(schedule, opts);
|
|
1989
2077
|
}
|
|
1990
|
-
function monthScopeForRecurrence(phrase,
|
|
1991
|
-
if (
|
|
2078
|
+
function monthScopeForRecurrence(phrase, schedule, opts) {
|
|
2079
|
+
if (schedule.pattern.month === "*") {
|
|
1992
2080
|
return phrase;
|
|
1993
2081
|
}
|
|
1994
2082
|
const carriesRecurrence = phrase.indexOf(" of the month") !== -1;
|
|
1995
|
-
if (carriesRecurrence &&
|
|
1996
|
-
return phrase.replace(" of the month", " of each month") + " from " + monthName(
|
|
2083
|
+
if (carriesRecurrence && schedule.shapes.month === "range") {
|
|
2084
|
+
return phrase.replace(" of the month", " of each month") + " from " + monthName(schedule, opts);
|
|
1997
2085
|
}
|
|
1998
|
-
if (carriesRecurrence && (
|
|
1999
|
-
return phrase.replace(" of the month", "") + " in " + monthName(
|
|
2086
|
+
if (carriesRecurrence && (schedule.shapes.month === "single" || schedule.shapes.month === "step")) {
|
|
2087
|
+
return phrase.replace(" of the month", "") + " in " + monthName(schedule, opts);
|
|
2000
2088
|
}
|
|
2001
|
-
return phrase + " in " + monthName(
|
|
2089
|
+
return phrase + " in " + monthName(schedule, opts);
|
|
2002
2090
|
}
|
|
2003
2091
|
function stepDates(dateField) {
|
|
2004
2092
|
const parts = dateField.split("/");
|
|
@@ -2011,15 +2099,15 @@ function stepDates(dateField) {
|
|
|
2011
2099
|
}
|
|
2012
2100
|
return phrase;
|
|
2013
2101
|
}
|
|
2014
|
-
function dateOrdinals(
|
|
2015
|
-
return renderSegments(segmentsOf(
|
|
2102
|
+
function dateOrdinals(schedule, opts) {
|
|
2103
|
+
return renderSegments(segmentsOf(schedule, "date"), getOrdinal, opts);
|
|
2016
2104
|
}
|
|
2017
|
-
function monthName(
|
|
2018
|
-
const oddEven = oddEvenMonth(
|
|
2105
|
+
function monthName(schedule, opts) {
|
|
2106
|
+
const oddEven = oddEvenMonth(schedule.pattern.month);
|
|
2019
2107
|
if (oddEven) {
|
|
2020
2108
|
return oddEven;
|
|
2021
2109
|
}
|
|
2022
|
-
return renderSegments(segmentsOf(
|
|
2110
|
+
return renderSegments(segmentsOf(schedule, "month"), function name(value) {
|
|
2023
2111
|
return getMonth(value, opts);
|
|
2024
2112
|
}, opts);
|
|
2025
2113
|
}
|
|
@@ -2036,8 +2124,8 @@ function oddEvenMonth(monthField) {
|
|
|
2036
2124
|
}
|
|
2037
2125
|
return start === "2" ? "every even-numbered month" : null;
|
|
2038
2126
|
}
|
|
2039
|
-
function weekdayPhrase(
|
|
2040
|
-
const segments = orderWeekdaysForDisplay(segmentsOf(
|
|
2127
|
+
function weekdayPhrase(schedule, recurring, opts) {
|
|
2128
|
+
const segments = orderWeekdaysForDisplay(segmentsOf(schedule, "weekday"));
|
|
2041
2129
|
const hasRange = segments.some(function range(segment) {
|
|
2042
2130
|
return segment.kind === "range";
|
|
2043
2131
|
});
|
|
@@ -2065,8 +2153,8 @@ function renderSegments(segments, word, opts) {
|
|
|
2065
2153
|
});
|
|
2066
2154
|
return joinList(pieces, opts);
|
|
2067
2155
|
}
|
|
2068
|
-
function applyYear(description,
|
|
2069
|
-
const yearField =
|
|
2156
|
+
function applyYear(description, schedule, opts) {
|
|
2157
|
+
const yearField = schedule.pattern.year;
|
|
2070
2158
|
if (yearField === "*") {
|
|
2071
2159
|
return description;
|
|
2072
2160
|
}
|
|
@@ -2074,7 +2162,7 @@ function applyYear(description, ir, opts) {
|
|
|
2074
2162
|
return description + ", " + stepYears(yearField, opts);
|
|
2075
2163
|
}
|
|
2076
2164
|
const label = yearLabel(yearField, opts);
|
|
2077
|
-
if (yearField.indexOf("-") === -1 && yearField.indexOf(",") === -1 &&
|
|
2165
|
+
if (yearField.indexOf("-") === -1 && yearField.indexOf(",") === -1 && schedule.pattern.date !== "*" && description.indexOf(" at ") !== -1) {
|
|
2078
2166
|
const yearGlue = opts.style.dayFirst ? " " : ", ";
|
|
2079
2167
|
return description.replace(" at ", yearGlue + label + " at ");
|
|
2080
2168
|
}
|
|
@@ -2197,9 +2285,9 @@ function interpretCronPattern(cronPattern, lang, opts) {
|
|
|
2197
2285
|
if (typeof cronPattern === "string" && cronPattern.trim().toLowerCase() === "@reboot") {
|
|
2198
2286
|
return lang.reboot;
|
|
2199
2287
|
}
|
|
2200
|
-
const
|
|
2201
|
-
const plan = lang.plan ? lang.plan(
|
|
2202
|
-
return lang.describe({ ...
|
|
2288
|
+
const schedule = analyze(prepare(cronPattern, opts));
|
|
2289
|
+
const plan = lang.plan ? lang.plan(schedule, schedule.plan) : schedule.plan;
|
|
2290
|
+
return lang.describe({ ...schedule, plan }, opts);
|
|
2203
2291
|
}
|
|
2204
2292
|
var cronli5_default = cronli5;
|
|
2205
2293
|
export {
|