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/lang/en.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// src/core/
|
|
1
|
+
// src/core/cadence.ts
|
|
2
2
|
function arithmeticStep(values) {
|
|
3
3
|
if (values.length < 5) {
|
|
4
4
|
return null;
|
|
@@ -14,31 +14,11 @@ function arithmeticStep(values) {
|
|
|
14
14
|
}
|
|
15
15
|
return { start: values[0], interval, last: values[values.length - 1] };
|
|
16
16
|
}
|
|
17
|
-
function
|
|
18
|
-
return
|
|
19
|
-
}
|
|
20
|
-
function orderWeekdaysForDisplay(segments) {
|
|
21
|
-
const flattened = segments.flatMap(function flat(segment) {
|
|
22
|
-
return segment.kind === "step" ? segment.fires.map(function single(value) {
|
|
23
|
-
return { kind: "single", value: "" + value };
|
|
24
|
-
}) : [segment];
|
|
25
|
-
});
|
|
26
|
-
function key(segment) {
|
|
27
|
-
return segment.kind === "range" ? weekdayDisplayKey(+segment.bounds[0]) : weekdayDisplayKey(+segment.value);
|
|
28
|
-
}
|
|
29
|
-
return flattened.map(function index(segment, position) {
|
|
30
|
-
return [segment, position];
|
|
31
|
-
}).sort(function byDisplayKey(a, b) {
|
|
32
|
-
return key(a[0]) - key(b[0]) || a[1] - b[1];
|
|
33
|
-
}).map(function unwrap(pair) {
|
|
34
|
-
return pair[0];
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
function segmentsOf(ir, field) {
|
|
38
|
-
return ir.analyses.segments[field] ?? [];
|
|
17
|
+
function segmentsOf(schedule, field) {
|
|
18
|
+
return schedule.analyses.segments[field] ?? [];
|
|
39
19
|
}
|
|
40
|
-
function stepSegment(
|
|
41
|
-
return segmentsOf(
|
|
20
|
+
function stepSegment(schedule, field) {
|
|
21
|
+
return segmentsOf(schedule, field)[0];
|
|
42
22
|
}
|
|
43
23
|
function singleValues(segments) {
|
|
44
24
|
const values = [];
|
|
@@ -53,6 +33,17 @@ function singleValues(segments) {
|
|
|
53
33
|
function offsetCleanStride(stride) {
|
|
54
34
|
return stride.start < stride.interval && 24 % stride.interval === 0;
|
|
55
35
|
}
|
|
36
|
+
function renderStride(spec, parts) {
|
|
37
|
+
const { start, interval, cycle } = spec;
|
|
38
|
+
const tiles = cycle % interval === 0;
|
|
39
|
+
if (start === 0 && tiles) {
|
|
40
|
+
return parts.bare();
|
|
41
|
+
}
|
|
42
|
+
if (start < interval && tiles) {
|
|
43
|
+
return parts.offset();
|
|
44
|
+
}
|
|
45
|
+
return parts.bounded();
|
|
46
|
+
}
|
|
56
47
|
function hourListStride(values) {
|
|
57
48
|
if (values.length < 2) {
|
|
58
49
|
return null;
|
|
@@ -72,6 +63,28 @@ function hourListStride(values) {
|
|
|
72
63
|
return { interval, last: values[values.length - 1], start: values[0] };
|
|
73
64
|
}
|
|
74
65
|
|
|
66
|
+
// src/core/weekday.ts
|
|
67
|
+
function weekdayDisplayKey(value) {
|
|
68
|
+
return value === 0 ? 7 : value;
|
|
69
|
+
}
|
|
70
|
+
function orderWeekdaysForDisplay(segments) {
|
|
71
|
+
const flattened = segments.flatMap(function flat(segment) {
|
|
72
|
+
return segment.kind === "step" ? segment.fires.map(function single(value) {
|
|
73
|
+
return { kind: "single", value: "" + value };
|
|
74
|
+
}) : [segment];
|
|
75
|
+
});
|
|
76
|
+
function key(segment) {
|
|
77
|
+
return segment.kind === "range" ? weekdayDisplayKey(+segment.bounds[0]) : weekdayDisplayKey(+segment.value);
|
|
78
|
+
}
|
|
79
|
+
return flattened.map(function index(segment, position) {
|
|
80
|
+
return [segment, position];
|
|
81
|
+
}).sort(function byDisplayKey(a, b) {
|
|
82
|
+
return key(a[0]) - key(b[0]) || a[1] - b[1];
|
|
83
|
+
}).map(function unwrap(pair) {
|
|
84
|
+
return pair[0];
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
|
|
75
88
|
// src/core/shapes.ts
|
|
76
89
|
function isOpenStep(field) {
|
|
77
90
|
return field.indexOf("/") !== -1 && field.indexOf("-") === -1 && field.indexOf(",") === -1;
|
|
@@ -209,72 +222,134 @@ function normalizeOptions(options) {
|
|
|
209
222
|
years: !!options.years
|
|
210
223
|
};
|
|
211
224
|
}
|
|
212
|
-
function describe(
|
|
213
|
-
const
|
|
214
|
-
|
|
215
|
-
|
|
225
|
+
function describe(schedule, opts) {
|
|
226
|
+
const dense = denseCadence(schedule, opts);
|
|
227
|
+
if (dense !== null) {
|
|
228
|
+
return applyYear(dense, schedule, opts);
|
|
229
|
+
}
|
|
230
|
+
const body = confinement(schedule, opts) ?? render(schedule, schedule.plan, opts);
|
|
231
|
+
const lead = isDayUnion(schedule, opts) ? dayUnionMonthLead(schedule, opts) : "";
|
|
232
|
+
return applyYear(lead + body, schedule, opts);
|
|
216
233
|
}
|
|
217
|
-
function render(
|
|
234
|
+
function render(schedule, plan, opts) {
|
|
218
235
|
const renderer = renderers[plan.kind];
|
|
219
|
-
return renderer(
|
|
236
|
+
return renderer(schedule, plan, opts);
|
|
220
237
|
}
|
|
221
|
-
function
|
|
222
|
-
return "
|
|
238
|
+
function isCadenceShape(shape) {
|
|
239
|
+
return shape === "step" || shape === "range" || shape === "list";
|
|
223
240
|
}
|
|
224
|
-
function
|
|
225
|
-
|
|
241
|
+
function isDenseCadence(schedule, opts) {
|
|
242
|
+
if (!opts.style.untilWindow || opts.short || schedule.plan.kind !== "composeSeconds" || schedule.plan.rest.kind === "clockTimes" || isDayUnion(schedule, opts)) {
|
|
243
|
+
return false;
|
|
244
|
+
}
|
|
245
|
+
const { shapes } = schedule;
|
|
246
|
+
return isCadenceShape(shapes.second) && isCadenceShape(shapes.minute) && isCadenceShape(shapes.hour);
|
|
226
247
|
}
|
|
227
|
-
function
|
|
228
|
-
const
|
|
229
|
-
|
|
248
|
+
function denseHourFragment(schedule, opts) {
|
|
249
|
+
const stride = hourStride(schedule);
|
|
250
|
+
if (stride) {
|
|
251
|
+
return hourStrideCadence(stride, opts);
|
|
252
|
+
}
|
|
253
|
+
if (schedule.shapes.hour === "range") {
|
|
254
|
+
const segment = segmentsOf(schedule, "hour").find(function range(part) {
|
|
255
|
+
return part.kind === "range";
|
|
256
|
+
});
|
|
257
|
+
return rangeWindow({
|
|
258
|
+
continuous: false,
|
|
259
|
+
from: +segment.bounds[0],
|
|
260
|
+
throughMinute: 0,
|
|
261
|
+
to: +segment.bounds[1]
|
|
262
|
+
}, opts);
|
|
263
|
+
}
|
|
264
|
+
return "during the " + hourSegmentTimes(schedule, { minute: 0, second: null }, false, opts) + " hours";
|
|
230
265
|
}
|
|
231
|
-
function
|
|
232
|
-
|
|
266
|
+
function denseMinuteFragment(schedule, opts) {
|
|
267
|
+
if (schedule.shapes.minute === "step") {
|
|
268
|
+
return stepCycle60(stepSegment(schedule, "minute"), "minute", "hour", opts);
|
|
269
|
+
}
|
|
270
|
+
if (schedule.shapes.minute === "range") {
|
|
271
|
+
return minuteRangeLead(schedule.pattern.minute, opts);
|
|
272
|
+
}
|
|
273
|
+
return strideFromSegments(
|
|
274
|
+
segmentsOf(schedule, "minute"),
|
|
275
|
+
"minute",
|
|
276
|
+
"hour",
|
|
277
|
+
opts
|
|
278
|
+
) ?? listPastThe(
|
|
279
|
+
segmentWords(segmentsOf(schedule, "minute"), opts),
|
|
280
|
+
"minute",
|
|
281
|
+
"hour",
|
|
282
|
+
opts
|
|
283
|
+
);
|
|
284
|
+
}
|
|
285
|
+
function denseCadence(schedule, opts) {
|
|
286
|
+
if (!isDenseCadence(schedule, opts)) {
|
|
287
|
+
return null;
|
|
288
|
+
}
|
|
289
|
+
const hour = denseHourFragment(schedule, opts);
|
|
290
|
+
const minute = denseMinuteFragment(schedule, opts);
|
|
291
|
+
const second = secondsClause(schedule, "minute", opts);
|
|
292
|
+
const nested = hour + ", " + minute + ", and within each of those minutes, " + second;
|
|
293
|
+
const anchor = trailingQualifier(schedule, opts).trim();
|
|
294
|
+
return anchor ? anchor + ", " + nested : nested;
|
|
295
|
+
}
|
|
296
|
+
function renderEverySecond(schedule, plan, opts) {
|
|
297
|
+
return "every second" + trailingQualifier(schedule, opts);
|
|
298
|
+
}
|
|
299
|
+
function renderStandaloneSeconds(schedule, plan, opts) {
|
|
300
|
+
return secondsLeadClause(schedule, opts) + trailingQualifier(schedule, opts);
|
|
301
|
+
}
|
|
302
|
+
function renderSecondPastMinute(schedule, plan, opts) {
|
|
303
|
+
const secondField = schedule.pattern.second;
|
|
304
|
+
return getNumber(secondField, opts) + " " + pluralize(secondField, "second") + " past the minute, every minute" + trailingQualifier(schedule, opts);
|
|
305
|
+
}
|
|
306
|
+
function renderSecondsWithinMinute(schedule, plan, opts) {
|
|
307
|
+
const minuteField = schedule.pattern.minute;
|
|
233
308
|
const minuteWord = getNumber(minuteField, opts);
|
|
234
309
|
const minuteUnit = pluralize(minuteField, "minute");
|
|
235
310
|
if (plan.singleSecond) {
|
|
236
|
-
const secondField =
|
|
237
|
-
return minuteWord + " " + minuteUnit + " and " + getNumber(secondField, opts) + " " + pluralize(secondField, "second") + " past the hour, every hour" + trailingQualifier(
|
|
311
|
+
const secondField = schedule.pattern.second;
|
|
312
|
+
return minuteWord + " " + minuteUnit + " and " + getNumber(secondField, opts) + " " + pluralize(secondField, "second") + " past the hour, every hour" + trailingQualifier(schedule, opts);
|
|
238
313
|
}
|
|
239
|
-
return secondsLeadClause(
|
|
314
|
+
return secondsLeadClause(schedule, opts) + ", " + minuteWord + " " + minuteUnit + " past the hour, every hour" + trailingQualifier(schedule, opts);
|
|
240
315
|
}
|
|
241
|
-
function composeHourCadence(
|
|
316
|
+
function composeHourCadence(schedule, plan, opts) {
|
|
242
317
|
const clockRest = plan.rest.kind === "clockTimes" || plan.rest.kind === "compactClockTimes";
|
|
243
|
-
if (!clockRest ||
|
|
318
|
+
if (!clockRest || schedule.shapes.minute !== "single") {
|
|
244
319
|
return null;
|
|
245
320
|
}
|
|
246
|
-
const minute = +
|
|
247
|
-
return hourCadence(
|
|
321
|
+
const minute = +schedule.pattern.minute;
|
|
322
|
+
return hourCadence(schedule, minute, opts) ?? hourRangeCadence(schedule, minute, opts);
|
|
248
323
|
}
|
|
249
|
-
function clockTimesConfinement(
|
|
250
|
-
if (+rest.times[0].minute === 0 &&
|
|
251
|
-
return secondsLeadClause(
|
|
324
|
+
function clockTimesConfinement(schedule, rest, opts) {
|
|
325
|
+
if (+rest.times[0].minute === 0 && schedule.shapes.minute === "single") {
|
|
326
|
+
return secondsLeadClause(schedule, opts) + " for one minute at " + durationHours(schedule, rest, opts);
|
|
252
327
|
}
|
|
253
|
-
return secondsLeadClause(
|
|
328
|
+
return secondsLeadClause(schedule, opts) + " of " + clockTimesOf(schedule, rest, opts);
|
|
254
329
|
}
|
|
255
|
-
function renderComposeSeconds(
|
|
256
|
-
const cadence = composeHourCadence(
|
|
330
|
+
function renderComposeSeconds(schedule, plan, opts) {
|
|
331
|
+
const cadence = composeHourCadence(schedule, plan, opts);
|
|
257
332
|
if (cadence !== null) {
|
|
258
333
|
return cadence;
|
|
259
334
|
}
|
|
260
|
-
if (plan.rest.kind === "clockTimes" && (
|
|
261
|
-
return clockTimesConfinement(
|
|
335
|
+
if (plan.rest.kind === "clockTimes" && (schedule.shapes.second === "wildcard" || schedule.shapes.second === "step")) {
|
|
336
|
+
return clockTimesConfinement(schedule, plan.rest, opts);
|
|
262
337
|
}
|
|
263
|
-
if (
|
|
264
|
-
return "every second of every other minute" + trailingQualifier(
|
|
338
|
+
if (schedule.shapes.second === "wildcard" && plan.rest.kind === "minuteFrequency" && plan.rest.hours.kind === "none" && schedule.pattern.minute === "*/2") {
|
|
339
|
+
return "every second of every other minute" + trailingQualifier(schedule, opts);
|
|
265
340
|
}
|
|
266
|
-
const restOwnsLead = plan.rest.kind === "compactClockTimes" &&
|
|
267
|
-
const lead = restOwnsLead ? "" : secondsLeadClause(
|
|
268
|
-
return lead + render(
|
|
341
|
+
const restOwnsLead = plan.rest.kind === "compactClockTimes" && schedule.analyses.clockSecond;
|
|
342
|
+
const lead = restOwnsLead ? "" : secondsLeadClause(schedule, opts) + ", ";
|
|
343
|
+
return lead + render(schedule, plan.rest, opts);
|
|
269
344
|
}
|
|
270
|
-
function durationHours(
|
|
345
|
+
function durationHours(schedule, plan, opts) {
|
|
271
346
|
const hours = plan.times.map(function clock(time) {
|
|
272
347
|
return getTime({ hour: time.hour, minute: 0 }, opts);
|
|
273
348
|
});
|
|
274
|
-
const trail = dayQualifier(
|
|
349
|
+
const trail = dayQualifier(schedule, leadingWords, opts);
|
|
275
350
|
return joinList(hours, opts) + (trail && ", " + trail);
|
|
276
351
|
}
|
|
277
|
-
function clockTimesOf(
|
|
352
|
+
function clockTimesOf(schedule, plan, opts) {
|
|
278
353
|
const times = plan.times.map(function clock(time) {
|
|
279
354
|
return getTime({
|
|
280
355
|
hour: time.hour,
|
|
@@ -283,21 +358,21 @@ function clockTimesOf(ir, plan, opts) {
|
|
|
283
358
|
explicit: true
|
|
284
359
|
}, opts);
|
|
285
360
|
});
|
|
286
|
-
const trail = dayQualifier(
|
|
361
|
+
const trail = dayQualifier(schedule, leadingWords, opts);
|
|
287
362
|
return joinList(times, opts) + (trail && ", " + trail);
|
|
288
363
|
}
|
|
289
|
-
function secondsLeadClause(
|
|
290
|
-
return secondsClause(
|
|
364
|
+
function secondsLeadClause(schedule, opts) {
|
|
365
|
+
return secondsClause(schedule, "minute", opts);
|
|
291
366
|
}
|
|
292
|
-
function secondsClause(
|
|
293
|
-
const secondField =
|
|
294
|
-
const shape =
|
|
367
|
+
function secondsClause(schedule, anchor, opts) {
|
|
368
|
+
const secondField = schedule.pattern.second;
|
|
369
|
+
const shape = schedule.shapes.second;
|
|
295
370
|
if (secondField === "*") {
|
|
296
371
|
return "every second";
|
|
297
372
|
}
|
|
298
373
|
if (shape === "step") {
|
|
299
374
|
return stepCycle60(
|
|
300
|
-
stepSegment(
|
|
375
|
+
stepSegment(schedule, "second"),
|
|
301
376
|
"second",
|
|
302
377
|
anchor,
|
|
303
378
|
opts
|
|
@@ -312,44 +387,44 @@ function secondsClause(ir, anchor, opts) {
|
|
|
312
387
|
return "at " + getNumber(secondField, opts) + " " + pluralize(secondField, "second") + " past the " + anchor;
|
|
313
388
|
}
|
|
314
389
|
return strideFromSegments(
|
|
315
|
-
segmentsOf(
|
|
390
|
+
segmentsOf(schedule, "second"),
|
|
316
391
|
"second",
|
|
317
392
|
anchor,
|
|
318
393
|
opts
|
|
319
394
|
) ?? listPastThe(
|
|
320
|
-
segmentWords(segmentsOf(
|
|
395
|
+
segmentWords(segmentsOf(schedule, "second"), opts),
|
|
321
396
|
"second",
|
|
322
397
|
anchor,
|
|
323
398
|
opts
|
|
324
399
|
);
|
|
325
400
|
}
|
|
326
|
-
function renderEveryMinute(
|
|
327
|
-
return "every minute" + trailingQualifier(
|
|
401
|
+
function renderEveryMinute(schedule, plan, opts) {
|
|
402
|
+
return "every minute" + trailingQualifier(schedule, opts);
|
|
328
403
|
}
|
|
329
|
-
function renderSingleMinute(
|
|
330
|
-
const minuteField =
|
|
331
|
-
return getNumber(minuteField, opts) + " " + pluralize(minuteField, "minute") + " past the hour, every hour" + trailingQualifier(
|
|
404
|
+
function renderSingleMinute(schedule, plan, opts) {
|
|
405
|
+
const minuteField = schedule.pattern.minute;
|
|
406
|
+
return getNumber(minuteField, opts) + " " + pluralize(minuteField, "minute") + " past the hour, every hour" + trailingQualifier(schedule, opts);
|
|
332
407
|
}
|
|
333
|
-
function renderRangeOfMinutes(
|
|
334
|
-
return minuteRangeLead(
|
|
408
|
+
function renderRangeOfMinutes(schedule, plan, opts) {
|
|
409
|
+
return minuteRangeLead(schedule.pattern.minute, opts) + trailingQualifier(schedule, opts);
|
|
335
410
|
}
|
|
336
|
-
function renderMultipleMinutes(
|
|
337
|
-
const stride = strideFromSegments(segmentsOf(
|
|
411
|
+
function renderMultipleMinutes(schedule, plan, opts) {
|
|
412
|
+
const stride = strideFromSegments(segmentsOf(schedule, "minute"), "minute", "hour", opts);
|
|
338
413
|
return (stride ?? listPastThe(segmentWords(
|
|
339
|
-
segmentsOf(
|
|
414
|
+
segmentsOf(schedule, "minute"),
|
|
340
415
|
opts
|
|
341
|
-
), "minute", "hour", opts)) + trailingQualifier(
|
|
416
|
+
), "minute", "hour", opts)) + trailingQualifier(schedule, opts);
|
|
342
417
|
}
|
|
343
|
-
function renderMinuteFrequency(
|
|
418
|
+
function renderMinuteFrequency(schedule, plan, opts) {
|
|
344
419
|
let phrase = stepCycle60(
|
|
345
|
-
stepSegment(
|
|
420
|
+
stepSegment(schedule, "minute"),
|
|
346
421
|
"minute",
|
|
347
422
|
"hour",
|
|
348
423
|
opts
|
|
349
424
|
);
|
|
350
425
|
if (plan.hours.kind === "during") {
|
|
351
|
-
const cadence = unevenHourCadence(
|
|
352
|
-
phrase += cadence ? ", " + cadence : " during the " + hourTimesFromPlan(
|
|
426
|
+
const cadence = unevenHourCadence(schedule, opts);
|
|
427
|
+
phrase += cadence ? ", " + cadence : " during the " + hourTimesFromPlan(schedule, plan.hours.times, false, opts) + " hours";
|
|
353
428
|
} else if (plan.hours.kind === "window") {
|
|
354
429
|
phrase += " " + rangeWindow({
|
|
355
430
|
continuous: false,
|
|
@@ -358,45 +433,50 @@ function renderMinuteFrequency(ir, plan, opts) {
|
|
|
358
433
|
to: plan.hours.to
|
|
359
434
|
}, opts);
|
|
360
435
|
} else if (plan.hours.kind === "step") {
|
|
361
|
-
phrase += " " + everyNthHour(stepSegment(
|
|
436
|
+
phrase += " " + everyNthHour(stepSegment(schedule, "hour"), opts);
|
|
362
437
|
}
|
|
363
|
-
return phrase + trailingQualifier(
|
|
438
|
+
return phrase + trailingQualifier(schedule, opts);
|
|
364
439
|
}
|
|
365
|
-
function renderMinuteSpanInHour(
|
|
366
|
-
if (
|
|
367
|
-
return "every minute of the " + getTime({ hour: plan.hour, minute: 0 }, opts) + " hour" + trailingQualifier(
|
|
440
|
+
function renderMinuteSpanInHour(schedule, plan, opts) {
|
|
441
|
+
if (schedule.pattern.minute === "*") {
|
|
442
|
+
return "every minute of the " + getTime({ hour: plan.hour, minute: 0 }, opts) + " hour" + trailingQualifier(schedule, opts);
|
|
368
443
|
}
|
|
369
|
-
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(
|
|
444
|
+
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);
|
|
370
445
|
}
|
|
371
|
-
function renderMinutesAcrossHours(
|
|
372
|
-
const cadence = unevenHourCadence(
|
|
446
|
+
function renderMinutesAcrossHours(schedule, plan, opts) {
|
|
447
|
+
const cadence = unevenHourCadence(schedule, opts);
|
|
373
448
|
if (plan.form === "wildcard") {
|
|
374
449
|
if (cadence !== null) {
|
|
375
|
-
return "every minute, " + cadence + trailingQualifier(
|
|
450
|
+
return "every minute, " + cadence + trailingQualifier(schedule, opts);
|
|
376
451
|
}
|
|
377
|
-
return "every minute during the " + hourTimesFromPlan(
|
|
452
|
+
return "every minute during the " + hourTimesFromPlan(schedule, plan.times, false, opts) + " hours" + trailingQualifier(schedule, opts);
|
|
378
453
|
}
|
|
379
454
|
if (plan.form === "range") {
|
|
380
|
-
const lead2 = minuteRangeLead(
|
|
455
|
+
const lead2 = minuteRangeLead(schedule.pattern.minute, opts);
|
|
381
456
|
if (cadence !== null) {
|
|
382
|
-
return lead2 + ", " + cadence + trailingQualifier(
|
|
457
|
+
return lead2 + ", " + cadence + trailingQualifier(schedule, opts);
|
|
383
458
|
}
|
|
384
459
|
if (singleHourFire(plan.times)) {
|
|
385
|
-
return lead2 + ", at " + hourTimesFromPlan(
|
|
460
|
+
return lead2 + ", at " + hourTimesFromPlan(schedule, plan.times, true, opts) + trailingQualifier(schedule, opts);
|
|
386
461
|
}
|
|
387
|
-
return lead2 + " during the " + hourTimesFromPlan(
|
|
462
|
+
return lead2 + " during the " + hourTimesFromPlan(schedule, plan.times, false, opts) + " hours" + trailingQualifier(schedule, opts);
|
|
388
463
|
}
|
|
389
|
-
const lead = strideFromSegments(
|
|
390
|
-
|
|
464
|
+
const lead = strideFromSegments(
|
|
465
|
+
segmentsOf(schedule, "minute"),
|
|
466
|
+
"minute",
|
|
467
|
+
"hour",
|
|
468
|
+
opts
|
|
469
|
+
) ?? listPastThe(
|
|
470
|
+
segmentWords(segmentsOf(schedule, "minute"), opts),
|
|
391
471
|
"minute",
|
|
392
472
|
"hour",
|
|
393
473
|
opts
|
|
394
474
|
);
|
|
395
475
|
if (cadence !== null) {
|
|
396
|
-
return lead + ", " + cadence + trailingQualifier(
|
|
476
|
+
return lead + ", " + cadence + trailingQualifier(schedule, opts);
|
|
397
477
|
}
|
|
398
|
-
const times = hourTimesFromPlan(
|
|
399
|
-
return lead + ", at " + times + trailingQualifier(
|
|
478
|
+
const times = hourTimesFromPlan(schedule, plan.times, true, opts);
|
|
479
|
+
return lead + ", at " + times + trailingQualifier(schedule, opts);
|
|
400
480
|
}
|
|
401
481
|
var stepOrdinals = {
|
|
402
482
|
2: "other",
|
|
@@ -411,60 +491,65 @@ function everyNthHour(segment, opts) {
|
|
|
411
491
|
const start = segment.startToken === "*" ? 0 : +segment.startToken;
|
|
412
492
|
return start === 0 ? base : base + " starting at " + getTime({ hour: start, minute: 0 }, opts);
|
|
413
493
|
}
|
|
414
|
-
function renderMinuteSpanAcrossHourStep(
|
|
415
|
-
const segment = stepSegment(
|
|
494
|
+
function renderMinuteSpanAcrossHourStep(schedule, plan, opts) {
|
|
495
|
+
const segment = stepSegment(schedule, "hour");
|
|
416
496
|
if (plan.form === "wildcard") {
|
|
417
|
-
return "every minute " + everyNthHour(segment, opts) + trailingQualifier(
|
|
497
|
+
return "every minute " + everyNthHour(segment, opts) + trailingQualifier(schedule, opts);
|
|
418
498
|
}
|
|
419
|
-
const lead = plan.form === "list" ? strideFromSegments(
|
|
420
|
-
|
|
499
|
+
const lead = plan.form === "list" ? strideFromSegments(
|
|
500
|
+
segmentsOf(schedule, "minute"),
|
|
421
501
|
"minute",
|
|
422
502
|
"hour",
|
|
423
503
|
opts
|
|
424
|
-
)
|
|
425
|
-
|
|
426
|
-
|
|
504
|
+
) ?? listPastThe(
|
|
505
|
+
segmentWords(segmentsOf(schedule, "minute"), opts),
|
|
506
|
+
"minute",
|
|
507
|
+
"hour",
|
|
508
|
+
opts
|
|
509
|
+
) : minuteRangeLead(schedule.pattern.minute, opts);
|
|
510
|
+
const cadence = unevenHourCadence(schedule, opts);
|
|
511
|
+
return lead + ", " + (cadence ?? stepHours(segment, opts)) + trailingQualifier(schedule, opts);
|
|
427
512
|
}
|
|
428
513
|
function minuteRangeLead(minuteField, opts) {
|
|
429
514
|
const bounds = minuteField.split("-");
|
|
430
515
|
const num = seriesNumber();
|
|
431
516
|
return "every minute from " + num(bounds[0]) + through(opts) + num(bounds[1]) + " past the hour";
|
|
432
517
|
}
|
|
433
|
-
function renderEveryHour(
|
|
434
|
-
return "every hour" + trailingQualifier(
|
|
518
|
+
function renderEveryHour(schedule, plan, opts) {
|
|
519
|
+
return "every hour" + trailingQualifier(schedule, opts);
|
|
435
520
|
}
|
|
436
|
-
function renderHourRange(
|
|
521
|
+
function renderHourRange(schedule, plan, opts) {
|
|
437
522
|
const window = hourWindow(boundedWindow(plan), opts);
|
|
438
523
|
if (plan.minuteForm === "wildcard") {
|
|
439
|
-
return "every minute " + window + trailingQualifier(
|
|
524
|
+
return "every minute " + window + trailingQualifier(schedule, opts);
|
|
440
525
|
}
|
|
441
526
|
if (plan.minuteForm === "range") {
|
|
442
|
-
return minuteRangeLead(
|
|
527
|
+
return minuteRangeLead(schedule.pattern.minute, opts) + ", " + window + trailingQualifier(schedule, opts);
|
|
443
528
|
}
|
|
444
|
-
return rangeMinuteLead(
|
|
529
|
+
return rangeMinuteLead(schedule, opts) + " " + window + trailingQualifier(schedule, opts);
|
|
445
530
|
}
|
|
446
|
-
function rangeMinuteLead(
|
|
447
|
-
if (
|
|
531
|
+
function rangeMinuteLead(schedule, opts) {
|
|
532
|
+
if (schedule.pattern.minute === "0") {
|
|
448
533
|
return "every hour";
|
|
449
534
|
}
|
|
450
535
|
return strideFromSegments(
|
|
451
|
-
segmentsOf(
|
|
536
|
+
segmentsOf(schedule, "minute"),
|
|
452
537
|
"minute",
|
|
453
538
|
"hour",
|
|
454
539
|
opts
|
|
455
540
|
) ?? listPastThe(
|
|
456
|
-
segmentWords(segmentsOf(
|
|
541
|
+
segmentWords(segmentsOf(schedule, "minute"), opts),
|
|
457
542
|
"minute",
|
|
458
543
|
"hour",
|
|
459
544
|
opts
|
|
460
545
|
);
|
|
461
546
|
}
|
|
462
|
-
function renderHourStep(
|
|
463
|
-
const cadence = unevenHourCadence(
|
|
547
|
+
function renderHourStep(schedule, plan, opts) {
|
|
548
|
+
const cadence = unevenHourCadence(schedule, opts);
|
|
464
549
|
if (cadence !== null) {
|
|
465
|
-
return cadence + trailingQualifier(
|
|
550
|
+
return cadence + trailingQualifier(schedule, opts);
|
|
466
551
|
}
|
|
467
|
-
return stepHours(stepSegment(
|
|
552
|
+
return stepHours(stepSegment(schedule, "hour"), opts) + trailingQualifier(schedule, opts);
|
|
468
553
|
}
|
|
469
554
|
function boundedWindow(plan) {
|
|
470
555
|
const continuous = plan.minuteForm === "wildcard";
|
|
@@ -487,10 +572,10 @@ function hourWindow(window, opts) {
|
|
|
487
572
|
to: window.to
|
|
488
573
|
}, opts);
|
|
489
574
|
}
|
|
490
|
-
function renderClockTimes(
|
|
491
|
-
if (
|
|
492
|
-
const minute = +
|
|
493
|
-
const cadence = hourCadence(
|
|
575
|
+
function renderClockTimes(schedule, plan, opts) {
|
|
576
|
+
if (schedule.shapes.minute === "single") {
|
|
577
|
+
const minute = +schedule.pattern.minute;
|
|
578
|
+
const cadence = hourCadence(schedule, minute, opts) ?? hourRangeCadence(schedule, minute, opts);
|
|
494
579
|
if (cadence !== null) {
|
|
495
580
|
return cadence;
|
|
496
581
|
}
|
|
@@ -504,47 +589,52 @@ function renderClockTimes(ir, plan, opts) {
|
|
|
504
589
|
plain
|
|
505
590
|
}, opts);
|
|
506
591
|
});
|
|
507
|
-
return interpretDayQualifier(
|
|
592
|
+
return interpretDayQualifier(schedule, opts) + "at " + joinList(times, opts) + dayUnionTrail(schedule, opts);
|
|
508
593
|
}
|
|
509
|
-
function dayUnionTrail(
|
|
510
|
-
return isDayUnion(
|
|
594
|
+
function dayUnionTrail(schedule, opts) {
|
|
595
|
+
return isDayUnion(schedule, opts) ? dayUnionCondition(schedule, opts) : "";
|
|
511
596
|
}
|
|
512
|
-
function renderCompactClockTimes(
|
|
597
|
+
function renderCompactClockTimes(schedule, plan, opts) {
|
|
513
598
|
if (plan.fold) {
|
|
514
|
-
const cadence2 = hourCadence(
|
|
599
|
+
const cadence2 = hourCadence(schedule, +plan.minute, opts) ?? hourRangeCadence(schedule, +plan.minute, opts);
|
|
515
600
|
if (cadence2 !== null) {
|
|
516
601
|
return cadence2;
|
|
517
602
|
}
|
|
518
|
-
const hasRange = segmentsOf(
|
|
603
|
+
const hasRange = segmentsOf(schedule, "hour").some(function range(segment) {
|
|
519
604
|
return segment.kind === "range";
|
|
520
605
|
});
|
|
521
|
-
if (hasRange && !
|
|
522
|
-
return foldedHourWindows(
|
|
606
|
+
if (hasRange && !schedule.analyses.clockSecond) {
|
|
607
|
+
return foldedHourWindows(schedule, plan, opts) + trailingQualifier(schedule, opts);
|
|
523
608
|
}
|
|
524
|
-
const fold = { minute: plan.minute, second:
|
|
525
|
-
return interpretDayQualifier(
|
|
609
|
+
const fold = { minute: plan.minute, second: schedule.analyses.clockSecond };
|
|
610
|
+
return interpretDayQualifier(schedule, opts) + "at " + hourSegmentTimes(schedule, fold, true, opts) + dayUnionTrail(schedule, opts);
|
|
526
611
|
}
|
|
527
612
|
const minuteLead = (
|
|
528
613
|
// The non-fold branch is a minute list, which has segments. An
|
|
529
614
|
// offset/uneven step enumerated to that list reads as a stride.
|
|
530
|
-
strideFromSegments(
|
|
531
|
-
|
|
615
|
+
strideFromSegments(
|
|
616
|
+
segmentsOf(schedule, "minute"),
|
|
617
|
+
"minute",
|
|
618
|
+
"hour",
|
|
619
|
+
opts
|
|
620
|
+
) ?? listPastThe(
|
|
621
|
+
segmentWords(segmentsOf(schedule, "minute"), opts),
|
|
532
622
|
"minute",
|
|
533
623
|
"hour",
|
|
534
624
|
opts
|
|
535
625
|
)
|
|
536
626
|
);
|
|
537
|
-
const cadence = unevenHourCadence(
|
|
538
|
-
const phrase = cadence ? minuteLead + ", " + cadence + trailingQualifier(
|
|
539
|
-
return
|
|
627
|
+
const cadence = unevenHourCadence(schedule, opts);
|
|
628
|
+
const phrase = cadence ? minuteLead + ", " + cadence + trailingQualifier(schedule, opts) : minuteLead + ", at " + hourSegmentTimes(schedule, { minute: 0, second: null }, true, opts) + trailingQualifier(schedule, opts);
|
|
629
|
+
return schedule.analyses.clockSecond ? secondsLeadClause(schedule, opts) + ", " + phrase : phrase;
|
|
540
630
|
}
|
|
541
|
-
function foldedHourWindows(
|
|
631
|
+
function foldedHourWindows(schedule, plan, opts) {
|
|
542
632
|
const minute = plan.minute;
|
|
543
633
|
const windows = [];
|
|
544
|
-
const times = collectHourOutliers(
|
|
634
|
+
const times = collectHourOutliers(schedule).map(function time(hour) {
|
|
545
635
|
return getTime({ hour, minute }, opts);
|
|
546
636
|
});
|
|
547
|
-
segmentsOf(
|
|
637
|
+
segmentsOf(schedule, "hour").forEach(function classify(segment) {
|
|
548
638
|
if (segment.kind === "range") {
|
|
549
639
|
windows.push(rangeWindow({
|
|
550
640
|
continuous: false,
|
|
@@ -554,12 +644,12 @@ function foldedHourWindows(ir, plan, opts) {
|
|
|
554
644
|
}, opts));
|
|
555
645
|
}
|
|
556
646
|
});
|
|
557
|
-
const phrase = rangeMinuteLead(
|
|
647
|
+
const phrase = rangeMinuteLead(schedule, opts) + " " + joinList(windows, opts);
|
|
558
648
|
return phrase + outlierTail(times, opts);
|
|
559
649
|
}
|
|
560
|
-
function collectHourOutliers(
|
|
650
|
+
function collectHourOutliers(schedule) {
|
|
561
651
|
const hours = [];
|
|
562
|
-
segmentsOf(
|
|
652
|
+
segmentsOf(schedule, "hour").forEach(function classify(segment) {
|
|
563
653
|
if (segment.kind === "step") {
|
|
564
654
|
hours.push(...segment.fires);
|
|
565
655
|
} else if (segment.kind !== "range") {
|
|
@@ -577,16 +667,16 @@ function outlierTail(times, opts) {
|
|
|
577
667
|
function isCadenceField(token) {
|
|
578
668
|
return token === "*" || token.startsWith("*/") && token.indexOf("-") === -1;
|
|
579
669
|
}
|
|
580
|
-
function leadingCadence(
|
|
581
|
-
const { second, minute } =
|
|
670
|
+
function leadingCadence(schedule, opts) {
|
|
671
|
+
const { second, minute } = schedule.pattern;
|
|
582
672
|
if (isCadenceField(second)) {
|
|
583
|
-
return { secondLead: true, text: secondsClause(
|
|
673
|
+
return { secondLead: true, text: secondsClause(schedule, "minute", opts) };
|
|
584
674
|
}
|
|
585
675
|
if (second === "0" && isCadenceField(minute)) {
|
|
586
676
|
const text = minute === "*" ? "every minute" : (
|
|
587
677
|
// A clean minute step's first segment is a step segment.
|
|
588
678
|
stepCycle60(
|
|
589
|
-
stepSegment(
|
|
679
|
+
stepSegment(schedule, "minute"),
|
|
590
680
|
"minute",
|
|
591
681
|
"hour",
|
|
592
682
|
opts
|
|
@@ -596,19 +686,19 @@ function leadingCadence(ir, opts) {
|
|
|
596
686
|
}
|
|
597
687
|
return null;
|
|
598
688
|
}
|
|
599
|
-
function minuteConfinement(
|
|
600
|
-
const minute =
|
|
689
|
+
function minuteConfinement(schedule, opts) {
|
|
690
|
+
const minute = schedule.pattern.minute;
|
|
601
691
|
if (minute === "*") {
|
|
602
692
|
return "";
|
|
603
693
|
}
|
|
604
694
|
if (isCadenceField(minute)) {
|
|
605
695
|
return " of every other minute";
|
|
606
696
|
}
|
|
607
|
-
const segments = segmentsOf(
|
|
608
|
-
if (
|
|
697
|
+
const segments = segmentsOf(schedule, "minute");
|
|
698
|
+
if (schedule.shapes.minute === "single") {
|
|
609
699
|
return " during minute :" + pad(minute);
|
|
610
700
|
}
|
|
611
|
-
if (
|
|
701
|
+
if (schedule.shapes.minute === "range") {
|
|
612
702
|
const bounds = minute.split("-");
|
|
613
703
|
return " during minutes :" + pad(bounds[0]) + through(opts) + ":" + pad(bounds[1]);
|
|
614
704
|
}
|
|
@@ -617,64 +707,61 @@ function minuteConfinement(ir, opts) {
|
|
|
617
707
|
});
|
|
618
708
|
return " during minutes " + joinList(values, opts);
|
|
619
709
|
}
|
|
620
|
-
function hourConfinement(
|
|
621
|
-
const hour =
|
|
710
|
+
function hourConfinement(schedule, opts) {
|
|
711
|
+
const hour = schedule.pattern.hour;
|
|
622
712
|
if (hour === "*") {
|
|
623
|
-
const minutePinned =
|
|
713
|
+
const minutePinned = schedule.pattern.minute !== "*" && !isCadenceField(schedule.pattern.minute);
|
|
624
714
|
return minutePinned ? " of every hour" : "";
|
|
625
715
|
}
|
|
626
716
|
if (isCadenceField(hour)) {
|
|
627
717
|
return hour === "*/2" ? " of every other hour" : "";
|
|
628
718
|
}
|
|
629
|
-
if (
|
|
719
|
+
if (schedule.shapes.hour === "single") {
|
|
630
720
|
const h = +hour;
|
|
631
|
-
if (
|
|
721
|
+
if (schedule.shapes.minute === "step") {
|
|
632
722
|
return " from " + getTime({ hour: h, minute: 0 }, opts) + " until " + getTime({ hour: (h + 1) % 24, minute: 0 }, opts);
|
|
633
723
|
}
|
|
634
|
-
if (
|
|
724
|
+
if (schedule.pattern.minute !== "*" && !isCadenceField(schedule.pattern.minute)) {
|
|
635
725
|
return " at " + getTime({ hour: h, minute: 0 }, opts);
|
|
636
726
|
}
|
|
637
727
|
return " of the " + getTime({ hour: h, minute: 0 }, opts) + " hour";
|
|
638
728
|
}
|
|
639
|
-
if (
|
|
729
|
+
if (schedule.shapes.hour === "range") {
|
|
640
730
|
const bounds = hour.split("-");
|
|
641
731
|
return " " + rangeWindow({
|
|
642
|
-
continuous:
|
|
732
|
+
continuous: schedule.pattern.minute === "*",
|
|
643
733
|
from: +bounds[0],
|
|
644
734
|
throughMinute: 0,
|
|
645
735
|
to: +bounds[1]
|
|
646
736
|
}, opts);
|
|
647
737
|
}
|
|
648
|
-
return " during the " + hourSegmentTimes(
|
|
649
|
-
}
|
|
650
|
-
function isContiguousHourRange(ir) {
|
|
651
|
-
return ir.shapes.hour === "range";
|
|
738
|
+
return " during the " + hourSegmentTimes(schedule, { minute: 0, second: null }, false, opts) + " hours";
|
|
652
739
|
}
|
|
653
|
-
function confinableHour(
|
|
654
|
-
if (
|
|
740
|
+
function confinableHour(schedule) {
|
|
741
|
+
if (schedule.shapes.hour !== "step") {
|
|
655
742
|
return true;
|
|
656
743
|
}
|
|
657
|
-
const segment = stepSegment(
|
|
658
|
-
return
|
|
744
|
+
const segment = stepSegment(schedule, "hour");
|
|
745
|
+
return schedule.pattern.hour === "*/2" || segment.startToken.indexOf("-") !== -1;
|
|
659
746
|
}
|
|
660
|
-
function isMinuteStride(
|
|
661
|
-
if (
|
|
747
|
+
function isMinuteStride(schedule) {
|
|
748
|
+
if (schedule.shapes.minute !== "list") {
|
|
662
749
|
return false;
|
|
663
750
|
}
|
|
664
|
-
const values = singleValues(segmentsOf(
|
|
751
|
+
const values = singleValues(segmentsOf(schedule, "minute"));
|
|
665
752
|
return values !== null && arithmeticStep(values) !== null;
|
|
666
753
|
}
|
|
667
|
-
function confinementEligible(
|
|
668
|
-
const { minute, hour } =
|
|
754
|
+
function confinementEligible(schedule, lead) {
|
|
755
|
+
const { minute, hour } = schedule.pattern;
|
|
669
756
|
const minuteStep = isCadenceField(minute) && minute !== "*";
|
|
670
|
-
if (!confinableHour(
|
|
757
|
+
if (!confinableHour(schedule)) {
|
|
671
758
|
return false;
|
|
672
759
|
}
|
|
673
760
|
if (lead.secondLead) {
|
|
674
761
|
if (minuteStep) {
|
|
675
|
-
return minute === "*/2" &&
|
|
762
|
+
return minute === "*/2" && schedule.shapes.hour !== "range";
|
|
676
763
|
}
|
|
677
|
-
if (isMinuteStride(
|
|
764
|
+
if (isMinuteStride(schedule) || schedule.shapes.minute === "list" && schedule.shapes.hour === "list") {
|
|
678
765
|
return false;
|
|
679
766
|
}
|
|
680
767
|
return true;
|
|
@@ -682,21 +769,21 @@ function confinementEligible(ir, lead) {
|
|
|
682
769
|
if (hour === "*/2") {
|
|
683
770
|
return true;
|
|
684
771
|
}
|
|
685
|
-
return
|
|
772
|
+
return schedule.shapes.hour === "single" && minute === "*/2";
|
|
686
773
|
}
|
|
687
|
-
function confinement(
|
|
774
|
+
function confinement(schedule, opts) {
|
|
688
775
|
if (!opts.style.untilWindow || opts.short) {
|
|
689
776
|
return null;
|
|
690
777
|
}
|
|
691
|
-
if (
|
|
778
|
+
if (schedule.pattern.minute === "*" && schedule.pattern.hour === "*") {
|
|
692
779
|
return null;
|
|
693
780
|
}
|
|
694
|
-
const lead = leadingCadence(
|
|
695
|
-
if (!lead || !confinementEligible(
|
|
781
|
+
const lead = leadingCadence(schedule, opts);
|
|
782
|
+
if (!lead || !confinementEligible(schedule, lead)) {
|
|
696
783
|
return null;
|
|
697
784
|
}
|
|
698
|
-
const minutePart = lead.secondLead ? minuteConfinement(
|
|
699
|
-
return lead.text + minutePart + hourConfinement(
|
|
785
|
+
const minutePart = lead.secondLead ? minuteConfinement(schedule, opts) : "";
|
|
786
|
+
return lead.text + minutePart + hourConfinement(schedule, opts) + trailingQualifier(schedule, opts);
|
|
700
787
|
}
|
|
701
788
|
var renderers = {
|
|
702
789
|
clockTimes: renderClockTimes,
|
|
@@ -718,23 +805,25 @@ var renderers = {
|
|
|
718
805
|
singleMinute: renderSingleMinute,
|
|
719
806
|
standaloneSeconds: renderStandaloneSeconds
|
|
720
807
|
};
|
|
721
|
-
function
|
|
808
|
+
function renderStride2(stride, opts) {
|
|
722
809
|
const { interval, start, last, cycle, unit, anchor } = stride;
|
|
723
810
|
const cadence = "every " + getNumber(interval, opts) + " " + unit + "s";
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
811
|
+
return renderStride({ start, interval, cycle }, {
|
|
812
|
+
bare: () => cadence,
|
|
813
|
+
// A clean wrap from a non-zero offset: name the start, no endpoint.
|
|
814
|
+
offset: () => cadence + " from " + getNumber(start, opts) + " " + pluralize(start, unit) + " past the " + anchor,
|
|
815
|
+
// A bounded, non-wrapping set: pin both endpoints. Each bound is a value,
|
|
816
|
+
// so it reads as a digit, matching the range idiom ("from 0 through 30").
|
|
817
|
+
bounded: () => {
|
|
818
|
+
const num = seriesNumber();
|
|
819
|
+
return cadence + " from " + num(start) + through(opts) + num(last) + " " + pluralize(last, unit) + " past the " + anchor;
|
|
820
|
+
}
|
|
821
|
+
});
|
|
733
822
|
}
|
|
734
823
|
function strideFromSegments(segments, unit, anchor, opts) {
|
|
735
824
|
const values = singleValues(segments);
|
|
736
825
|
const step = values && arithmeticStep(values);
|
|
737
|
-
return step ?
|
|
826
|
+
return step ? renderStride2({ ...step, cycle: 60, unit, anchor }, opts) : null;
|
|
738
827
|
}
|
|
739
828
|
function stepCycle60(segment, unit, anchor, opts) {
|
|
740
829
|
if (segment.startToken.indexOf("-") !== -1) {
|
|
@@ -744,7 +833,7 @@ function stepCycle60(segment, unit, anchor, opts) {
|
|
|
744
833
|
if (start !== 0 && segment.fires.length <= 3) {
|
|
745
834
|
return listPastThe(numberWords(segment.fires, opts), unit, anchor, opts);
|
|
746
835
|
}
|
|
747
|
-
return
|
|
836
|
+
return renderStride2({
|
|
748
837
|
interval: segment.interval,
|
|
749
838
|
start,
|
|
750
839
|
last: segment.fires[segment.fires.length - 1],
|
|
@@ -770,24 +859,21 @@ function stepHours(segment, opts) {
|
|
|
770
859
|
function hourStrideCadence(stride, opts) {
|
|
771
860
|
const { start, interval, last } = stride;
|
|
772
861
|
const cadence = "every " + getNumber(interval, opts) + " hours";
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
return cadence + " from " + getTime({ hour: start, minute: 0 }, opts);
|
|
779
|
-
}
|
|
780
|
-
return cadence + " from " + getTime({ hour: start, minute: 0 }, opts) + through(opts) + getTime({ hour: last, minute: 0 }, opts);
|
|
862
|
+
return renderStride({ start, interval, cycle: 24 }, {
|
|
863
|
+
bare: () => cadence,
|
|
864
|
+
offset: () => cadence + " from " + getTime({ hour: start, minute: 0 }, opts),
|
|
865
|
+
bounded: () => cadence + " from " + getTime({ hour: start, minute: 0 }, opts) + through(opts) + getTime({ hour: last, minute: 0 }, opts)
|
|
866
|
+
});
|
|
781
867
|
}
|
|
782
|
-
function unevenHourCadence(
|
|
783
|
-
const stride = hourStride(
|
|
868
|
+
function unevenHourCadence(schedule, opts) {
|
|
869
|
+
const stride = hourStride(schedule);
|
|
784
870
|
if (!stride || offsetCleanStride(stride)) {
|
|
785
871
|
return null;
|
|
786
872
|
}
|
|
787
873
|
return hourStrideCadence(stride, opts);
|
|
788
874
|
}
|
|
789
|
-
function hourStride(
|
|
790
|
-
const segments = segmentsOf(
|
|
875
|
+
function hourStride(schedule) {
|
|
876
|
+
const segments = segmentsOf(schedule, "hour");
|
|
791
877
|
if (segments.length === 1 && segments[0].kind === "step") {
|
|
792
878
|
const segment = segments[0];
|
|
793
879
|
if (segment.fires.length < 2) {
|
|
@@ -799,57 +885,57 @@ function hourStride(ir) {
|
|
|
799
885
|
const values = singleValues(segments);
|
|
800
886
|
return values && hourListStride(values);
|
|
801
887
|
}
|
|
802
|
-
function subMinuteSecond(
|
|
803
|
-
return
|
|
888
|
+
function subMinuteSecond(schedule) {
|
|
889
|
+
return schedule.pattern.second === "*" || schedule.shapes.second === "step";
|
|
804
890
|
}
|
|
805
|
-
function hourCadenceLead(
|
|
891
|
+
function hourCadenceLead(schedule, minute, opts) {
|
|
806
892
|
if (minute === 0) {
|
|
807
|
-
if (subMinuteSecond(
|
|
808
|
-
return secondsClause(
|
|
893
|
+
if (subMinuteSecond(schedule)) {
|
|
894
|
+
return secondsClause(schedule, "minute", opts) + " for one minute";
|
|
809
895
|
}
|
|
810
|
-
return secondsClause(
|
|
896
|
+
return secondsClause(schedule, "hour", opts);
|
|
811
897
|
}
|
|
812
898
|
const minutePhrase = getNumber(minute, opts) + " " + pluralize(minute, "minute") + " past the hour";
|
|
813
|
-
if (
|
|
899
|
+
if (schedule.pattern.second === "0") {
|
|
814
900
|
return minutePhrase;
|
|
815
901
|
}
|
|
816
|
-
return secondsClause(
|
|
902
|
+
return secondsClause(schedule, "minute", opts) + ", " + minutePhrase;
|
|
817
903
|
}
|
|
818
|
-
function hourCadence(
|
|
819
|
-
const stride = hourStride(
|
|
904
|
+
function hourCadence(schedule, minute, opts) {
|
|
905
|
+
const stride = hourStride(schedule);
|
|
820
906
|
if (!stride) {
|
|
821
907
|
return null;
|
|
822
908
|
}
|
|
823
909
|
const fires = (stride.last - stride.start) / stride.interval + 1;
|
|
824
|
-
if (
|
|
910
|
+
if (schedule.pattern.second === "0" && fires <= maxClockTimes && offsetCleanStride(stride)) {
|
|
825
911
|
return null;
|
|
826
912
|
}
|
|
827
|
-
const minuteZeroStride = minute === 0 && subMinuteSecond(
|
|
913
|
+
const minuteZeroStride = minute === 0 && subMinuteSecond(schedule) && cleanStrideSegment(schedule);
|
|
828
914
|
if (minuteZeroStride) {
|
|
829
|
-
return secondsClause(
|
|
915
|
+
return secondsClause(schedule, "minute", opts) + " for one minute " + everyNthHour(minuteZeroStride, opts) + trailingQualifier(schedule, opts);
|
|
830
916
|
}
|
|
831
|
-
if (minute === 0 &&
|
|
832
|
-
return hourStrideCadence(stride, opts) + trailingQualifier(
|
|
917
|
+
if (minute === 0 && schedule.pattern.second === "0") {
|
|
918
|
+
return hourStrideCadence(stride, opts) + trailingQualifier(schedule, opts);
|
|
833
919
|
}
|
|
834
|
-
return hourCadenceLead(
|
|
920
|
+
return hourCadenceLead(schedule, minute, opts) + ", " + hourStrideCadence(stride, opts) + trailingQualifier(schedule, opts);
|
|
835
921
|
}
|
|
836
|
-
function cleanStrideSegment(
|
|
837
|
-
const segments = segmentsOf(
|
|
922
|
+
function cleanStrideSegment(schedule) {
|
|
923
|
+
const segments = segmentsOf(schedule, "hour");
|
|
838
924
|
const segment = segments.length === 1 && segments[0];
|
|
839
925
|
if (!segment || segment.kind !== "step" || segment.startToken.indexOf("-") !== -1 || !(segment.interval in stepOrdinals)) {
|
|
840
926
|
return null;
|
|
841
927
|
}
|
|
842
928
|
return segment;
|
|
843
929
|
}
|
|
844
|
-
function hasHourWindow(
|
|
845
|
-
return segmentsOf(
|
|
930
|
+
function hasHourWindow(schedule) {
|
|
931
|
+
return segmentsOf(schedule, "hour").some(function range(segment) {
|
|
846
932
|
return segment.kind === "range";
|
|
847
933
|
});
|
|
848
934
|
}
|
|
849
|
-
function hourRangeWindowTail(
|
|
935
|
+
function hourRangeWindowTail(schedule, opts) {
|
|
850
936
|
const windows = [];
|
|
851
|
-
const outlierHours = collectHourOutliers(
|
|
852
|
-
segmentsOf(
|
|
937
|
+
const outlierHours = collectHourOutliers(schedule);
|
|
938
|
+
segmentsOf(schedule, "hour").forEach(function classify(segment) {
|
|
853
939
|
if (segment.kind === "range") {
|
|
854
940
|
windows.push(rangeWindow({
|
|
855
941
|
continuous: false,
|
|
@@ -865,17 +951,17 @@ function hourRangeWindowTail(ir, opts) {
|
|
|
865
951
|
});
|
|
866
952
|
return phrase + outlierTail(times, opts);
|
|
867
953
|
}
|
|
868
|
-
function hourRangeCadence(
|
|
869
|
-
if (minute !== 0 || !hasHourWindow(
|
|
954
|
+
function hourRangeCadence(schedule, minute, opts) {
|
|
955
|
+
if (minute !== 0 || !hasHourWindow(schedule)) {
|
|
870
956
|
return null;
|
|
871
957
|
}
|
|
872
|
-
if (
|
|
958
|
+
if (schedule.pattern.second === "0") {
|
|
873
959
|
return null;
|
|
874
960
|
}
|
|
875
|
-
if (subMinuteSecond(
|
|
876
|
-
return secondsClause(
|
|
961
|
+
if (subMinuteSecond(schedule)) {
|
|
962
|
+
return secondsClause(schedule, "minute", opts) + " for one minute during the " + hourSegmentTimes(schedule, { minute: 0, second: null }, false, opts) + " hours" + trailingQualifier(schedule, opts);
|
|
877
963
|
}
|
|
878
|
-
return hourCadenceLead(
|
|
964
|
+
return hourCadenceLead(schedule, minute, opts) + ", " + hourRangeWindowTail(schedule, opts) + trailingQualifier(schedule, opts);
|
|
879
965
|
}
|
|
880
966
|
function seriesNumber() {
|
|
881
967
|
return function format(n) {
|
|
@@ -934,11 +1020,11 @@ function hourTimes(hours, opts) {
|
|
|
934
1020
|
function singleHourFire(times) {
|
|
935
1021
|
return times.kind === "fires" && times.fires.length === 1;
|
|
936
1022
|
}
|
|
937
|
-
function hourTimesFromPlan(
|
|
1023
|
+
function hourTimesFromPlan(schedule, times, atContext, opts) {
|
|
938
1024
|
if (times.kind === "fires") {
|
|
939
1025
|
return hourTimes(times.fires, opts);
|
|
940
1026
|
}
|
|
941
|
-
return hourSegmentTimes(
|
|
1027
|
+
return hourSegmentTimes(schedule, { minute: 0, second: null }, atContext, opts);
|
|
942
1028
|
}
|
|
943
1029
|
function segmentHours(segment) {
|
|
944
1030
|
if (segment.kind === "range") {
|
|
@@ -946,9 +1032,9 @@ function segmentHours(segment) {
|
|
|
946
1032
|
}
|
|
947
1033
|
return segment.kind === "step" ? segment.fires : [segment.value];
|
|
948
1034
|
}
|
|
949
|
-
function hourSegmentTimes(
|
|
1035
|
+
function hourSegmentTimes(schedule, fold, atContext, opts) {
|
|
950
1036
|
const { minute, second } = fold;
|
|
951
|
-
const segments = segmentsOf(
|
|
1037
|
+
const segments = segmentsOf(schedule, "hour");
|
|
952
1038
|
const plain = mixedTwelve(segments.flatMap(function entries(segment) {
|
|
953
1039
|
return segmentHours(segment).map(function entry(hour) {
|
|
954
1040
|
return { hour: +hour, minute, second };
|
|
@@ -1011,85 +1097,85 @@ var leadingWords = {
|
|
|
1011
1097
|
stepDate: "",
|
|
1012
1098
|
weekday: "every "
|
|
1013
1099
|
};
|
|
1014
|
-
function trailingQualifier(
|
|
1015
|
-
if (isDayUnion(
|
|
1016
|
-
return dayUnionCondition(
|
|
1100
|
+
function trailingQualifier(schedule, opts) {
|
|
1101
|
+
if (isDayUnion(schedule, opts)) {
|
|
1102
|
+
return dayUnionCondition(schedule, opts);
|
|
1017
1103
|
}
|
|
1018
|
-
const phrase = dayQualifier(
|
|
1104
|
+
const phrase = dayQualifier(schedule, trailingWords, opts);
|
|
1019
1105
|
return phrase && " " + phrase;
|
|
1020
1106
|
}
|
|
1021
|
-
function interpretDayQualifier(
|
|
1022
|
-
if (isDayUnion(
|
|
1107
|
+
function interpretDayQualifier(schedule, opts) {
|
|
1108
|
+
if (isDayUnion(schedule, opts)) {
|
|
1023
1109
|
return "";
|
|
1024
1110
|
}
|
|
1025
|
-
return dayQualifier(
|
|
1111
|
+
return dayQualifier(schedule, leadingWords, opts) + " ";
|
|
1026
1112
|
}
|
|
1027
|
-
function dayQualifier(
|
|
1028
|
-
const pattern =
|
|
1113
|
+
function dayQualifier(schedule, words, opts) {
|
|
1114
|
+
const pattern = schedule.pattern;
|
|
1029
1115
|
if (pattern.date !== "*" && pattern.weekday !== "*") {
|
|
1030
|
-
return dateOrWeekday(
|
|
1116
|
+
return dateOrWeekday(schedule, opts);
|
|
1031
1117
|
}
|
|
1032
1118
|
if (pattern.date !== "*") {
|
|
1033
|
-
return datePhrase(
|
|
1119
|
+
return datePhrase(schedule, words, opts);
|
|
1034
1120
|
}
|
|
1035
1121
|
if (pattern.weekday !== "*") {
|
|
1036
1122
|
const quartzWeekday = quartzWeekdayPhrase(pattern.weekday, opts);
|
|
1037
1123
|
if (quartzWeekday) {
|
|
1038
|
-
return monthScopeForRecurrence(quartzWeekday,
|
|
1124
|
+
return monthScopeForRecurrence(quartzWeekday, schedule, opts);
|
|
1039
1125
|
}
|
|
1040
|
-
const weekdays = words.weekday + weekdayPhrase(
|
|
1041
|
-
return weekdays + monthScope(
|
|
1126
|
+
const weekdays = words.weekday + weekdayPhrase(schedule, words.recurringWeekday, opts);
|
|
1127
|
+
return weekdays + monthScope(schedule, opts);
|
|
1042
1128
|
}
|
|
1043
1129
|
if (pattern.month !== "*") {
|
|
1044
|
-
return words.month + monthName(
|
|
1130
|
+
return words.month + monthName(schedule, opts);
|
|
1045
1131
|
}
|
|
1046
1132
|
return words.all;
|
|
1047
1133
|
}
|
|
1048
|
-
function datePhrase(
|
|
1049
|
-
const pattern =
|
|
1134
|
+
function datePhrase(schedule, words, opts) {
|
|
1135
|
+
const pattern = schedule.pattern;
|
|
1050
1136
|
const quartzDate = quartzDatePhrase(pattern.date, opts);
|
|
1051
1137
|
if (quartzDate) {
|
|
1052
|
-
return monthScopeForRecurrence(quartzDate,
|
|
1138
|
+
return monthScopeForRecurrence(quartzDate, schedule, opts);
|
|
1053
1139
|
}
|
|
1054
1140
|
if (isOpenStep(pattern.date)) {
|
|
1055
1141
|
return monthScopeForRecurrence(
|
|
1056
1142
|
words.stepDate + stepDates(pattern.date),
|
|
1057
|
-
|
|
1143
|
+
schedule,
|
|
1058
1144
|
opts
|
|
1059
1145
|
);
|
|
1060
1146
|
}
|
|
1061
|
-
if (pattern.month !== "*" && !monthFoldsIntoDate(
|
|
1062
|
-
return "on the " + dateOrdinals(
|
|
1147
|
+
if (pattern.month !== "*" && !monthFoldsIntoDate(schedule)) {
|
|
1148
|
+
return "on the " + dateOrdinals(schedule, opts) + monthScope(schedule, opts);
|
|
1063
1149
|
}
|
|
1064
1150
|
if (pattern.month !== "*") {
|
|
1065
|
-
return "on " + monthDatePhrase(
|
|
1151
|
+
return "on " + monthDatePhrase(schedule, opts);
|
|
1066
1152
|
}
|
|
1067
|
-
return "on the " + dateOrdinals(
|
|
1153
|
+
return "on the " + dateOrdinals(schedule, opts);
|
|
1068
1154
|
}
|
|
1069
|
-
function monthFoldsIntoDate(
|
|
1070
|
-
return !oddEvenMonth(
|
|
1071
|
-
segmentsOf(
|
|
1155
|
+
function monthFoldsIntoDate(schedule) {
|
|
1156
|
+
return !oddEvenMonth(schedule.pattern.month) && // Reached only with a restricted month, which has segments.
|
|
1157
|
+
segmentsOf(schedule, "month").every(function flat(segment) {
|
|
1072
1158
|
return segment.kind !== "range";
|
|
1073
1159
|
});
|
|
1074
1160
|
}
|
|
1075
|
-
function isDayUnion(
|
|
1076
|
-
return
|
|
1161
|
+
function isDayUnion(schedule, opts) {
|
|
1162
|
+
return schedule.pattern.date !== "*" && schedule.pattern.weekday !== "*" && !!opts.style.untilWindow && !opts.short;
|
|
1077
1163
|
}
|
|
1078
|
-
function dayUnionCondition(
|
|
1164
|
+
function dayUnionCondition(schedule, opts) {
|
|
1079
1165
|
const pieces = [
|
|
1080
|
-
...dayUnionDatePieces(
|
|
1081
|
-
...dayUnionWeekdayPieces(
|
|
1166
|
+
...dayUnionDatePieces(schedule, opts),
|
|
1167
|
+
...dayUnionWeekdayPieces(schedule, opts)
|
|
1082
1168
|
];
|
|
1083
1169
|
return " whenever the day is " + joinOr(pieces, opts);
|
|
1084
1170
|
}
|
|
1085
|
-
function dayUnionMonthLead(
|
|
1086
|
-
if (
|
|
1171
|
+
function dayUnionMonthLead(schedule, opts) {
|
|
1172
|
+
if (schedule.pattern.month === "*") {
|
|
1087
1173
|
return "";
|
|
1088
1174
|
}
|
|
1089
|
-
return "in " + monthName(
|
|
1175
|
+
return "in " + monthName(schedule, opts) + " ";
|
|
1090
1176
|
}
|
|
1091
|
-
function dayUnionDatePieces(
|
|
1092
|
-
const dateField =
|
|
1177
|
+
function dayUnionDatePieces(schedule, opts) {
|
|
1178
|
+
const dateField = schedule.pattern.date;
|
|
1093
1179
|
const quartz = quartzDatePhrase(dateField, opts);
|
|
1094
1180
|
if (quartz) {
|
|
1095
1181
|
return [quartz.replace(/^on /, "")];
|
|
@@ -1099,7 +1185,7 @@ function dayUnionDatePieces(ir, opts) {
|
|
|
1099
1185
|
return [oddEven];
|
|
1100
1186
|
}
|
|
1101
1187
|
const pieces = [];
|
|
1102
|
-
segmentsOf(
|
|
1188
|
+
segmentsOf(schedule, "date").forEach(function expand(segment) {
|
|
1103
1189
|
if (segment.kind === "range") {
|
|
1104
1190
|
pieces.push("from the " + getOrdinal(segment.bounds[0]) + through(opts) + "the " + getOrdinal(segment.bounds[1]));
|
|
1105
1191
|
} else if (segment.kind === "step") {
|
|
@@ -1112,14 +1198,14 @@ function dayUnionDatePieces(ir, opts) {
|
|
|
1112
1198
|
});
|
|
1113
1199
|
return pieces;
|
|
1114
1200
|
}
|
|
1115
|
-
function dayUnionWeekdayPieces(
|
|
1116
|
-
const weekdayField =
|
|
1201
|
+
function dayUnionWeekdayPieces(schedule, opts) {
|
|
1202
|
+
const weekdayField = schedule.pattern.weekday;
|
|
1117
1203
|
const quartz = quartzWeekdayPhrase(weekdayField, opts);
|
|
1118
1204
|
if (quartz) {
|
|
1119
1205
|
return [quartz.replace(/^on /, "")];
|
|
1120
1206
|
}
|
|
1121
1207
|
const pieces = [];
|
|
1122
|
-
segmentsOf(
|
|
1208
|
+
segmentsOf(schedule, "weekday").forEach(function expand(segment) {
|
|
1123
1209
|
if (segment.kind === "range" && segment.bounds[0] === "1" && segment.bounds[1] === "5") {
|
|
1124
1210
|
pieces.push("a weekday");
|
|
1125
1211
|
} else if (segment.kind === "range") {
|
|
@@ -1147,16 +1233,16 @@ function oddEvenDay(dateField) {
|
|
|
1147
1233
|
}
|
|
1148
1234
|
return start === "2" ? "an even-numbered day" : null;
|
|
1149
1235
|
}
|
|
1150
|
-
function dateOrWeekday(
|
|
1151
|
-
const pattern =
|
|
1152
|
-
const weekdayPart = quartzWeekdayPhrase(pattern.weekday, opts) || "on " + weekdayPhrase(
|
|
1153
|
-
if (pattern.month !== "*" && monthFoldsIntoDate(
|
|
1154
|
-
return "on " + monthDatePhrase(
|
|
1236
|
+
function dateOrWeekday(schedule, opts) {
|
|
1237
|
+
const pattern = schedule.pattern;
|
|
1238
|
+
const weekdayPart = quartzWeekdayPhrase(pattern.weekday, opts) || "on " + weekdayPhrase(schedule, false, opts);
|
|
1239
|
+
if (pattern.month !== "*" && monthFoldsIntoDate(schedule) && !quartzDatePhrase(pattern.date, opts) && !isOpenStep(pattern.date)) {
|
|
1240
|
+
return "on " + monthDatePhrase(schedule, opts) + " or " + weekdayPart + " in " + monthName(schedule, opts);
|
|
1155
1241
|
}
|
|
1156
|
-
return datePart(
|
|
1242
|
+
return datePart(schedule, opts) + " or " + weekdayPart + orMonthScope(schedule, opts);
|
|
1157
1243
|
}
|
|
1158
|
-
function datePart(
|
|
1159
|
-
const pattern =
|
|
1244
|
+
function datePart(schedule, opts) {
|
|
1245
|
+
const pattern = schedule.pattern;
|
|
1160
1246
|
const quartzDate = quartzDatePhrase(pattern.date, opts);
|
|
1161
1247
|
if (quartzDate) {
|
|
1162
1248
|
return quartzDate;
|
|
@@ -1164,13 +1250,13 @@ function datePart(ir, opts) {
|
|
|
1164
1250
|
if (isOpenStep(pattern.date)) {
|
|
1165
1251
|
return stepDates(pattern.date);
|
|
1166
1252
|
}
|
|
1167
|
-
return "on the " + dateOrdinals(
|
|
1253
|
+
return "on the " + dateOrdinals(schedule, opts);
|
|
1168
1254
|
}
|
|
1169
|
-
function orMonthScope(
|
|
1170
|
-
if (
|
|
1255
|
+
function orMonthScope(schedule, opts) {
|
|
1256
|
+
if (schedule.pattern.month === "*") {
|
|
1171
1257
|
return "";
|
|
1172
1258
|
}
|
|
1173
|
-
return ", in " + monthName(
|
|
1259
|
+
return ", in " + monthName(schedule, opts);
|
|
1174
1260
|
}
|
|
1175
1261
|
function quartzDatePhrase(dateField, opts) {
|
|
1176
1262
|
if (dateField === "L") {
|
|
@@ -1197,39 +1283,39 @@ function quartzWeekdayPhrase(weekdayField, opts) {
|
|
|
1197
1283
|
return "on the last " + getWeekday(weekdayField.slice(0, -1), opts) + " of the month";
|
|
1198
1284
|
}
|
|
1199
1285
|
}
|
|
1200
|
-
function monthDatePhrase(
|
|
1201
|
-
const month = monthName(
|
|
1286
|
+
function monthDatePhrase(schedule, opts) {
|
|
1287
|
+
const month = monthName(schedule, opts);
|
|
1202
1288
|
const days = renderSegments(
|
|
1203
|
-
segmentsOf(
|
|
1289
|
+
segmentsOf(schedule, "date"),
|
|
1204
1290
|
opts.style.ordinals ? getOrdinal : cardinalDay,
|
|
1205
1291
|
opts
|
|
1206
1292
|
);
|
|
1207
|
-
if (opts.style.dayFirst &&
|
|
1208
|
-
return "the " + getOrdinal(
|
|
1293
|
+
if (opts.style.dayFirst && schedule.shapes.date === "single" && schedule.shapes.month !== "single") {
|
|
1294
|
+
return "the " + getOrdinal(schedule.pattern.date) + " of " + month;
|
|
1209
1295
|
}
|
|
1210
1296
|
return opts.style.dayFirst ? days + " " + month : month + " " + days;
|
|
1211
1297
|
}
|
|
1212
1298
|
function cardinalDay(value) {
|
|
1213
1299
|
return "" + value;
|
|
1214
1300
|
}
|
|
1215
|
-
function monthScope(
|
|
1216
|
-
if (
|
|
1301
|
+
function monthScope(schedule, opts) {
|
|
1302
|
+
if (schedule.pattern.month === "*") {
|
|
1217
1303
|
return "";
|
|
1218
1304
|
}
|
|
1219
|
-
return " in " + monthName(
|
|
1305
|
+
return " in " + monthName(schedule, opts);
|
|
1220
1306
|
}
|
|
1221
|
-
function monthScopeForRecurrence(phrase,
|
|
1222
|
-
if (
|
|
1307
|
+
function monthScopeForRecurrence(phrase, schedule, opts) {
|
|
1308
|
+
if (schedule.pattern.month === "*") {
|
|
1223
1309
|
return phrase;
|
|
1224
1310
|
}
|
|
1225
1311
|
const carriesRecurrence = phrase.indexOf(" of the month") !== -1;
|
|
1226
|
-
if (carriesRecurrence &&
|
|
1227
|
-
return phrase.replace(" of the month", " of each month") + " from " + monthName(
|
|
1312
|
+
if (carriesRecurrence && schedule.shapes.month === "range") {
|
|
1313
|
+
return phrase.replace(" of the month", " of each month") + " from " + monthName(schedule, opts);
|
|
1228
1314
|
}
|
|
1229
|
-
if (carriesRecurrence && (
|
|
1230
|
-
return phrase.replace(" of the month", "") + " in " + monthName(
|
|
1315
|
+
if (carriesRecurrence && (schedule.shapes.month === "single" || schedule.shapes.month === "step")) {
|
|
1316
|
+
return phrase.replace(" of the month", "") + " in " + monthName(schedule, opts);
|
|
1231
1317
|
}
|
|
1232
|
-
return phrase + " in " + monthName(
|
|
1318
|
+
return phrase + " in " + monthName(schedule, opts);
|
|
1233
1319
|
}
|
|
1234
1320
|
function stepDates(dateField) {
|
|
1235
1321
|
const parts = dateField.split("/");
|
|
@@ -1242,15 +1328,15 @@ function stepDates(dateField) {
|
|
|
1242
1328
|
}
|
|
1243
1329
|
return phrase;
|
|
1244
1330
|
}
|
|
1245
|
-
function dateOrdinals(
|
|
1246
|
-
return renderSegments(segmentsOf(
|
|
1331
|
+
function dateOrdinals(schedule, opts) {
|
|
1332
|
+
return renderSegments(segmentsOf(schedule, "date"), getOrdinal, opts);
|
|
1247
1333
|
}
|
|
1248
|
-
function monthName(
|
|
1249
|
-
const oddEven = oddEvenMonth(
|
|
1334
|
+
function monthName(schedule, opts) {
|
|
1335
|
+
const oddEven = oddEvenMonth(schedule.pattern.month);
|
|
1250
1336
|
if (oddEven) {
|
|
1251
1337
|
return oddEven;
|
|
1252
1338
|
}
|
|
1253
|
-
return renderSegments(segmentsOf(
|
|
1339
|
+
return renderSegments(segmentsOf(schedule, "month"), function name(value) {
|
|
1254
1340
|
return getMonth(value, opts);
|
|
1255
1341
|
}, opts);
|
|
1256
1342
|
}
|
|
@@ -1267,8 +1353,8 @@ function oddEvenMonth(monthField) {
|
|
|
1267
1353
|
}
|
|
1268
1354
|
return start === "2" ? "every even-numbered month" : null;
|
|
1269
1355
|
}
|
|
1270
|
-
function weekdayPhrase(
|
|
1271
|
-
const segments = orderWeekdaysForDisplay(segmentsOf(
|
|
1356
|
+
function weekdayPhrase(schedule, recurring, opts) {
|
|
1357
|
+
const segments = orderWeekdaysForDisplay(segmentsOf(schedule, "weekday"));
|
|
1272
1358
|
const hasRange = segments.some(function range(segment) {
|
|
1273
1359
|
return segment.kind === "range";
|
|
1274
1360
|
});
|
|
@@ -1296,8 +1382,8 @@ function renderSegments(segments, word, opts) {
|
|
|
1296
1382
|
});
|
|
1297
1383
|
return joinList(pieces, opts);
|
|
1298
1384
|
}
|
|
1299
|
-
function applyYear(description,
|
|
1300
|
-
const yearField =
|
|
1385
|
+
function applyYear(description, schedule, opts) {
|
|
1386
|
+
const yearField = schedule.pattern.year;
|
|
1301
1387
|
if (yearField === "*") {
|
|
1302
1388
|
return description;
|
|
1303
1389
|
}
|
|
@@ -1305,7 +1391,7 @@ function applyYear(description, ir, opts) {
|
|
|
1305
1391
|
return description + ", " + stepYears(yearField, opts);
|
|
1306
1392
|
}
|
|
1307
1393
|
const label = yearLabel(yearField, opts);
|
|
1308
|
-
if (yearField.indexOf("-") === -1 && yearField.indexOf(",") === -1 &&
|
|
1394
|
+
if (yearField.indexOf("-") === -1 && yearField.indexOf(",") === -1 && schedule.pattern.date !== "*" && description.indexOf(" at ") !== -1) {
|
|
1309
1395
|
const yearGlue = opts.style.dayFirst ? " " : ", ";
|
|
1310
1396
|
return description.replace(" at ", yearGlue + label + " at ");
|
|
1311
1397
|
}
|