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