cronli5 0.2.1 → 0.3.4
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 +109 -0
- package/README.md +4 -4
- 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 +320 -240
- package/dist/lang/zh.js +320 -240
- package/package.json +6 -6
- 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 +386 -245
- 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.cjs
CHANGED
|
@@ -95,81 +95,9 @@ function isNonNegativeInteger(value) {
|
|
|
95
95
|
const digits = /^\d+$/;
|
|
96
96
|
return digits.test(value);
|
|
97
97
|
}
|
|
98
|
-
function arithmeticStep(values) {
|
|
99
|
-
if (values.length < 5) {
|
|
100
|
-
return null;
|
|
101
|
-
}
|
|
102
|
-
const interval = values[1] - values[0];
|
|
103
|
-
if (interval < 2) {
|
|
104
|
-
return null;
|
|
105
|
-
}
|
|
106
|
-
for (let i = 2; i < values.length; i += 1) {
|
|
107
|
-
if (values[i] - values[i - 1] !== interval) {
|
|
108
|
-
return null;
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
return { start: values[0], interval, last: values[values.length - 1] };
|
|
112
|
-
}
|
|
113
|
-
function weekdayDisplayKey(value) {
|
|
114
|
-
return value === 0 ? 7 : value;
|
|
115
|
-
}
|
|
116
|
-
function orderWeekdaysForDisplay(segments) {
|
|
117
|
-
const flattened = segments.flatMap(function flat(segment) {
|
|
118
|
-
return segment.kind === "step" ? segment.fires.map(function single(value) {
|
|
119
|
-
return { kind: "single", value: "" + value };
|
|
120
|
-
}) : [segment];
|
|
121
|
-
});
|
|
122
|
-
function key(segment) {
|
|
123
|
-
return segment.kind === "range" ? weekdayDisplayKey(+segment.bounds[0]) : weekdayDisplayKey(+segment.value);
|
|
124
|
-
}
|
|
125
|
-
return flattened.map(function index(segment, position) {
|
|
126
|
-
return [segment, position];
|
|
127
|
-
}).sort(function byDisplayKey(a, b) {
|
|
128
|
-
return key(a[0]) - key(b[0]) || a[1] - b[1];
|
|
129
|
-
}).map(function unwrap(pair) {
|
|
130
|
-
return pair[0];
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
98
|
function toFieldNumber(token, numberMap) {
|
|
134
99
|
return isNonNegativeInteger(token) ? +token : numberMap[token.toUpperCase()];
|
|
135
100
|
}
|
|
136
|
-
function segmentsOf(ir, field) {
|
|
137
|
-
return ir.analyses.segments[field] ?? [];
|
|
138
|
-
}
|
|
139
|
-
function stepSegment(ir, field) {
|
|
140
|
-
return segmentsOf(ir, field)[0];
|
|
141
|
-
}
|
|
142
|
-
function singleValues(segments) {
|
|
143
|
-
const values = [];
|
|
144
|
-
for (const segment of segments) {
|
|
145
|
-
if (segment.kind !== "single") {
|
|
146
|
-
return null;
|
|
147
|
-
}
|
|
148
|
-
values.push(+segment.value);
|
|
149
|
-
}
|
|
150
|
-
return values;
|
|
151
|
-
}
|
|
152
|
-
function offsetCleanStride(stride) {
|
|
153
|
-
return stride.start < stride.interval && 24 % stride.interval === 0;
|
|
154
|
-
}
|
|
155
|
-
function hourListStride(values) {
|
|
156
|
-
if (values.length < 2) {
|
|
157
|
-
return null;
|
|
158
|
-
}
|
|
159
|
-
const interval = values[1] - values[0];
|
|
160
|
-
if (interval < 2) {
|
|
161
|
-
return null;
|
|
162
|
-
}
|
|
163
|
-
for (let i = 2; i < values.length; i += 1) {
|
|
164
|
-
if (values[i] - values[i - 1] !== interval) {
|
|
165
|
-
return null;
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
if (values[0] !== 0 && values.length < 5) {
|
|
169
|
-
return null;
|
|
170
|
-
}
|
|
171
|
-
return { interval, last: values[values.length - 1], start: values[0] };
|
|
172
|
-
}
|
|
173
101
|
|
|
174
102
|
// src/core/validate.ts
|
|
175
103
|
function validateCronPattern(cronPattern) {
|
|
@@ -299,7 +227,7 @@ function normalizeField(value, field, spec) {
|
|
|
299
227
|
const cycle = timeFieldCycle[field];
|
|
300
228
|
const segments = stringValue.split(",").map(function canonical(segment) {
|
|
301
229
|
return canonicalizeTokens(collapseFullSpanRange(
|
|
302
|
-
|
|
230
|
+
enumerateIfNonUniform(
|
|
303
231
|
collapseFullSpanStep(
|
|
304
232
|
collapseDegenerateRange(
|
|
305
233
|
collapseOnceStep(collapseUnitStep(segment, spec), spec),
|
|
@@ -363,7 +291,7 @@ function collapseOnceStep(segment, spec) {
|
|
|
363
291
|
}
|
|
364
292
|
return start === "*" ? "" + spec.min : start;
|
|
365
293
|
}
|
|
366
|
-
function
|
|
294
|
+
function enumerateIfNonUniform(segment, spec, cycle) {
|
|
367
295
|
const parts = segment.split("/");
|
|
368
296
|
if (typeof cycle !== "number" || parts.length !== 2 || includes(parts[0], "-")) {
|
|
369
297
|
return segment;
|
|
@@ -502,6 +430,93 @@ function expandMacro(cronString) {
|
|
|
502
430
|
throw new Error("`cronli5` does not recognize the macro `" + trimmed + "`.");
|
|
503
431
|
}
|
|
504
432
|
|
|
433
|
+
// src/core/weekday.ts
|
|
434
|
+
function weekdayDisplayKey(value) {
|
|
435
|
+
return value === 0 ? 7 : value;
|
|
436
|
+
}
|
|
437
|
+
function orderWeekdaysForDisplay(segments) {
|
|
438
|
+
const flattened = segments.flatMap(function flat(segment) {
|
|
439
|
+
return segment.kind === "step" ? segment.fires.map(function single(value) {
|
|
440
|
+
return { kind: "single", value: "" + value };
|
|
441
|
+
}) : [segment];
|
|
442
|
+
});
|
|
443
|
+
function key(segment) {
|
|
444
|
+
return segment.kind === "range" ? weekdayDisplayKey(+segment.bounds[0]) : weekdayDisplayKey(+segment.value);
|
|
445
|
+
}
|
|
446
|
+
return flattened.map(function index(segment, position) {
|
|
447
|
+
return [segment, position];
|
|
448
|
+
}).sort(function byDisplayKey(a, b) {
|
|
449
|
+
return key(a[0]) - key(b[0]) || a[1] - b[1];
|
|
450
|
+
}).map(function unwrap(pair) {
|
|
451
|
+
return pair[0];
|
|
452
|
+
});
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
// src/core/cadence.ts
|
|
456
|
+
function arithmeticStep(values) {
|
|
457
|
+
if (values.length < 5) {
|
|
458
|
+
return null;
|
|
459
|
+
}
|
|
460
|
+
const interval = values[1] - values[0];
|
|
461
|
+
if (interval < 2) {
|
|
462
|
+
return null;
|
|
463
|
+
}
|
|
464
|
+
for (let i = 2; i < values.length; i += 1) {
|
|
465
|
+
if (values[i] - values[i - 1] !== interval) {
|
|
466
|
+
return null;
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
return { start: values[0], interval, last: values[values.length - 1] };
|
|
470
|
+
}
|
|
471
|
+
function segmentsOf(schedule, field) {
|
|
472
|
+
return schedule.analyses.segments[field] ?? [];
|
|
473
|
+
}
|
|
474
|
+
function stepSegment(schedule, field) {
|
|
475
|
+
return segmentsOf(schedule, field)[0];
|
|
476
|
+
}
|
|
477
|
+
function singleValues(segments) {
|
|
478
|
+
const values = [];
|
|
479
|
+
for (const segment of segments) {
|
|
480
|
+
if (segment.kind !== "single") {
|
|
481
|
+
return null;
|
|
482
|
+
}
|
|
483
|
+
values.push(+segment.value);
|
|
484
|
+
}
|
|
485
|
+
return values;
|
|
486
|
+
}
|
|
487
|
+
function offsetCleanStride(stride) {
|
|
488
|
+
return stride.start < stride.interval && 24 % stride.interval === 0;
|
|
489
|
+
}
|
|
490
|
+
function renderStride(spec, parts) {
|
|
491
|
+
const { start, interval, cycle } = spec;
|
|
492
|
+
const tiles = cycle % interval === 0;
|
|
493
|
+
if (start === 0 && tiles) {
|
|
494
|
+
return parts.bare();
|
|
495
|
+
}
|
|
496
|
+
if (start < interval && tiles) {
|
|
497
|
+
return parts.offset();
|
|
498
|
+
}
|
|
499
|
+
return parts.bounded();
|
|
500
|
+
}
|
|
501
|
+
function hourListStride(values) {
|
|
502
|
+
if (values.length < 2) {
|
|
503
|
+
return null;
|
|
504
|
+
}
|
|
505
|
+
const interval = values[1] - values[0];
|
|
506
|
+
if (interval < 2) {
|
|
507
|
+
return null;
|
|
508
|
+
}
|
|
509
|
+
for (let i = 2; i < values.length; i += 1) {
|
|
510
|
+
if (values[i] - values[i - 1] !== interval) {
|
|
511
|
+
return null;
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
if (values[0] !== 0 && values.length < 5) {
|
|
515
|
+
return null;
|
|
516
|
+
}
|
|
517
|
+
return { interval, last: values[values.length - 1], start: values[0] };
|
|
518
|
+
}
|
|
519
|
+
|
|
505
520
|
// src/core/shapes.ts
|
|
506
521
|
function isSingleValue(field) {
|
|
507
522
|
return field !== "*" && !includes(field, ",") && !includes(field, "-") && !includes(field, "/");
|
|
@@ -656,11 +671,11 @@ function analyze(pattern) {
|
|
|
656
671
|
minuteSpan: minuteSpan(pattern.minute),
|
|
657
672
|
segments
|
|
658
673
|
};
|
|
659
|
-
const
|
|
660
|
-
return { ...
|
|
674
|
+
const facts = { analyses, pattern, shapes };
|
|
675
|
+
return { ...facts, plan: selectPlan(facts) };
|
|
661
676
|
}
|
|
662
|
-
function selectPlan(
|
|
663
|
-
const { analyses, pattern, shapes } =
|
|
677
|
+
function selectPlan(facts) {
|
|
678
|
+
const { analyses, pattern, shapes } = facts;
|
|
664
679
|
if (pattern.second !== "0") {
|
|
665
680
|
const seconds = planSeconds(pattern, shapes, analyses);
|
|
666
681
|
if (seconds) {
|
|
@@ -1004,72 +1019,134 @@ function normalizeOptions(options) {
|
|
|
1004
1019
|
years: !!options.years
|
|
1005
1020
|
};
|
|
1006
1021
|
}
|
|
1007
|
-
function describe(
|
|
1008
|
-
const
|
|
1009
|
-
|
|
1010
|
-
|
|
1022
|
+
function describe(schedule, opts) {
|
|
1023
|
+
const dense = denseCadence(schedule, opts);
|
|
1024
|
+
if (dense !== null) {
|
|
1025
|
+
return applyYear(dense, schedule, opts);
|
|
1026
|
+
}
|
|
1027
|
+
const body = confinement(schedule, opts) ?? render(schedule, schedule.plan, opts);
|
|
1028
|
+
const lead = isDayUnion(schedule, opts) ? dayUnionMonthLead(schedule, opts) : "";
|
|
1029
|
+
return applyYear(lead + body, schedule, opts);
|
|
1011
1030
|
}
|
|
1012
|
-
function render(
|
|
1031
|
+
function render(schedule, plan, opts) {
|
|
1013
1032
|
const renderer = renderers[plan.kind];
|
|
1014
|
-
return renderer(
|
|
1033
|
+
return renderer(schedule, plan, opts);
|
|
1015
1034
|
}
|
|
1016
|
-
function
|
|
1017
|
-
return "
|
|
1035
|
+
function isCadenceShape(shape) {
|
|
1036
|
+
return shape === "step" || shape === "range" || shape === "list";
|
|
1018
1037
|
}
|
|
1019
|
-
function
|
|
1020
|
-
|
|
1038
|
+
function isDenseCadence(schedule, opts) {
|
|
1039
|
+
if (!opts.style.untilWindow || opts.short || schedule.plan.kind !== "composeSeconds" || schedule.plan.rest.kind === "clockTimes" || isDayUnion(schedule, opts)) {
|
|
1040
|
+
return false;
|
|
1041
|
+
}
|
|
1042
|
+
const { shapes } = schedule;
|
|
1043
|
+
return isCadenceShape(shapes.second) && isCadenceShape(shapes.minute) && isCadenceShape(shapes.hour);
|
|
1021
1044
|
}
|
|
1022
|
-
function
|
|
1023
|
-
const
|
|
1024
|
-
|
|
1045
|
+
function denseHourFragment(schedule, opts) {
|
|
1046
|
+
const stride = hourStride(schedule);
|
|
1047
|
+
if (stride) {
|
|
1048
|
+
return hourStrideCadence(stride, opts);
|
|
1049
|
+
}
|
|
1050
|
+
if (schedule.shapes.hour === "range") {
|
|
1051
|
+
const segment = segmentsOf(schedule, "hour").find(function range(part) {
|
|
1052
|
+
return part.kind === "range";
|
|
1053
|
+
});
|
|
1054
|
+
return rangeWindow({
|
|
1055
|
+
continuous: false,
|
|
1056
|
+
from: +segment.bounds[0],
|
|
1057
|
+
throughMinute: 0,
|
|
1058
|
+
to: +segment.bounds[1]
|
|
1059
|
+
}, opts);
|
|
1060
|
+
}
|
|
1061
|
+
return "during the " + hourSegmentTimes(schedule, { minute: 0, second: null }, false, opts) + " hours";
|
|
1025
1062
|
}
|
|
1026
|
-
function
|
|
1027
|
-
|
|
1063
|
+
function denseMinuteFragment(schedule, opts) {
|
|
1064
|
+
if (schedule.shapes.minute === "step") {
|
|
1065
|
+
return stepCycle60(stepSegment(schedule, "minute"), "minute", "hour", opts);
|
|
1066
|
+
}
|
|
1067
|
+
if (schedule.shapes.minute === "range") {
|
|
1068
|
+
return minuteRangeLead(schedule.pattern.minute, opts);
|
|
1069
|
+
}
|
|
1070
|
+
return strideFromSegments(
|
|
1071
|
+
segmentsOf(schedule, "minute"),
|
|
1072
|
+
"minute",
|
|
1073
|
+
"hour",
|
|
1074
|
+
opts
|
|
1075
|
+
) ?? listPastThe(
|
|
1076
|
+
segmentWords(segmentsOf(schedule, "minute"), opts),
|
|
1077
|
+
"minute",
|
|
1078
|
+
"hour",
|
|
1079
|
+
opts
|
|
1080
|
+
);
|
|
1081
|
+
}
|
|
1082
|
+
function denseCadence(schedule, opts) {
|
|
1083
|
+
if (!isDenseCadence(schedule, opts)) {
|
|
1084
|
+
return null;
|
|
1085
|
+
}
|
|
1086
|
+
const hour = denseHourFragment(schedule, opts);
|
|
1087
|
+
const minute = denseMinuteFragment(schedule, opts);
|
|
1088
|
+
const second = secondsClause(schedule, "minute", opts);
|
|
1089
|
+
const nested = hour + ", " + minute + ", and within each of those minutes, " + second;
|
|
1090
|
+
const anchor = trailingQualifier(schedule, opts).trim();
|
|
1091
|
+
return anchor ? anchor + ", " + nested : nested;
|
|
1092
|
+
}
|
|
1093
|
+
function renderEverySecond(schedule, plan, opts) {
|
|
1094
|
+
return "every second" + trailingQualifier(schedule, opts);
|
|
1095
|
+
}
|
|
1096
|
+
function renderStandaloneSeconds(schedule, plan, opts) {
|
|
1097
|
+
return secondsLeadClause(schedule, opts) + trailingQualifier(schedule, opts);
|
|
1098
|
+
}
|
|
1099
|
+
function renderSecondPastMinute(schedule, plan, opts) {
|
|
1100
|
+
const secondField = schedule.pattern.second;
|
|
1101
|
+
return getNumber(secondField, opts) + " " + pluralize(secondField, "second") + " past the minute, every minute" + trailingQualifier(schedule, opts);
|
|
1102
|
+
}
|
|
1103
|
+
function renderSecondsWithinMinute(schedule, plan, opts) {
|
|
1104
|
+
const minuteField = schedule.pattern.minute;
|
|
1028
1105
|
const minuteWord = getNumber(minuteField, opts);
|
|
1029
1106
|
const minuteUnit = pluralize(minuteField, "minute");
|
|
1030
1107
|
if (plan.singleSecond) {
|
|
1031
|
-
const secondField =
|
|
1032
|
-
return minuteWord + " " + minuteUnit + " and " + getNumber(secondField, opts) + " " + pluralize(secondField, "second") + " past the hour, every hour" + trailingQualifier(
|
|
1108
|
+
const secondField = schedule.pattern.second;
|
|
1109
|
+
return minuteWord + " " + minuteUnit + " and " + getNumber(secondField, opts) + " " + pluralize(secondField, "second") + " past the hour, every hour" + trailingQualifier(schedule, opts);
|
|
1033
1110
|
}
|
|
1034
|
-
return secondsLeadClause(
|
|
1111
|
+
return secondsLeadClause(schedule, opts) + ", " + minuteWord + " " + minuteUnit + " past the hour, every hour" + trailingQualifier(schedule, opts);
|
|
1035
1112
|
}
|
|
1036
|
-
function composeHourCadence(
|
|
1113
|
+
function composeHourCadence(schedule, plan, opts) {
|
|
1037
1114
|
const clockRest = plan.rest.kind === "clockTimes" || plan.rest.kind === "compactClockTimes";
|
|
1038
|
-
if (!clockRest ||
|
|
1115
|
+
if (!clockRest || schedule.shapes.minute !== "single") {
|
|
1039
1116
|
return null;
|
|
1040
1117
|
}
|
|
1041
|
-
const minute = +
|
|
1042
|
-
return hourCadence(
|
|
1118
|
+
const minute = +schedule.pattern.minute;
|
|
1119
|
+
return hourCadence(schedule, minute, opts) ?? hourRangeCadence(schedule, minute, opts);
|
|
1043
1120
|
}
|
|
1044
|
-
function clockTimesConfinement(
|
|
1045
|
-
if (+rest.times[0].minute === 0 &&
|
|
1046
|
-
return secondsLeadClause(
|
|
1121
|
+
function clockTimesConfinement(schedule, rest, opts) {
|
|
1122
|
+
if (+rest.times[0].minute === 0 && schedule.shapes.minute === "single") {
|
|
1123
|
+
return secondsLeadClause(schedule, opts) + " for one minute at " + durationHours(schedule, rest, opts);
|
|
1047
1124
|
}
|
|
1048
|
-
return secondsLeadClause(
|
|
1125
|
+
return secondsLeadClause(schedule, opts) + " of " + clockTimesOf(schedule, rest, opts);
|
|
1049
1126
|
}
|
|
1050
|
-
function renderComposeSeconds(
|
|
1051
|
-
const cadence = composeHourCadence(
|
|
1127
|
+
function renderComposeSeconds(schedule, plan, opts) {
|
|
1128
|
+
const cadence = composeHourCadence(schedule, plan, opts);
|
|
1052
1129
|
if (cadence !== null) {
|
|
1053
1130
|
return cadence;
|
|
1054
1131
|
}
|
|
1055
|
-
if (plan.rest.kind === "clockTimes" && (
|
|
1056
|
-
return clockTimesConfinement(
|
|
1132
|
+
if (plan.rest.kind === "clockTimes" && (schedule.shapes.second === "wildcard" || schedule.shapes.second === "step")) {
|
|
1133
|
+
return clockTimesConfinement(schedule, plan.rest, opts);
|
|
1057
1134
|
}
|
|
1058
|
-
if (
|
|
1059
|
-
return "every second of every other minute" + trailingQualifier(
|
|
1135
|
+
if (schedule.shapes.second === "wildcard" && plan.rest.kind === "minuteFrequency" && plan.rest.hours.kind === "none" && schedule.pattern.minute === "*/2") {
|
|
1136
|
+
return "every second of every other minute" + trailingQualifier(schedule, opts);
|
|
1060
1137
|
}
|
|
1061
|
-
const restOwnsLead = plan.rest.kind === "compactClockTimes" &&
|
|
1062
|
-
const lead = restOwnsLead ? "" : secondsLeadClause(
|
|
1063
|
-
return lead + render(
|
|
1138
|
+
const restOwnsLead = plan.rest.kind === "compactClockTimes" && schedule.analyses.clockSecond;
|
|
1139
|
+
const lead = restOwnsLead ? "" : secondsLeadClause(schedule, opts) + ", ";
|
|
1140
|
+
return lead + render(schedule, plan.rest, opts);
|
|
1064
1141
|
}
|
|
1065
|
-
function durationHours(
|
|
1142
|
+
function durationHours(schedule, plan, opts) {
|
|
1066
1143
|
const hours = plan.times.map(function clock(time) {
|
|
1067
1144
|
return getTime({ hour: time.hour, minute: 0 }, opts);
|
|
1068
1145
|
});
|
|
1069
|
-
const trail = dayQualifier(
|
|
1146
|
+
const trail = dayQualifier(schedule, leadingWords, opts);
|
|
1070
1147
|
return joinList(hours, opts) + (trail && ", " + trail);
|
|
1071
1148
|
}
|
|
1072
|
-
function clockTimesOf(
|
|
1149
|
+
function clockTimesOf(schedule, plan, opts) {
|
|
1073
1150
|
const times = plan.times.map(function clock(time) {
|
|
1074
1151
|
return getTime({
|
|
1075
1152
|
hour: time.hour,
|
|
@@ -1078,21 +1155,21 @@ function clockTimesOf(ir, plan, opts) {
|
|
|
1078
1155
|
explicit: true
|
|
1079
1156
|
}, opts);
|
|
1080
1157
|
});
|
|
1081
|
-
const trail = dayQualifier(
|
|
1158
|
+
const trail = dayQualifier(schedule, leadingWords, opts);
|
|
1082
1159
|
return joinList(times, opts) + (trail && ", " + trail);
|
|
1083
1160
|
}
|
|
1084
|
-
function secondsLeadClause(
|
|
1085
|
-
return secondsClause(
|
|
1161
|
+
function secondsLeadClause(schedule, opts) {
|
|
1162
|
+
return secondsClause(schedule, "minute", opts);
|
|
1086
1163
|
}
|
|
1087
|
-
function secondsClause(
|
|
1088
|
-
const secondField =
|
|
1089
|
-
const shape =
|
|
1164
|
+
function secondsClause(schedule, anchor, opts) {
|
|
1165
|
+
const secondField = schedule.pattern.second;
|
|
1166
|
+
const shape = schedule.shapes.second;
|
|
1090
1167
|
if (secondField === "*") {
|
|
1091
1168
|
return "every second";
|
|
1092
1169
|
}
|
|
1093
1170
|
if (shape === "step") {
|
|
1094
1171
|
return stepCycle60(
|
|
1095
|
-
stepSegment(
|
|
1172
|
+
stepSegment(schedule, "second"),
|
|
1096
1173
|
"second",
|
|
1097
1174
|
anchor,
|
|
1098
1175
|
opts
|
|
@@ -1107,44 +1184,44 @@ function secondsClause(ir, anchor, opts) {
|
|
|
1107
1184
|
return "at " + getNumber(secondField, opts) + " " + pluralize(secondField, "second") + " past the " + anchor;
|
|
1108
1185
|
}
|
|
1109
1186
|
return strideFromSegments(
|
|
1110
|
-
segmentsOf(
|
|
1187
|
+
segmentsOf(schedule, "second"),
|
|
1111
1188
|
"second",
|
|
1112
1189
|
anchor,
|
|
1113
1190
|
opts
|
|
1114
1191
|
) ?? listPastThe(
|
|
1115
|
-
segmentWords(segmentsOf(
|
|
1192
|
+
segmentWords(segmentsOf(schedule, "second"), opts),
|
|
1116
1193
|
"second",
|
|
1117
1194
|
anchor,
|
|
1118
1195
|
opts
|
|
1119
1196
|
);
|
|
1120
1197
|
}
|
|
1121
|
-
function renderEveryMinute(
|
|
1122
|
-
return "every minute" + trailingQualifier(
|
|
1198
|
+
function renderEveryMinute(schedule, plan, opts) {
|
|
1199
|
+
return "every minute" + trailingQualifier(schedule, opts);
|
|
1123
1200
|
}
|
|
1124
|
-
function renderSingleMinute(
|
|
1125
|
-
const minuteField =
|
|
1126
|
-
return getNumber(minuteField, opts) + " " + pluralize(minuteField, "minute") + " past the hour, every hour" + trailingQualifier(
|
|
1201
|
+
function renderSingleMinute(schedule, plan, opts) {
|
|
1202
|
+
const minuteField = schedule.pattern.minute;
|
|
1203
|
+
return getNumber(minuteField, opts) + " " + pluralize(minuteField, "minute") + " past the hour, every hour" + trailingQualifier(schedule, opts);
|
|
1127
1204
|
}
|
|
1128
|
-
function renderRangeOfMinutes(
|
|
1129
|
-
return minuteRangeLead(
|
|
1205
|
+
function renderRangeOfMinutes(schedule, plan, opts) {
|
|
1206
|
+
return minuteRangeLead(schedule.pattern.minute, opts) + trailingQualifier(schedule, opts);
|
|
1130
1207
|
}
|
|
1131
|
-
function renderMultipleMinutes(
|
|
1132
|
-
const stride = strideFromSegments(segmentsOf(
|
|
1208
|
+
function renderMultipleMinutes(schedule, plan, opts) {
|
|
1209
|
+
const stride = strideFromSegments(segmentsOf(schedule, "minute"), "minute", "hour", opts);
|
|
1133
1210
|
return (stride ?? listPastThe(segmentWords(
|
|
1134
|
-
segmentsOf(
|
|
1211
|
+
segmentsOf(schedule, "minute"),
|
|
1135
1212
|
opts
|
|
1136
|
-
), "minute", "hour", opts)) + trailingQualifier(
|
|
1213
|
+
), "minute", "hour", opts)) + trailingQualifier(schedule, opts);
|
|
1137
1214
|
}
|
|
1138
|
-
function renderMinuteFrequency(
|
|
1215
|
+
function renderMinuteFrequency(schedule, plan, opts) {
|
|
1139
1216
|
let phrase = stepCycle60(
|
|
1140
|
-
stepSegment(
|
|
1217
|
+
stepSegment(schedule, "minute"),
|
|
1141
1218
|
"minute",
|
|
1142
1219
|
"hour",
|
|
1143
1220
|
opts
|
|
1144
1221
|
);
|
|
1145
1222
|
if (plan.hours.kind === "during") {
|
|
1146
|
-
const cadence = unevenHourCadence(
|
|
1147
|
-
phrase += cadence ? ", " + cadence : " during the " + hourTimesFromPlan(
|
|
1223
|
+
const cadence = unevenHourCadence(schedule, opts);
|
|
1224
|
+
phrase += cadence ? ", " + cadence : " during the " + hourTimesFromPlan(schedule, plan.hours.times, false, opts) + " hours";
|
|
1148
1225
|
} else if (plan.hours.kind === "window") {
|
|
1149
1226
|
phrase += " " + rangeWindow({
|
|
1150
1227
|
continuous: false,
|
|
@@ -1153,45 +1230,50 @@ function renderMinuteFrequency(ir, plan, opts) {
|
|
|
1153
1230
|
to: plan.hours.to
|
|
1154
1231
|
}, opts);
|
|
1155
1232
|
} else if (plan.hours.kind === "step") {
|
|
1156
|
-
phrase += " " + everyNthHour(stepSegment(
|
|
1233
|
+
phrase += " " + everyNthHour(stepSegment(schedule, "hour"), opts);
|
|
1157
1234
|
}
|
|
1158
|
-
return phrase + trailingQualifier(
|
|
1235
|
+
return phrase + trailingQualifier(schedule, opts);
|
|
1159
1236
|
}
|
|
1160
|
-
function renderMinuteSpanInHour(
|
|
1161
|
-
if (
|
|
1162
|
-
return "every minute of the " + getTime({ hour: plan.hour, minute: 0 }, opts) + " hour" + trailingQualifier(
|
|
1237
|
+
function renderMinuteSpanInHour(schedule, plan, opts) {
|
|
1238
|
+
if (schedule.pattern.minute === "*") {
|
|
1239
|
+
return "every minute of the " + getTime({ hour: plan.hour, minute: 0 }, opts) + " hour" + trailingQualifier(schedule, opts);
|
|
1163
1240
|
}
|
|
1164
|
-
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(
|
|
1241
|
+
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);
|
|
1165
1242
|
}
|
|
1166
|
-
function renderMinutesAcrossHours(
|
|
1167
|
-
const cadence = unevenHourCadence(
|
|
1243
|
+
function renderMinutesAcrossHours(schedule, plan, opts) {
|
|
1244
|
+
const cadence = unevenHourCadence(schedule, opts);
|
|
1168
1245
|
if (plan.form === "wildcard") {
|
|
1169
1246
|
if (cadence !== null) {
|
|
1170
|
-
return "every minute, " + cadence + trailingQualifier(
|
|
1247
|
+
return "every minute, " + cadence + trailingQualifier(schedule, opts);
|
|
1171
1248
|
}
|
|
1172
|
-
return "every minute during the " + hourTimesFromPlan(
|
|
1249
|
+
return "every minute during the " + hourTimesFromPlan(schedule, plan.times, false, opts) + " hours" + trailingQualifier(schedule, opts);
|
|
1173
1250
|
}
|
|
1174
1251
|
if (plan.form === "range") {
|
|
1175
|
-
const lead2 = minuteRangeLead(
|
|
1252
|
+
const lead2 = minuteRangeLead(schedule.pattern.minute, opts);
|
|
1176
1253
|
if (cadence !== null) {
|
|
1177
|
-
return lead2 + ", " + cadence + trailingQualifier(
|
|
1254
|
+
return lead2 + ", " + cadence + trailingQualifier(schedule, opts);
|
|
1178
1255
|
}
|
|
1179
1256
|
if (singleHourFire(plan.times)) {
|
|
1180
|
-
return lead2 + ", at " + hourTimesFromPlan(
|
|
1257
|
+
return lead2 + ", at " + hourTimesFromPlan(schedule, plan.times, true, opts) + trailingQualifier(schedule, opts);
|
|
1181
1258
|
}
|
|
1182
|
-
return lead2 + " during the " + hourTimesFromPlan(
|
|
1259
|
+
return lead2 + " during the " + hourTimesFromPlan(schedule, plan.times, false, opts) + " hours" + trailingQualifier(schedule, opts);
|
|
1183
1260
|
}
|
|
1184
|
-
const lead = strideFromSegments(
|
|
1185
|
-
|
|
1261
|
+
const lead = strideFromSegments(
|
|
1262
|
+
segmentsOf(schedule, "minute"),
|
|
1263
|
+
"minute",
|
|
1264
|
+
"hour",
|
|
1265
|
+
opts
|
|
1266
|
+
) ?? listPastThe(
|
|
1267
|
+
segmentWords(segmentsOf(schedule, "minute"), opts),
|
|
1186
1268
|
"minute",
|
|
1187
1269
|
"hour",
|
|
1188
1270
|
opts
|
|
1189
1271
|
);
|
|
1190
1272
|
if (cadence !== null) {
|
|
1191
|
-
return lead + ", " + cadence + trailingQualifier(
|
|
1273
|
+
return lead + ", " + cadence + trailingQualifier(schedule, opts);
|
|
1192
1274
|
}
|
|
1193
|
-
const times = hourTimesFromPlan(
|
|
1194
|
-
return lead + ", at " + times + trailingQualifier(
|
|
1275
|
+
const times = hourTimesFromPlan(schedule, plan.times, true, opts);
|
|
1276
|
+
return lead + ", at " + times + trailingQualifier(schedule, opts);
|
|
1195
1277
|
}
|
|
1196
1278
|
var stepOrdinals = {
|
|
1197
1279
|
2: "other",
|
|
@@ -1206,60 +1288,65 @@ function everyNthHour(segment, opts) {
|
|
|
1206
1288
|
const start = segment.startToken === "*" ? 0 : +segment.startToken;
|
|
1207
1289
|
return start === 0 ? base : base + " starting at " + getTime({ hour: start, minute: 0 }, opts);
|
|
1208
1290
|
}
|
|
1209
|
-
function renderMinuteSpanAcrossHourStep(
|
|
1210
|
-
const segment = stepSegment(
|
|
1291
|
+
function renderMinuteSpanAcrossHourStep(schedule, plan, opts) {
|
|
1292
|
+
const segment = stepSegment(schedule, "hour");
|
|
1211
1293
|
if (plan.form === "wildcard") {
|
|
1212
|
-
return "every minute " + everyNthHour(segment, opts) + trailingQualifier(
|
|
1294
|
+
return "every minute " + everyNthHour(segment, opts) + trailingQualifier(schedule, opts);
|
|
1213
1295
|
}
|
|
1214
|
-
const lead = plan.form === "list" ? strideFromSegments(
|
|
1215
|
-
|
|
1296
|
+
const lead = plan.form === "list" ? strideFromSegments(
|
|
1297
|
+
segmentsOf(schedule, "minute"),
|
|
1298
|
+
"minute",
|
|
1299
|
+
"hour",
|
|
1300
|
+
opts
|
|
1301
|
+
) ?? listPastThe(
|
|
1302
|
+
segmentWords(segmentsOf(schedule, "minute"), opts),
|
|
1216
1303
|
"minute",
|
|
1217
1304
|
"hour",
|
|
1218
1305
|
opts
|
|
1219
|
-
) : minuteRangeLead(
|
|
1220
|
-
const cadence = unevenHourCadence(
|
|
1221
|
-
return lead + ", " + (cadence ?? stepHours(segment, opts)) + trailingQualifier(
|
|
1306
|
+
) : minuteRangeLead(schedule.pattern.minute, opts);
|
|
1307
|
+
const cadence = unevenHourCadence(schedule, opts);
|
|
1308
|
+
return lead + ", " + (cadence ?? stepHours(segment, opts)) + trailingQualifier(schedule, opts);
|
|
1222
1309
|
}
|
|
1223
1310
|
function minuteRangeLead(minuteField, opts) {
|
|
1224
1311
|
const bounds = minuteField.split("-");
|
|
1225
1312
|
const num = seriesNumber();
|
|
1226
1313
|
return "every minute from " + num(bounds[0]) + through(opts) + num(bounds[1]) + " past the hour";
|
|
1227
1314
|
}
|
|
1228
|
-
function renderEveryHour(
|
|
1229
|
-
return "every hour" + trailingQualifier(
|
|
1315
|
+
function renderEveryHour(schedule, plan, opts) {
|
|
1316
|
+
return "every hour" + trailingQualifier(schedule, opts);
|
|
1230
1317
|
}
|
|
1231
|
-
function renderHourRange(
|
|
1318
|
+
function renderHourRange(schedule, plan, opts) {
|
|
1232
1319
|
const window = hourWindow(boundedWindow(plan), opts);
|
|
1233
1320
|
if (plan.minuteForm === "wildcard") {
|
|
1234
|
-
return "every minute " + window + trailingQualifier(
|
|
1321
|
+
return "every minute " + window + trailingQualifier(schedule, opts);
|
|
1235
1322
|
}
|
|
1236
1323
|
if (plan.minuteForm === "range") {
|
|
1237
|
-
return minuteRangeLead(
|
|
1324
|
+
return minuteRangeLead(schedule.pattern.minute, opts) + ", " + window + trailingQualifier(schedule, opts);
|
|
1238
1325
|
}
|
|
1239
|
-
return rangeMinuteLead(
|
|
1326
|
+
return rangeMinuteLead(schedule, opts) + " " + window + trailingQualifier(schedule, opts);
|
|
1240
1327
|
}
|
|
1241
|
-
function rangeMinuteLead(
|
|
1242
|
-
if (
|
|
1328
|
+
function rangeMinuteLead(schedule, opts) {
|
|
1329
|
+
if (schedule.pattern.minute === "0") {
|
|
1243
1330
|
return "every hour";
|
|
1244
1331
|
}
|
|
1245
1332
|
return strideFromSegments(
|
|
1246
|
-
segmentsOf(
|
|
1333
|
+
segmentsOf(schedule, "minute"),
|
|
1247
1334
|
"minute",
|
|
1248
1335
|
"hour",
|
|
1249
1336
|
opts
|
|
1250
1337
|
) ?? listPastThe(
|
|
1251
|
-
segmentWords(segmentsOf(
|
|
1338
|
+
segmentWords(segmentsOf(schedule, "minute"), opts),
|
|
1252
1339
|
"minute",
|
|
1253
1340
|
"hour",
|
|
1254
1341
|
opts
|
|
1255
1342
|
);
|
|
1256
1343
|
}
|
|
1257
|
-
function renderHourStep(
|
|
1258
|
-
const cadence = unevenHourCadence(
|
|
1344
|
+
function renderHourStep(schedule, plan, opts) {
|
|
1345
|
+
const cadence = unevenHourCadence(schedule, opts);
|
|
1259
1346
|
if (cadence !== null) {
|
|
1260
|
-
return cadence + trailingQualifier(
|
|
1347
|
+
return cadence + trailingQualifier(schedule, opts);
|
|
1261
1348
|
}
|
|
1262
|
-
return stepHours(stepSegment(
|
|
1349
|
+
return stepHours(stepSegment(schedule, "hour"), opts) + trailingQualifier(schedule, opts);
|
|
1263
1350
|
}
|
|
1264
1351
|
function boundedWindow(plan) {
|
|
1265
1352
|
const continuous = plan.minuteForm === "wildcard";
|
|
@@ -1282,10 +1369,10 @@ function hourWindow(window, opts) {
|
|
|
1282
1369
|
to: window.to
|
|
1283
1370
|
}, opts);
|
|
1284
1371
|
}
|
|
1285
|
-
function renderClockTimes(
|
|
1286
|
-
if (
|
|
1287
|
-
const minute = +
|
|
1288
|
-
const cadence = hourCadence(
|
|
1372
|
+
function renderClockTimes(schedule, plan, opts) {
|
|
1373
|
+
if (schedule.shapes.minute === "single") {
|
|
1374
|
+
const minute = +schedule.pattern.minute;
|
|
1375
|
+
const cadence = hourCadence(schedule, minute, opts) ?? hourRangeCadence(schedule, minute, opts);
|
|
1289
1376
|
if (cadence !== null) {
|
|
1290
1377
|
return cadence;
|
|
1291
1378
|
}
|
|
@@ -1299,47 +1386,52 @@ function renderClockTimes(ir, plan, opts) {
|
|
|
1299
1386
|
plain
|
|
1300
1387
|
}, opts);
|
|
1301
1388
|
});
|
|
1302
|
-
return interpretDayQualifier(
|
|
1389
|
+
return interpretDayQualifier(schedule, opts) + "at " + joinList(times, opts) + dayUnionTrail(schedule, opts);
|
|
1303
1390
|
}
|
|
1304
|
-
function dayUnionTrail(
|
|
1305
|
-
return isDayUnion(
|
|
1391
|
+
function dayUnionTrail(schedule, opts) {
|
|
1392
|
+
return isDayUnion(schedule, opts) ? dayUnionCondition(schedule, opts) : "";
|
|
1306
1393
|
}
|
|
1307
|
-
function renderCompactClockTimes(
|
|
1394
|
+
function renderCompactClockTimes(schedule, plan, opts) {
|
|
1308
1395
|
if (plan.fold) {
|
|
1309
|
-
const cadence2 = hourCadence(
|
|
1396
|
+
const cadence2 = hourCadence(schedule, +plan.minute, opts) ?? hourRangeCadence(schedule, +plan.minute, opts);
|
|
1310
1397
|
if (cadence2 !== null) {
|
|
1311
1398
|
return cadence2;
|
|
1312
1399
|
}
|
|
1313
|
-
const hasRange = segmentsOf(
|
|
1400
|
+
const hasRange = segmentsOf(schedule, "hour").some(function range(segment) {
|
|
1314
1401
|
return segment.kind === "range";
|
|
1315
1402
|
});
|
|
1316
|
-
if (hasRange && !
|
|
1317
|
-
return foldedHourWindows(
|
|
1403
|
+
if (hasRange && !schedule.analyses.clockSecond) {
|
|
1404
|
+
return foldedHourWindows(schedule, plan, opts) + trailingQualifier(schedule, opts);
|
|
1318
1405
|
}
|
|
1319
|
-
const fold = { minute: plan.minute, second:
|
|
1320
|
-
return interpretDayQualifier(
|
|
1406
|
+
const fold = { minute: plan.minute, second: schedule.analyses.clockSecond };
|
|
1407
|
+
return interpretDayQualifier(schedule, opts) + "at " + hourSegmentTimes(schedule, fold, true, opts) + dayUnionTrail(schedule, opts);
|
|
1321
1408
|
}
|
|
1322
1409
|
const minuteLead = (
|
|
1323
1410
|
// The non-fold branch is a minute list, which has segments. An
|
|
1324
1411
|
// offset/uneven step enumerated to that list reads as a stride.
|
|
1325
|
-
strideFromSegments(
|
|
1326
|
-
|
|
1412
|
+
strideFromSegments(
|
|
1413
|
+
segmentsOf(schedule, "minute"),
|
|
1414
|
+
"minute",
|
|
1415
|
+
"hour",
|
|
1416
|
+
opts
|
|
1417
|
+
) ?? listPastThe(
|
|
1418
|
+
segmentWords(segmentsOf(schedule, "minute"), opts),
|
|
1327
1419
|
"minute",
|
|
1328
1420
|
"hour",
|
|
1329
1421
|
opts
|
|
1330
1422
|
)
|
|
1331
1423
|
);
|
|
1332
|
-
const cadence = unevenHourCadence(
|
|
1333
|
-
const phrase = cadence ? minuteLead + ", " + cadence + trailingQualifier(
|
|
1334
|
-
return
|
|
1424
|
+
const cadence = unevenHourCadence(schedule, opts);
|
|
1425
|
+
const phrase = cadence ? minuteLead + ", " + cadence + trailingQualifier(schedule, opts) : minuteLead + ", at " + hourSegmentTimes(schedule, { minute: 0, second: null }, true, opts) + trailingQualifier(schedule, opts);
|
|
1426
|
+
return schedule.analyses.clockSecond ? secondsLeadClause(schedule, opts) + ", " + phrase : phrase;
|
|
1335
1427
|
}
|
|
1336
|
-
function foldedHourWindows(
|
|
1428
|
+
function foldedHourWindows(schedule, plan, opts) {
|
|
1337
1429
|
const minute = plan.minute;
|
|
1338
1430
|
const windows = [];
|
|
1339
|
-
const times = collectHourOutliers(
|
|
1431
|
+
const times = collectHourOutliers(schedule).map(function time(hour) {
|
|
1340
1432
|
return getTime({ hour, minute }, opts);
|
|
1341
1433
|
});
|
|
1342
|
-
segmentsOf(
|
|
1434
|
+
segmentsOf(schedule, "hour").forEach(function classify(segment) {
|
|
1343
1435
|
if (segment.kind === "range") {
|
|
1344
1436
|
windows.push(rangeWindow({
|
|
1345
1437
|
continuous: false,
|
|
@@ -1349,12 +1441,12 @@ function foldedHourWindows(ir, plan, opts) {
|
|
|
1349
1441
|
}, opts));
|
|
1350
1442
|
}
|
|
1351
1443
|
});
|
|
1352
|
-
const phrase = rangeMinuteLead(
|
|
1444
|
+
const phrase = rangeMinuteLead(schedule, opts) + " " + joinList(windows, opts);
|
|
1353
1445
|
return phrase + outlierTail(times, opts);
|
|
1354
1446
|
}
|
|
1355
|
-
function collectHourOutliers(
|
|
1447
|
+
function collectHourOutliers(schedule) {
|
|
1356
1448
|
const hours = [];
|
|
1357
|
-
segmentsOf(
|
|
1449
|
+
segmentsOf(schedule, "hour").forEach(function classify(segment) {
|
|
1358
1450
|
if (segment.kind === "step") {
|
|
1359
1451
|
hours.push(...segment.fires);
|
|
1360
1452
|
} else if (segment.kind !== "range") {
|
|
@@ -1372,16 +1464,16 @@ function outlierTail(times, opts) {
|
|
|
1372
1464
|
function isCadenceField(token) {
|
|
1373
1465
|
return token === "*" || token.startsWith("*/") && token.indexOf("-") === -1;
|
|
1374
1466
|
}
|
|
1375
|
-
function leadingCadence(
|
|
1376
|
-
const { second, minute } =
|
|
1467
|
+
function leadingCadence(schedule, opts) {
|
|
1468
|
+
const { second, minute } = schedule.pattern;
|
|
1377
1469
|
if (isCadenceField(second)) {
|
|
1378
|
-
return { secondLead: true, text: secondsClause(
|
|
1470
|
+
return { secondLead: true, text: secondsClause(schedule, "minute", opts) };
|
|
1379
1471
|
}
|
|
1380
1472
|
if (second === "0" && isCadenceField(minute)) {
|
|
1381
1473
|
const text = minute === "*" ? "every minute" : (
|
|
1382
1474
|
// A clean minute step's first segment is a step segment.
|
|
1383
1475
|
stepCycle60(
|
|
1384
|
-
stepSegment(
|
|
1476
|
+
stepSegment(schedule, "minute"),
|
|
1385
1477
|
"minute",
|
|
1386
1478
|
"hour",
|
|
1387
1479
|
opts
|
|
@@ -1391,19 +1483,19 @@ function leadingCadence(ir, opts) {
|
|
|
1391
1483
|
}
|
|
1392
1484
|
return null;
|
|
1393
1485
|
}
|
|
1394
|
-
function minuteConfinement(
|
|
1395
|
-
const minute =
|
|
1486
|
+
function minuteConfinement(schedule, opts) {
|
|
1487
|
+
const minute = schedule.pattern.minute;
|
|
1396
1488
|
if (minute === "*") {
|
|
1397
1489
|
return "";
|
|
1398
1490
|
}
|
|
1399
1491
|
if (isCadenceField(minute)) {
|
|
1400
1492
|
return " of every other minute";
|
|
1401
1493
|
}
|
|
1402
|
-
const segments = segmentsOf(
|
|
1403
|
-
if (
|
|
1494
|
+
const segments = segmentsOf(schedule, "minute");
|
|
1495
|
+
if (schedule.shapes.minute === "single") {
|
|
1404
1496
|
return " during minute :" + pad(minute);
|
|
1405
1497
|
}
|
|
1406
|
-
if (
|
|
1498
|
+
if (schedule.shapes.minute === "range") {
|
|
1407
1499
|
const bounds = minute.split("-");
|
|
1408
1500
|
return " during minutes :" + pad(bounds[0]) + through(opts) + ":" + pad(bounds[1]);
|
|
1409
1501
|
}
|
|
@@ -1412,64 +1504,61 @@ function minuteConfinement(ir, opts) {
|
|
|
1412
1504
|
});
|
|
1413
1505
|
return " during minutes " + joinList(values, opts);
|
|
1414
1506
|
}
|
|
1415
|
-
function hourConfinement(
|
|
1416
|
-
const hour =
|
|
1507
|
+
function hourConfinement(schedule, opts) {
|
|
1508
|
+
const hour = schedule.pattern.hour;
|
|
1417
1509
|
if (hour === "*") {
|
|
1418
|
-
const minutePinned =
|
|
1510
|
+
const minutePinned = schedule.pattern.minute !== "*" && !isCadenceField(schedule.pattern.minute);
|
|
1419
1511
|
return minutePinned ? " of every hour" : "";
|
|
1420
1512
|
}
|
|
1421
1513
|
if (isCadenceField(hour)) {
|
|
1422
1514
|
return hour === "*/2" ? " of every other hour" : "";
|
|
1423
1515
|
}
|
|
1424
|
-
if (
|
|
1516
|
+
if (schedule.shapes.hour === "single") {
|
|
1425
1517
|
const h = +hour;
|
|
1426
|
-
if (
|
|
1518
|
+
if (schedule.shapes.minute === "step") {
|
|
1427
1519
|
return " from " + getTime({ hour: h, minute: 0 }, opts) + " until " + getTime({ hour: (h + 1) % 24, minute: 0 }, opts);
|
|
1428
1520
|
}
|
|
1429
|
-
if (
|
|
1521
|
+
if (schedule.pattern.minute !== "*" && !isCadenceField(schedule.pattern.minute)) {
|
|
1430
1522
|
return " at " + getTime({ hour: h, minute: 0 }, opts);
|
|
1431
1523
|
}
|
|
1432
1524
|
return " of the " + getTime({ hour: h, minute: 0 }, opts) + " hour";
|
|
1433
1525
|
}
|
|
1434
|
-
if (
|
|
1526
|
+
if (schedule.shapes.hour === "range") {
|
|
1435
1527
|
const bounds = hour.split("-");
|
|
1436
1528
|
return " " + rangeWindow({
|
|
1437
|
-
continuous:
|
|
1529
|
+
continuous: schedule.pattern.minute === "*",
|
|
1438
1530
|
from: +bounds[0],
|
|
1439
1531
|
throughMinute: 0,
|
|
1440
1532
|
to: +bounds[1]
|
|
1441
1533
|
}, opts);
|
|
1442
1534
|
}
|
|
1443
|
-
return " during the " + hourSegmentTimes(
|
|
1444
|
-
}
|
|
1445
|
-
function isContiguousHourRange(ir) {
|
|
1446
|
-
return ir.shapes.hour === "range";
|
|
1535
|
+
return " during the " + hourSegmentTimes(schedule, { minute: 0, second: null }, false, opts) + " hours";
|
|
1447
1536
|
}
|
|
1448
|
-
function confinableHour(
|
|
1449
|
-
if (
|
|
1537
|
+
function confinableHour(schedule) {
|
|
1538
|
+
if (schedule.shapes.hour !== "step") {
|
|
1450
1539
|
return true;
|
|
1451
1540
|
}
|
|
1452
|
-
const segment = stepSegment(
|
|
1453
|
-
return
|
|
1541
|
+
const segment = stepSegment(schedule, "hour");
|
|
1542
|
+
return schedule.pattern.hour === "*/2" || segment.startToken.indexOf("-") !== -1;
|
|
1454
1543
|
}
|
|
1455
|
-
function isMinuteStride(
|
|
1456
|
-
if (
|
|
1544
|
+
function isMinuteStride(schedule) {
|
|
1545
|
+
if (schedule.shapes.minute !== "list") {
|
|
1457
1546
|
return false;
|
|
1458
1547
|
}
|
|
1459
|
-
const values = singleValues(segmentsOf(
|
|
1548
|
+
const values = singleValues(segmentsOf(schedule, "minute"));
|
|
1460
1549
|
return values !== null && arithmeticStep(values) !== null;
|
|
1461
1550
|
}
|
|
1462
|
-
function confinementEligible(
|
|
1463
|
-
const { minute, hour } =
|
|
1551
|
+
function confinementEligible(schedule, lead) {
|
|
1552
|
+
const { minute, hour } = schedule.pattern;
|
|
1464
1553
|
const minuteStep = isCadenceField(minute) && minute !== "*";
|
|
1465
|
-
if (!confinableHour(
|
|
1554
|
+
if (!confinableHour(schedule)) {
|
|
1466
1555
|
return false;
|
|
1467
1556
|
}
|
|
1468
1557
|
if (lead.secondLead) {
|
|
1469
1558
|
if (minuteStep) {
|
|
1470
|
-
return minute === "*/2" &&
|
|
1559
|
+
return minute === "*/2" && schedule.shapes.hour !== "range";
|
|
1471
1560
|
}
|
|
1472
|
-
if (isMinuteStride(
|
|
1561
|
+
if (isMinuteStride(schedule) || schedule.shapes.minute === "list" && schedule.shapes.hour === "list") {
|
|
1473
1562
|
return false;
|
|
1474
1563
|
}
|
|
1475
1564
|
return true;
|
|
@@ -1477,21 +1566,21 @@ function confinementEligible(ir, lead) {
|
|
|
1477
1566
|
if (hour === "*/2") {
|
|
1478
1567
|
return true;
|
|
1479
1568
|
}
|
|
1480
|
-
return
|
|
1569
|
+
return schedule.shapes.hour === "single" && minute === "*/2";
|
|
1481
1570
|
}
|
|
1482
|
-
function confinement(
|
|
1571
|
+
function confinement(schedule, opts) {
|
|
1483
1572
|
if (!opts.style.untilWindow || opts.short) {
|
|
1484
1573
|
return null;
|
|
1485
1574
|
}
|
|
1486
|
-
if (
|
|
1575
|
+
if (schedule.pattern.minute === "*" && schedule.pattern.hour === "*") {
|
|
1487
1576
|
return null;
|
|
1488
1577
|
}
|
|
1489
|
-
const lead = leadingCadence(
|
|
1490
|
-
if (!lead || !confinementEligible(
|
|
1578
|
+
const lead = leadingCadence(schedule, opts);
|
|
1579
|
+
if (!lead || !confinementEligible(schedule, lead)) {
|
|
1491
1580
|
return null;
|
|
1492
1581
|
}
|
|
1493
|
-
const minutePart = lead.secondLead ? minuteConfinement(
|
|
1494
|
-
return lead.text + minutePart + hourConfinement(
|
|
1582
|
+
const minutePart = lead.secondLead ? minuteConfinement(schedule, opts) : "";
|
|
1583
|
+
return lead.text + minutePart + hourConfinement(schedule, opts) + trailingQualifier(schedule, opts);
|
|
1495
1584
|
}
|
|
1496
1585
|
var renderers = {
|
|
1497
1586
|
clockTimes: renderClockTimes,
|
|
@@ -1513,23 +1602,25 @@ var renderers = {
|
|
|
1513
1602
|
singleMinute: renderSingleMinute,
|
|
1514
1603
|
standaloneSeconds: renderStandaloneSeconds
|
|
1515
1604
|
};
|
|
1516
|
-
function
|
|
1605
|
+
function renderStride2(stride, opts) {
|
|
1517
1606
|
const { interval, start, last, cycle, unit, anchor } = stride;
|
|
1518
1607
|
const cadence = "every " + getNumber(interval, opts) + " " + unit + "s";
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1608
|
+
return renderStride({ start, interval, cycle }, {
|
|
1609
|
+
bare: () => cadence,
|
|
1610
|
+
// A clean wrap from a non-zero offset: name the start, no endpoint.
|
|
1611
|
+
offset: () => cadence + " from " + getNumber(start, opts) + " " + pluralize(start, unit) + " past the " + anchor,
|
|
1612
|
+
// A bounded, non-wrapping set: pin both endpoints. Each bound is a value,
|
|
1613
|
+
// so it reads as a digit, matching the range idiom ("from 0 through 30").
|
|
1614
|
+
bounded: () => {
|
|
1615
|
+
const num = seriesNumber();
|
|
1616
|
+
return cadence + " from " + num(start) + through(opts) + num(last) + " " + pluralize(last, unit) + " past the " + anchor;
|
|
1617
|
+
}
|
|
1618
|
+
});
|
|
1528
1619
|
}
|
|
1529
1620
|
function strideFromSegments(segments, unit, anchor, opts) {
|
|
1530
1621
|
const values = singleValues(segments);
|
|
1531
1622
|
const step = values && arithmeticStep(values);
|
|
1532
|
-
return step ?
|
|
1623
|
+
return step ? renderStride2({ ...step, cycle: 60, unit, anchor }, opts) : null;
|
|
1533
1624
|
}
|
|
1534
1625
|
function stepCycle60(segment, unit, anchor, opts) {
|
|
1535
1626
|
if (segment.startToken.indexOf("-") !== -1) {
|
|
@@ -1539,7 +1630,7 @@ function stepCycle60(segment, unit, anchor, opts) {
|
|
|
1539
1630
|
if (start !== 0 && segment.fires.length <= 3) {
|
|
1540
1631
|
return listPastThe(numberWords(segment.fires, opts), unit, anchor, opts);
|
|
1541
1632
|
}
|
|
1542
|
-
return
|
|
1633
|
+
return renderStride2({
|
|
1543
1634
|
interval: segment.interval,
|
|
1544
1635
|
start,
|
|
1545
1636
|
last: segment.fires[segment.fires.length - 1],
|
|
@@ -1565,24 +1656,21 @@ function stepHours(segment, opts) {
|
|
|
1565
1656
|
function hourStrideCadence(stride, opts) {
|
|
1566
1657
|
const { start, interval, last } = stride;
|
|
1567
1658
|
const cadence = "every " + getNumber(interval, opts) + " hours";
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
return cadence + " from " + getTime({ hour: start, minute: 0 }, opts);
|
|
1574
|
-
}
|
|
1575
|
-
return cadence + " from " + getTime({ hour: start, minute: 0 }, opts) + through(opts) + getTime({ hour: last, minute: 0 }, opts);
|
|
1659
|
+
return renderStride({ start, interval, cycle: 24 }, {
|
|
1660
|
+
bare: () => cadence,
|
|
1661
|
+
offset: () => cadence + " from " + getTime({ hour: start, minute: 0 }, opts),
|
|
1662
|
+
bounded: () => cadence + " from " + getTime({ hour: start, minute: 0 }, opts) + through(opts) + getTime({ hour: last, minute: 0 }, opts)
|
|
1663
|
+
});
|
|
1576
1664
|
}
|
|
1577
|
-
function unevenHourCadence(
|
|
1578
|
-
const stride = hourStride(
|
|
1665
|
+
function unevenHourCadence(schedule, opts) {
|
|
1666
|
+
const stride = hourStride(schedule);
|
|
1579
1667
|
if (!stride || offsetCleanStride(stride)) {
|
|
1580
1668
|
return null;
|
|
1581
1669
|
}
|
|
1582
1670
|
return hourStrideCadence(stride, opts);
|
|
1583
1671
|
}
|
|
1584
|
-
function hourStride(
|
|
1585
|
-
const segments = segmentsOf(
|
|
1672
|
+
function hourStride(schedule) {
|
|
1673
|
+
const segments = segmentsOf(schedule, "hour");
|
|
1586
1674
|
if (segments.length === 1 && segments[0].kind === "step") {
|
|
1587
1675
|
const segment = segments[0];
|
|
1588
1676
|
if (segment.fires.length < 2) {
|
|
@@ -1594,57 +1682,57 @@ function hourStride(ir) {
|
|
|
1594
1682
|
const values = singleValues(segments);
|
|
1595
1683
|
return values && hourListStride(values);
|
|
1596
1684
|
}
|
|
1597
|
-
function subMinuteSecond(
|
|
1598
|
-
return
|
|
1685
|
+
function subMinuteSecond(schedule) {
|
|
1686
|
+
return schedule.pattern.second === "*" || schedule.shapes.second === "step";
|
|
1599
1687
|
}
|
|
1600
|
-
function hourCadenceLead(
|
|
1688
|
+
function hourCadenceLead(schedule, minute, opts) {
|
|
1601
1689
|
if (minute === 0) {
|
|
1602
|
-
if (subMinuteSecond(
|
|
1603
|
-
return secondsClause(
|
|
1690
|
+
if (subMinuteSecond(schedule)) {
|
|
1691
|
+
return secondsClause(schedule, "minute", opts) + " for one minute";
|
|
1604
1692
|
}
|
|
1605
|
-
return secondsClause(
|
|
1693
|
+
return secondsClause(schedule, "hour", opts);
|
|
1606
1694
|
}
|
|
1607
1695
|
const minutePhrase = getNumber(minute, opts) + " " + pluralize(minute, "minute") + " past the hour";
|
|
1608
|
-
if (
|
|
1696
|
+
if (schedule.pattern.second === "0") {
|
|
1609
1697
|
return minutePhrase;
|
|
1610
1698
|
}
|
|
1611
|
-
return secondsClause(
|
|
1699
|
+
return secondsClause(schedule, "minute", opts) + ", " + minutePhrase;
|
|
1612
1700
|
}
|
|
1613
|
-
function hourCadence(
|
|
1614
|
-
const stride = hourStride(
|
|
1701
|
+
function hourCadence(schedule, minute, opts) {
|
|
1702
|
+
const stride = hourStride(schedule);
|
|
1615
1703
|
if (!stride) {
|
|
1616
1704
|
return null;
|
|
1617
1705
|
}
|
|
1618
1706
|
const fires = (stride.last - stride.start) / stride.interval + 1;
|
|
1619
|
-
if (
|
|
1707
|
+
if (schedule.pattern.second === "0" && fires <= maxClockTimes && offsetCleanStride(stride)) {
|
|
1620
1708
|
return null;
|
|
1621
1709
|
}
|
|
1622
|
-
const minuteZeroStride = minute === 0 && subMinuteSecond(
|
|
1710
|
+
const minuteZeroStride = minute === 0 && subMinuteSecond(schedule) && cleanStrideSegment(schedule);
|
|
1623
1711
|
if (minuteZeroStride) {
|
|
1624
|
-
return secondsClause(
|
|
1712
|
+
return secondsClause(schedule, "minute", opts) + " for one minute " + everyNthHour(minuteZeroStride, opts) + trailingQualifier(schedule, opts);
|
|
1625
1713
|
}
|
|
1626
|
-
if (minute === 0 &&
|
|
1627
|
-
return hourStrideCadence(stride, opts) + trailingQualifier(
|
|
1714
|
+
if (minute === 0 && schedule.pattern.second === "0") {
|
|
1715
|
+
return hourStrideCadence(stride, opts) + trailingQualifier(schedule, opts);
|
|
1628
1716
|
}
|
|
1629
|
-
return hourCadenceLead(
|
|
1717
|
+
return hourCadenceLead(schedule, minute, opts) + ", " + hourStrideCadence(stride, opts) + trailingQualifier(schedule, opts);
|
|
1630
1718
|
}
|
|
1631
|
-
function cleanStrideSegment(
|
|
1632
|
-
const segments = segmentsOf(
|
|
1719
|
+
function cleanStrideSegment(schedule) {
|
|
1720
|
+
const segments = segmentsOf(schedule, "hour");
|
|
1633
1721
|
const segment = segments.length === 1 && segments[0];
|
|
1634
1722
|
if (!segment || segment.kind !== "step" || segment.startToken.indexOf("-") !== -1 || !(segment.interval in stepOrdinals)) {
|
|
1635
1723
|
return null;
|
|
1636
1724
|
}
|
|
1637
1725
|
return segment;
|
|
1638
1726
|
}
|
|
1639
|
-
function hasHourWindow(
|
|
1640
|
-
return segmentsOf(
|
|
1727
|
+
function hasHourWindow(schedule) {
|
|
1728
|
+
return segmentsOf(schedule, "hour").some(function range(segment) {
|
|
1641
1729
|
return segment.kind === "range";
|
|
1642
1730
|
});
|
|
1643
1731
|
}
|
|
1644
|
-
function hourRangeWindowTail(
|
|
1732
|
+
function hourRangeWindowTail(schedule, opts) {
|
|
1645
1733
|
const windows = [];
|
|
1646
|
-
const outlierHours = collectHourOutliers(
|
|
1647
|
-
segmentsOf(
|
|
1734
|
+
const outlierHours = collectHourOutliers(schedule);
|
|
1735
|
+
segmentsOf(schedule, "hour").forEach(function classify(segment) {
|
|
1648
1736
|
if (segment.kind === "range") {
|
|
1649
1737
|
windows.push(rangeWindow({
|
|
1650
1738
|
continuous: false,
|
|
@@ -1660,17 +1748,17 @@ function hourRangeWindowTail(ir, opts) {
|
|
|
1660
1748
|
});
|
|
1661
1749
|
return phrase + outlierTail(times, opts);
|
|
1662
1750
|
}
|
|
1663
|
-
function hourRangeCadence(
|
|
1664
|
-
if (minute !== 0 || !hasHourWindow(
|
|
1751
|
+
function hourRangeCadence(schedule, minute, opts) {
|
|
1752
|
+
if (minute !== 0 || !hasHourWindow(schedule)) {
|
|
1665
1753
|
return null;
|
|
1666
1754
|
}
|
|
1667
|
-
if (
|
|
1755
|
+
if (schedule.pattern.second === "0") {
|
|
1668
1756
|
return null;
|
|
1669
1757
|
}
|
|
1670
|
-
if (subMinuteSecond(
|
|
1671
|
-
return secondsClause(
|
|
1758
|
+
if (subMinuteSecond(schedule)) {
|
|
1759
|
+
return secondsClause(schedule, "minute", opts) + " for one minute during the " + hourSegmentTimes(schedule, { minute: 0, second: null }, false, opts) + " hours" + trailingQualifier(schedule, opts);
|
|
1672
1760
|
}
|
|
1673
|
-
return hourCadenceLead(
|
|
1761
|
+
return hourCadenceLead(schedule, minute, opts) + ", " + hourRangeWindowTail(schedule, opts) + trailingQualifier(schedule, opts);
|
|
1674
1762
|
}
|
|
1675
1763
|
function seriesNumber() {
|
|
1676
1764
|
return function format(n) {
|
|
@@ -1729,11 +1817,11 @@ function hourTimes(hours, opts) {
|
|
|
1729
1817
|
function singleHourFire(times) {
|
|
1730
1818
|
return times.kind === "fires" && times.fires.length === 1;
|
|
1731
1819
|
}
|
|
1732
|
-
function hourTimesFromPlan(
|
|
1820
|
+
function hourTimesFromPlan(schedule, times, atContext, opts) {
|
|
1733
1821
|
if (times.kind === "fires") {
|
|
1734
1822
|
return hourTimes(times.fires, opts);
|
|
1735
1823
|
}
|
|
1736
|
-
return hourSegmentTimes(
|
|
1824
|
+
return hourSegmentTimes(schedule, { minute: 0, second: null }, atContext, opts);
|
|
1737
1825
|
}
|
|
1738
1826
|
function segmentHours(segment) {
|
|
1739
1827
|
if (segment.kind === "range") {
|
|
@@ -1741,9 +1829,9 @@ function segmentHours(segment) {
|
|
|
1741
1829
|
}
|
|
1742
1830
|
return segment.kind === "step" ? segment.fires : [segment.value];
|
|
1743
1831
|
}
|
|
1744
|
-
function hourSegmentTimes(
|
|
1832
|
+
function hourSegmentTimes(schedule, fold, atContext, opts) {
|
|
1745
1833
|
const { minute, second } = fold;
|
|
1746
|
-
const segments = segmentsOf(
|
|
1834
|
+
const segments = segmentsOf(schedule, "hour");
|
|
1747
1835
|
const plain = mixedTwelve(segments.flatMap(function entries(segment) {
|
|
1748
1836
|
return segmentHours(segment).map(function entry(hour) {
|
|
1749
1837
|
return { hour: +hour, minute, second };
|
|
@@ -1806,85 +1894,85 @@ var leadingWords = {
|
|
|
1806
1894
|
stepDate: "",
|
|
1807
1895
|
weekday: "every "
|
|
1808
1896
|
};
|
|
1809
|
-
function trailingQualifier(
|
|
1810
|
-
if (isDayUnion(
|
|
1811
|
-
return dayUnionCondition(
|
|
1897
|
+
function trailingQualifier(schedule, opts) {
|
|
1898
|
+
if (isDayUnion(schedule, opts)) {
|
|
1899
|
+
return dayUnionCondition(schedule, opts);
|
|
1812
1900
|
}
|
|
1813
|
-
const phrase = dayQualifier(
|
|
1901
|
+
const phrase = dayQualifier(schedule, trailingWords, opts);
|
|
1814
1902
|
return phrase && " " + phrase;
|
|
1815
1903
|
}
|
|
1816
|
-
function interpretDayQualifier(
|
|
1817
|
-
if (isDayUnion(
|
|
1904
|
+
function interpretDayQualifier(schedule, opts) {
|
|
1905
|
+
if (isDayUnion(schedule, opts)) {
|
|
1818
1906
|
return "";
|
|
1819
1907
|
}
|
|
1820
|
-
return dayQualifier(
|
|
1908
|
+
return dayQualifier(schedule, leadingWords, opts) + " ";
|
|
1821
1909
|
}
|
|
1822
|
-
function dayQualifier(
|
|
1823
|
-
const pattern =
|
|
1910
|
+
function dayQualifier(schedule, words, opts) {
|
|
1911
|
+
const pattern = schedule.pattern;
|
|
1824
1912
|
if (pattern.date !== "*" && pattern.weekday !== "*") {
|
|
1825
|
-
return dateOrWeekday(
|
|
1913
|
+
return dateOrWeekday(schedule, opts);
|
|
1826
1914
|
}
|
|
1827
1915
|
if (pattern.date !== "*") {
|
|
1828
|
-
return datePhrase(
|
|
1916
|
+
return datePhrase(schedule, words, opts);
|
|
1829
1917
|
}
|
|
1830
1918
|
if (pattern.weekday !== "*") {
|
|
1831
1919
|
const quartzWeekday = quartzWeekdayPhrase(pattern.weekday, opts);
|
|
1832
1920
|
if (quartzWeekday) {
|
|
1833
|
-
return monthScopeForRecurrence(quartzWeekday,
|
|
1921
|
+
return monthScopeForRecurrence(quartzWeekday, schedule, opts);
|
|
1834
1922
|
}
|
|
1835
|
-
const weekdays = words.weekday + weekdayPhrase(
|
|
1836
|
-
return weekdays + monthScope(
|
|
1923
|
+
const weekdays = words.weekday + weekdayPhrase(schedule, words.recurringWeekday, opts);
|
|
1924
|
+
return weekdays + monthScope(schedule, opts);
|
|
1837
1925
|
}
|
|
1838
1926
|
if (pattern.month !== "*") {
|
|
1839
|
-
return words.month + monthName(
|
|
1927
|
+
return words.month + monthName(schedule, opts);
|
|
1840
1928
|
}
|
|
1841
1929
|
return words.all;
|
|
1842
1930
|
}
|
|
1843
|
-
function datePhrase(
|
|
1844
|
-
const pattern =
|
|
1931
|
+
function datePhrase(schedule, words, opts) {
|
|
1932
|
+
const pattern = schedule.pattern;
|
|
1845
1933
|
const quartzDate = quartzDatePhrase(pattern.date, opts);
|
|
1846
1934
|
if (quartzDate) {
|
|
1847
|
-
return monthScopeForRecurrence(quartzDate,
|
|
1935
|
+
return monthScopeForRecurrence(quartzDate, schedule, opts);
|
|
1848
1936
|
}
|
|
1849
1937
|
if (isOpenStep(pattern.date)) {
|
|
1850
1938
|
return monthScopeForRecurrence(
|
|
1851
1939
|
words.stepDate + stepDates(pattern.date),
|
|
1852
|
-
|
|
1940
|
+
schedule,
|
|
1853
1941
|
opts
|
|
1854
1942
|
);
|
|
1855
1943
|
}
|
|
1856
|
-
if (pattern.month !== "*" && !monthFoldsIntoDate(
|
|
1857
|
-
return "on the " + dateOrdinals(
|
|
1944
|
+
if (pattern.month !== "*" && !monthFoldsIntoDate(schedule)) {
|
|
1945
|
+
return "on the " + dateOrdinals(schedule, opts) + monthScope(schedule, opts);
|
|
1858
1946
|
}
|
|
1859
1947
|
if (pattern.month !== "*") {
|
|
1860
|
-
return "on " + monthDatePhrase(
|
|
1948
|
+
return "on " + monthDatePhrase(schedule, opts);
|
|
1861
1949
|
}
|
|
1862
|
-
return "on the " + dateOrdinals(
|
|
1950
|
+
return "on the " + dateOrdinals(schedule, opts);
|
|
1863
1951
|
}
|
|
1864
|
-
function monthFoldsIntoDate(
|
|
1865
|
-
return !oddEvenMonth(
|
|
1866
|
-
segmentsOf(
|
|
1952
|
+
function monthFoldsIntoDate(schedule) {
|
|
1953
|
+
return !oddEvenMonth(schedule.pattern.month) && // Reached only with a restricted month, which has segments.
|
|
1954
|
+
segmentsOf(schedule, "month").every(function flat(segment) {
|
|
1867
1955
|
return segment.kind !== "range";
|
|
1868
1956
|
});
|
|
1869
1957
|
}
|
|
1870
|
-
function isDayUnion(
|
|
1871
|
-
return
|
|
1958
|
+
function isDayUnion(schedule, opts) {
|
|
1959
|
+
return schedule.pattern.date !== "*" && schedule.pattern.weekday !== "*" && !!opts.style.untilWindow && !opts.short;
|
|
1872
1960
|
}
|
|
1873
|
-
function dayUnionCondition(
|
|
1961
|
+
function dayUnionCondition(schedule, opts) {
|
|
1874
1962
|
const pieces = [
|
|
1875
|
-
...dayUnionDatePieces(
|
|
1876
|
-
...dayUnionWeekdayPieces(
|
|
1963
|
+
...dayUnionDatePieces(schedule, opts),
|
|
1964
|
+
...dayUnionWeekdayPieces(schedule, opts)
|
|
1877
1965
|
];
|
|
1878
1966
|
return " whenever the day is " + joinOr(pieces, opts);
|
|
1879
1967
|
}
|
|
1880
|
-
function dayUnionMonthLead(
|
|
1881
|
-
if (
|
|
1968
|
+
function dayUnionMonthLead(schedule, opts) {
|
|
1969
|
+
if (schedule.pattern.month === "*") {
|
|
1882
1970
|
return "";
|
|
1883
1971
|
}
|
|
1884
|
-
return "in " + monthName(
|
|
1972
|
+
return "in " + monthName(schedule, opts) + " ";
|
|
1885
1973
|
}
|
|
1886
|
-
function dayUnionDatePieces(
|
|
1887
|
-
const dateField =
|
|
1974
|
+
function dayUnionDatePieces(schedule, opts) {
|
|
1975
|
+
const dateField = schedule.pattern.date;
|
|
1888
1976
|
const quartz = quartzDatePhrase(dateField, opts);
|
|
1889
1977
|
if (quartz) {
|
|
1890
1978
|
return [quartz.replace(/^on /, "")];
|
|
@@ -1894,7 +1982,7 @@ function dayUnionDatePieces(ir, opts) {
|
|
|
1894
1982
|
return [oddEven];
|
|
1895
1983
|
}
|
|
1896
1984
|
const pieces = [];
|
|
1897
|
-
segmentsOf(
|
|
1985
|
+
segmentsOf(schedule, "date").forEach(function expand(segment) {
|
|
1898
1986
|
if (segment.kind === "range") {
|
|
1899
1987
|
pieces.push("from the " + getOrdinal(segment.bounds[0]) + through(opts) + "the " + getOrdinal(segment.bounds[1]));
|
|
1900
1988
|
} else if (segment.kind === "step") {
|
|
@@ -1907,14 +1995,14 @@ function dayUnionDatePieces(ir, opts) {
|
|
|
1907
1995
|
});
|
|
1908
1996
|
return pieces;
|
|
1909
1997
|
}
|
|
1910
|
-
function dayUnionWeekdayPieces(
|
|
1911
|
-
const weekdayField =
|
|
1998
|
+
function dayUnionWeekdayPieces(schedule, opts) {
|
|
1999
|
+
const weekdayField = schedule.pattern.weekday;
|
|
1912
2000
|
const quartz = quartzWeekdayPhrase(weekdayField, opts);
|
|
1913
2001
|
if (quartz) {
|
|
1914
2002
|
return [quartz.replace(/^on /, "")];
|
|
1915
2003
|
}
|
|
1916
2004
|
const pieces = [];
|
|
1917
|
-
segmentsOf(
|
|
2005
|
+
segmentsOf(schedule, "weekday").forEach(function expand(segment) {
|
|
1918
2006
|
if (segment.kind === "range" && segment.bounds[0] === "1" && segment.bounds[1] === "5") {
|
|
1919
2007
|
pieces.push("a weekday");
|
|
1920
2008
|
} else if (segment.kind === "range") {
|
|
@@ -1942,16 +2030,16 @@ function oddEvenDay(dateField) {
|
|
|
1942
2030
|
}
|
|
1943
2031
|
return start === "2" ? "an even-numbered day" : null;
|
|
1944
2032
|
}
|
|
1945
|
-
function dateOrWeekday(
|
|
1946
|
-
const pattern =
|
|
1947
|
-
const weekdayPart = quartzWeekdayPhrase(pattern.weekday, opts) || "on " + weekdayPhrase(
|
|
1948
|
-
if (pattern.month !== "*" && monthFoldsIntoDate(
|
|
1949
|
-
return "on " + monthDatePhrase(
|
|
2033
|
+
function dateOrWeekday(schedule, opts) {
|
|
2034
|
+
const pattern = schedule.pattern;
|
|
2035
|
+
const weekdayPart = quartzWeekdayPhrase(pattern.weekday, opts) || "on " + weekdayPhrase(schedule, false, opts);
|
|
2036
|
+
if (pattern.month !== "*" && monthFoldsIntoDate(schedule) && !quartzDatePhrase(pattern.date, opts) && !isOpenStep(pattern.date)) {
|
|
2037
|
+
return "on " + monthDatePhrase(schedule, opts) + " or " + weekdayPart + " in " + monthName(schedule, opts);
|
|
1950
2038
|
}
|
|
1951
|
-
return datePart(
|
|
2039
|
+
return datePart(schedule, opts) + " or " + weekdayPart + orMonthScope(schedule, opts);
|
|
1952
2040
|
}
|
|
1953
|
-
function datePart(
|
|
1954
|
-
const pattern =
|
|
2041
|
+
function datePart(schedule, opts) {
|
|
2042
|
+
const pattern = schedule.pattern;
|
|
1955
2043
|
const quartzDate = quartzDatePhrase(pattern.date, opts);
|
|
1956
2044
|
if (quartzDate) {
|
|
1957
2045
|
return quartzDate;
|
|
@@ -1959,13 +2047,13 @@ function datePart(ir, opts) {
|
|
|
1959
2047
|
if (isOpenStep(pattern.date)) {
|
|
1960
2048
|
return stepDates(pattern.date);
|
|
1961
2049
|
}
|
|
1962
|
-
return "on the " + dateOrdinals(
|
|
2050
|
+
return "on the " + dateOrdinals(schedule, opts);
|
|
1963
2051
|
}
|
|
1964
|
-
function orMonthScope(
|
|
1965
|
-
if (
|
|
2052
|
+
function orMonthScope(schedule, opts) {
|
|
2053
|
+
if (schedule.pattern.month === "*") {
|
|
1966
2054
|
return "";
|
|
1967
2055
|
}
|
|
1968
|
-
return ", in " + monthName(
|
|
2056
|
+
return ", in " + monthName(schedule, opts);
|
|
1969
2057
|
}
|
|
1970
2058
|
function quartzDatePhrase(dateField, opts) {
|
|
1971
2059
|
if (dateField === "L") {
|
|
@@ -1992,39 +2080,39 @@ function quartzWeekdayPhrase(weekdayField, opts) {
|
|
|
1992
2080
|
return "on the last " + getWeekday(weekdayField.slice(0, -1), opts) + " of the month";
|
|
1993
2081
|
}
|
|
1994
2082
|
}
|
|
1995
|
-
function monthDatePhrase(
|
|
1996
|
-
const month = monthName(
|
|
2083
|
+
function monthDatePhrase(schedule, opts) {
|
|
2084
|
+
const month = monthName(schedule, opts);
|
|
1997
2085
|
const days = renderSegments(
|
|
1998
|
-
segmentsOf(
|
|
2086
|
+
segmentsOf(schedule, "date"),
|
|
1999
2087
|
opts.style.ordinals ? getOrdinal : cardinalDay,
|
|
2000
2088
|
opts
|
|
2001
2089
|
);
|
|
2002
|
-
if (opts.style.dayFirst &&
|
|
2003
|
-
return "the " + getOrdinal(
|
|
2090
|
+
if (opts.style.dayFirst && schedule.shapes.date === "single" && schedule.shapes.month !== "single") {
|
|
2091
|
+
return "the " + getOrdinal(schedule.pattern.date) + " of " + month;
|
|
2004
2092
|
}
|
|
2005
2093
|
return opts.style.dayFirst ? days + " " + month : month + " " + days;
|
|
2006
2094
|
}
|
|
2007
2095
|
function cardinalDay(value) {
|
|
2008
2096
|
return "" + value;
|
|
2009
2097
|
}
|
|
2010
|
-
function monthScope(
|
|
2011
|
-
if (
|
|
2098
|
+
function monthScope(schedule, opts) {
|
|
2099
|
+
if (schedule.pattern.month === "*") {
|
|
2012
2100
|
return "";
|
|
2013
2101
|
}
|
|
2014
|
-
return " in " + monthName(
|
|
2102
|
+
return " in " + monthName(schedule, opts);
|
|
2015
2103
|
}
|
|
2016
|
-
function monthScopeForRecurrence(phrase,
|
|
2017
|
-
if (
|
|
2104
|
+
function monthScopeForRecurrence(phrase, schedule, opts) {
|
|
2105
|
+
if (schedule.pattern.month === "*") {
|
|
2018
2106
|
return phrase;
|
|
2019
2107
|
}
|
|
2020
2108
|
const carriesRecurrence = phrase.indexOf(" of the month") !== -1;
|
|
2021
|
-
if (carriesRecurrence &&
|
|
2022
|
-
return phrase.replace(" of the month", " of each month") + " from " + monthName(
|
|
2109
|
+
if (carriesRecurrence && schedule.shapes.month === "range") {
|
|
2110
|
+
return phrase.replace(" of the month", " of each month") + " from " + monthName(schedule, opts);
|
|
2023
2111
|
}
|
|
2024
|
-
if (carriesRecurrence && (
|
|
2025
|
-
return phrase.replace(" of the month", "") + " in " + monthName(
|
|
2112
|
+
if (carriesRecurrence && (schedule.shapes.month === "single" || schedule.shapes.month === "step")) {
|
|
2113
|
+
return phrase.replace(" of the month", "") + " in " + monthName(schedule, opts);
|
|
2026
2114
|
}
|
|
2027
|
-
return phrase + " in " + monthName(
|
|
2115
|
+
return phrase + " in " + monthName(schedule, opts);
|
|
2028
2116
|
}
|
|
2029
2117
|
function stepDates(dateField) {
|
|
2030
2118
|
const parts = dateField.split("/");
|
|
@@ -2037,15 +2125,15 @@ function stepDates(dateField) {
|
|
|
2037
2125
|
}
|
|
2038
2126
|
return phrase;
|
|
2039
2127
|
}
|
|
2040
|
-
function dateOrdinals(
|
|
2041
|
-
return renderSegments(segmentsOf(
|
|
2128
|
+
function dateOrdinals(schedule, opts) {
|
|
2129
|
+
return renderSegments(segmentsOf(schedule, "date"), getOrdinal, opts);
|
|
2042
2130
|
}
|
|
2043
|
-
function monthName(
|
|
2044
|
-
const oddEven = oddEvenMonth(
|
|
2131
|
+
function monthName(schedule, opts) {
|
|
2132
|
+
const oddEven = oddEvenMonth(schedule.pattern.month);
|
|
2045
2133
|
if (oddEven) {
|
|
2046
2134
|
return oddEven;
|
|
2047
2135
|
}
|
|
2048
|
-
return renderSegments(segmentsOf(
|
|
2136
|
+
return renderSegments(segmentsOf(schedule, "month"), function name(value) {
|
|
2049
2137
|
return getMonth(value, opts);
|
|
2050
2138
|
}, opts);
|
|
2051
2139
|
}
|
|
@@ -2062,8 +2150,8 @@ function oddEvenMonth(monthField) {
|
|
|
2062
2150
|
}
|
|
2063
2151
|
return start === "2" ? "every even-numbered month" : null;
|
|
2064
2152
|
}
|
|
2065
|
-
function weekdayPhrase(
|
|
2066
|
-
const segments = orderWeekdaysForDisplay(segmentsOf(
|
|
2153
|
+
function weekdayPhrase(schedule, recurring, opts) {
|
|
2154
|
+
const segments = orderWeekdaysForDisplay(segmentsOf(schedule, "weekday"));
|
|
2067
2155
|
const hasRange = segments.some(function range(segment) {
|
|
2068
2156
|
return segment.kind === "range";
|
|
2069
2157
|
});
|
|
@@ -2091,8 +2179,8 @@ function renderSegments(segments, word, opts) {
|
|
|
2091
2179
|
});
|
|
2092
2180
|
return joinList(pieces, opts);
|
|
2093
2181
|
}
|
|
2094
|
-
function applyYear(description,
|
|
2095
|
-
const yearField =
|
|
2182
|
+
function applyYear(description, schedule, opts) {
|
|
2183
|
+
const yearField = schedule.pattern.year;
|
|
2096
2184
|
if (yearField === "*") {
|
|
2097
2185
|
return description;
|
|
2098
2186
|
}
|
|
@@ -2100,7 +2188,7 @@ function applyYear(description, ir, opts) {
|
|
|
2100
2188
|
return description + ", " + stepYears(yearField, opts);
|
|
2101
2189
|
}
|
|
2102
2190
|
const label = yearLabel(yearField, opts);
|
|
2103
|
-
if (yearField.indexOf("-") === -1 && yearField.indexOf(",") === -1 &&
|
|
2191
|
+
if (yearField.indexOf("-") === -1 && yearField.indexOf(",") === -1 && schedule.pattern.date !== "*" && description.indexOf(" at ") !== -1) {
|
|
2104
2192
|
const yearGlue = opts.style.dayFirst ? " " : ", ";
|
|
2105
2193
|
return description.replace(" at ", yearGlue + label + " at ");
|
|
2106
2194
|
}
|
|
@@ -2223,9 +2311,9 @@ function interpretCronPattern(cronPattern, lang, opts) {
|
|
|
2223
2311
|
if (typeof cronPattern === "string" && cronPattern.trim().toLowerCase() === "@reboot") {
|
|
2224
2312
|
return lang.reboot;
|
|
2225
2313
|
}
|
|
2226
|
-
const
|
|
2227
|
-
const plan = lang.plan ? lang.plan(
|
|
2228
|
-
return lang.describe({ ...
|
|
2314
|
+
const schedule = analyze(prepare(cronPattern, opts));
|
|
2315
|
+
const plan = lang.plan ? lang.plan(schedule, schedule.plan) : schedule.plan;
|
|
2316
|
+
return lang.describe({ ...schedule, plan }, opts);
|
|
2229
2317
|
}
|
|
2230
2318
|
var cronli5_default = cronli5;
|
|
2231
2319
|
/**
|