cronli5 0.1.4 → 0.1.6
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 +53 -0
- package/cronli5.min.js +2 -2
- package/dist/cronli5.cjs +286 -45
- package/dist/cronli5.js +286 -45
- package/dist/lang/de.cjs +252 -13
- package/dist/lang/de.js +252 -13
- package/dist/lang/en.cjs +281 -38
- package/dist/lang/en.js +281 -38
- package/dist/lang/es.cjs +259 -29
- package/dist/lang/es.js +259 -29
- package/dist/lang/fi.cjs +285 -49
- package/dist/lang/fi.js +285 -49
- package/dist/lang/zh.cjs +225 -42
- package/dist/lang/zh.js +225 -42
- package/package.json +3 -2
- package/src/core/analyze.ts +7 -0
- package/src/core/ir.ts +1 -1
- package/src/core/util.ts +31 -1
- package/src/lang/de/index.ts +561 -30
- package/src/lang/en/index.ts +593 -59
- package/src/lang/es/index.ts +576 -52
- package/src/lang/fi/index.ts +633 -95
- package/src/lang/zh/index.ts +484 -77
- package/types/core/ir.d.ts +1 -1
- package/types/core/util.d.ts +6 -1
package/dist/lang/en.cjs
CHANGED
|
@@ -24,6 +24,26 @@ __export(index_exports, {
|
|
|
24
24
|
});
|
|
25
25
|
module.exports = __toCommonJS(index_exports);
|
|
26
26
|
|
|
27
|
+
// src/core/util.ts
|
|
28
|
+
function arithmeticStep(values) {
|
|
29
|
+
if (values.length < 5) {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
const interval = values[1] - values[0];
|
|
33
|
+
if (interval < 2) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
for (let i = 2; i < values.length; i += 1) {
|
|
37
|
+
if (values[i] - values[i - 1] !== interval) {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return { start: values[0], interval, last: values[values.length - 1] };
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// src/core/specs.ts
|
|
45
|
+
var maxClockTimes = 6;
|
|
46
|
+
|
|
27
47
|
// src/core/format.ts
|
|
28
48
|
function pad(n) {
|
|
29
49
|
n = "" + n;
|
|
@@ -179,18 +199,34 @@ function renderSecondsWithinMinute(ir, plan, opts) {
|
|
|
179
199
|
}
|
|
180
200
|
return secondsLeadClause(ir, opts) + ", " + minuteWord + " " + minuteUnit + " past the hour, every hour" + trailingQualifier(ir, opts);
|
|
181
201
|
}
|
|
202
|
+
function composeHourCadence(ir, plan, opts) {
|
|
203
|
+
const clockRest = plan.rest.kind === "clockTimes" || plan.rest.kind === "compactClockTimes";
|
|
204
|
+
if (!clockRest || ir.shapes.minute !== "single") {
|
|
205
|
+
return null;
|
|
206
|
+
}
|
|
207
|
+
const minute = +ir.pattern.minute;
|
|
208
|
+
return hourCadence(ir, minute, opts) ?? hourRangeCadence(ir, minute, opts);
|
|
209
|
+
}
|
|
210
|
+
function clockTimesConfinement(ir, rest, opts) {
|
|
211
|
+
if (+rest.times[0].minute === 0 && ir.shapes.minute === "single") {
|
|
212
|
+
return secondsLeadClause(ir, opts) + " for one minute at " + durationHours(ir, rest, opts);
|
|
213
|
+
}
|
|
214
|
+
return secondsLeadClause(ir, opts) + " of " + clockTimesOf(ir, rest, opts);
|
|
215
|
+
}
|
|
182
216
|
function renderComposeSeconds(ir, plan, opts) {
|
|
217
|
+
const cadence = composeHourCadence(ir, plan, opts);
|
|
218
|
+
if (cadence !== null) {
|
|
219
|
+
return cadence;
|
|
220
|
+
}
|
|
183
221
|
if (plan.rest.kind === "clockTimes" && (ir.shapes.second === "wildcard" || ir.shapes.second === "step")) {
|
|
184
|
-
|
|
185
|
-
if (+minute === 0) {
|
|
186
|
-
return secondsLeadClause(ir, opts) + " for one minute at " + durationHours(ir, plan.rest, opts);
|
|
187
|
-
}
|
|
188
|
-
return secondsLeadClause(ir, opts) + " of " + clockTimesOf(ir, plan.rest, opts);
|
|
222
|
+
return clockTimesConfinement(ir, plan.rest, opts);
|
|
189
223
|
}
|
|
190
224
|
if (ir.shapes.second === "wildcard" && plan.rest.kind === "minuteFrequency" && plan.rest.hours.kind === "none" && ir.pattern.minute === "*/2") {
|
|
191
225
|
return "every second of every other minute" + trailingQualifier(ir, opts);
|
|
192
226
|
}
|
|
193
|
-
|
|
227
|
+
const restOwnsLead = plan.rest.kind === "compactClockTimes" && ir.analyses.clockSecond;
|
|
228
|
+
const lead = restOwnsLead ? "" : secondsLeadClause(ir, opts) + ", ";
|
|
229
|
+
return lead + render(ir, plan.rest, opts);
|
|
194
230
|
}
|
|
195
231
|
function durationHours(ir, plan, opts) {
|
|
196
232
|
const hours = plan.times.map(function clock(time) {
|
|
@@ -212,6 +248,9 @@ function clockTimesOf(ir, plan, opts) {
|
|
|
212
248
|
return joinList(times, opts) + (trail && ", " + trail);
|
|
213
249
|
}
|
|
214
250
|
function secondsLeadClause(ir, opts) {
|
|
251
|
+
return secondsClause(ir, "minute", opts);
|
|
252
|
+
}
|
|
253
|
+
function secondsClause(ir, anchor, opts) {
|
|
215
254
|
const secondField = ir.pattern.second;
|
|
216
255
|
const shape = ir.shapes.second;
|
|
217
256
|
if (secondField === "*") {
|
|
@@ -221,22 +260,27 @@ function secondsLeadClause(ir, opts) {
|
|
|
221
260
|
return stepCycle60(
|
|
222
261
|
ir.analyses.segments.second[0],
|
|
223
262
|
"second",
|
|
224
|
-
|
|
263
|
+
anchor,
|
|
225
264
|
opts
|
|
226
265
|
);
|
|
227
266
|
}
|
|
228
267
|
if (shape === "range") {
|
|
229
268
|
const bounds = secondField.split("-");
|
|
230
269
|
const num = seriesNumber(bounds, opts);
|
|
231
|
-
return "every second from " + num(bounds[0]) + through(opts) + num(bounds[1]) + " past the
|
|
270
|
+
return "every second from " + num(bounds[0]) + through(opts) + num(bounds[1]) + " past the " + anchor;
|
|
232
271
|
}
|
|
233
272
|
if (shape === "single") {
|
|
234
|
-
return "at " + getNumber(secondField, opts) + " " + pluralize(secondField, "second") + " past the
|
|
273
|
+
return "at " + getNumber(secondField, opts) + " " + pluralize(secondField, "second") + " past the " + anchor;
|
|
235
274
|
}
|
|
236
|
-
return
|
|
275
|
+
return strideFromSegments(
|
|
276
|
+
ir.analyses.segments.second,
|
|
277
|
+
"second",
|
|
278
|
+
anchor,
|
|
279
|
+
opts
|
|
280
|
+
) ?? listPastThe(
|
|
237
281
|
segmentWords(ir.analyses.segments.second, opts),
|
|
238
282
|
"second",
|
|
239
|
-
|
|
283
|
+
anchor,
|
|
240
284
|
opts
|
|
241
285
|
);
|
|
242
286
|
}
|
|
@@ -251,12 +295,11 @@ function renderRangeOfMinutes(ir, plan, opts) {
|
|
|
251
295
|
return minuteRangeLead(ir.pattern.minute, opts) + trailingQualifier(ir, opts);
|
|
252
296
|
}
|
|
253
297
|
function renderMultipleMinutes(ir, plan, opts) {
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
"hour",
|
|
298
|
+
const stride = strideFromSegments(ir.analyses.segments.minute, "minute", "hour", opts);
|
|
299
|
+
return (stride ?? listPastThe(segmentWords(
|
|
300
|
+
ir.analyses.segments.minute,
|
|
258
301
|
opts
|
|
259
|
-
) + trailingQualifier(ir, opts);
|
|
302
|
+
), "minute", "hour", opts)) + trailingQualifier(ir, opts);
|
|
260
303
|
}
|
|
261
304
|
function renderMinuteFrequency(ir, plan, opts) {
|
|
262
305
|
let phrase = stepCycle60(
|
|
@@ -266,7 +309,8 @@ function renderMinuteFrequency(ir, plan, opts) {
|
|
|
266
309
|
opts
|
|
267
310
|
);
|
|
268
311
|
if (plan.hours.kind === "during") {
|
|
269
|
-
|
|
312
|
+
const cadence = unevenHourCadence(ir, opts);
|
|
313
|
+
phrase += cadence ? ", " + cadence : " during the " + hourTimesFromPlan(ir, plan.hours.times, false, opts) + " hours";
|
|
270
314
|
} else if (plan.hours.kind === "window") {
|
|
271
315
|
phrase += " " + hourWindow(plan.hours, opts);
|
|
272
316
|
} else if (plan.hours.kind === "step") {
|
|
@@ -281,19 +325,27 @@ function renderMinuteSpanInHour(ir, plan, opts) {
|
|
|
281
325
|
return "every minute from " + getTime({ hour: plan.hour, minute: plan.span[0] }, opts) + through(opts) + getTime({ hour: plan.hour, minute: plan.span[1] }, opts) + trailingQualifier(ir, opts);
|
|
282
326
|
}
|
|
283
327
|
function renderMinutesAcrossHours(ir, plan, opts) {
|
|
328
|
+
const cadence = unevenHourCadence(ir, opts);
|
|
284
329
|
if (plan.form === "wildcard") {
|
|
330
|
+
if (cadence !== null) {
|
|
331
|
+
return "every minute, " + cadence + trailingQualifier(ir, opts);
|
|
332
|
+
}
|
|
285
333
|
return "every minute during the " + hourTimesFromPlan(ir, plan.times, false, opts) + " hours" + trailingQualifier(ir, opts);
|
|
286
334
|
}
|
|
287
|
-
const times = hourTimesFromPlan(ir, plan.times, true, opts);
|
|
288
335
|
const lead = plan.form === "range" ? minuteRangeLead(ir.pattern.minute, opts) : (
|
|
289
|
-
// The 'list' form is a minute list, which has segments
|
|
290
|
-
|
|
336
|
+
// The 'list' form is a minute list, which has segments; an offset/uneven
|
|
337
|
+
// step enumerated to that list reads as a stride.
|
|
338
|
+
strideFromSegments(ir.analyses.segments.minute, "minute", "hour", opts) ?? listPastThe(
|
|
291
339
|
segmentWords(ir.analyses.segments.minute, opts),
|
|
292
340
|
"minute",
|
|
293
341
|
"hour",
|
|
294
342
|
opts
|
|
295
343
|
)
|
|
296
344
|
);
|
|
345
|
+
if (cadence !== null) {
|
|
346
|
+
return lead + ", " + cadence + trailingQualifier(ir, opts);
|
|
347
|
+
}
|
|
348
|
+
const times = hourTimesFromPlan(ir, plan.times, true, opts);
|
|
297
349
|
return lead + ", at " + times + trailingQualifier(ir, opts);
|
|
298
350
|
}
|
|
299
351
|
var stepOrdinals = {
|
|
@@ -314,7 +366,14 @@ function renderMinuteSpanAcrossHourStep(ir, plan, opts) {
|
|
|
314
366
|
if (plan.form === "wildcard") {
|
|
315
367
|
return "every minute " + everyNthHour(segment, opts) + trailingQualifier(ir, opts);
|
|
316
368
|
}
|
|
317
|
-
|
|
369
|
+
const lead = plan.form === "list" ? strideFromSegments(ir.analyses.segments.minute, "minute", "hour", opts) ?? listPastThe(
|
|
370
|
+
segmentWords(ir.analyses.segments.minute, opts),
|
|
371
|
+
"minute",
|
|
372
|
+
"hour",
|
|
373
|
+
opts
|
|
374
|
+
) : minuteRangeLead(ir.pattern.minute, opts);
|
|
375
|
+
const cadence = unevenHourCadence(ir, opts);
|
|
376
|
+
return lead + ", " + (cadence ?? stepHours(segment, opts)) + trailingQualifier(ir, opts);
|
|
318
377
|
}
|
|
319
378
|
function minuteRangeLead(minuteField, opts) {
|
|
320
379
|
const bounds = minuteField.split("-");
|
|
@@ -338,7 +397,12 @@ function rangeMinuteLead(ir, opts) {
|
|
|
338
397
|
if (ir.pattern.minute === "0") {
|
|
339
398
|
return "every hour";
|
|
340
399
|
}
|
|
341
|
-
return
|
|
400
|
+
return strideFromSegments(
|
|
401
|
+
ir.analyses.segments.minute,
|
|
402
|
+
"minute",
|
|
403
|
+
"hour",
|
|
404
|
+
opts
|
|
405
|
+
) ?? listPastThe(
|
|
342
406
|
segmentWords(ir.analyses.segments.minute, opts),
|
|
343
407
|
"minute",
|
|
344
408
|
"hour",
|
|
@@ -346,6 +410,10 @@ function rangeMinuteLead(ir, opts) {
|
|
|
346
410
|
);
|
|
347
411
|
}
|
|
348
412
|
function renderHourStep(ir, plan, opts) {
|
|
413
|
+
const cadence = unevenHourCadence(ir, opts);
|
|
414
|
+
if (cadence !== null) {
|
|
415
|
+
return cadence + trailingQualifier(ir, opts);
|
|
416
|
+
}
|
|
349
417
|
return stepHours(ir.analyses.segments.hour[0], opts) + trailingQualifier(ir, opts);
|
|
350
418
|
}
|
|
351
419
|
function boundedWindow(plan) {
|
|
@@ -355,6 +423,13 @@ function hourWindow(window, opts) {
|
|
|
355
423
|
return "from " + getTime({ hour: window.from, minute: 0 }, opts) + through(opts) + getTime({ hour: window.to, minute: window.last }, opts);
|
|
356
424
|
}
|
|
357
425
|
function renderClockTimes(ir, plan, opts) {
|
|
426
|
+
if (ir.shapes.minute === "single") {
|
|
427
|
+
const minute = +ir.pattern.minute;
|
|
428
|
+
const cadence = hourCadence(ir, minute, opts) ?? hourRangeCadence(ir, minute, opts);
|
|
429
|
+
if (cadence !== null) {
|
|
430
|
+
return cadence;
|
|
431
|
+
}
|
|
432
|
+
}
|
|
358
433
|
const plain = mixedTwelve(plan.times);
|
|
359
434
|
const times = plan.times.map(function clock(time) {
|
|
360
435
|
return getTime({
|
|
@@ -368,6 +443,10 @@ function renderClockTimes(ir, plan, opts) {
|
|
|
368
443
|
}
|
|
369
444
|
function renderCompactClockTimes(ir, plan, opts) {
|
|
370
445
|
if (plan.fold) {
|
|
446
|
+
const cadence2 = hourCadence(ir, +plan.minute, opts) ?? hourRangeCadence(ir, +plan.minute, opts);
|
|
447
|
+
if (cadence2 !== null) {
|
|
448
|
+
return cadence2;
|
|
449
|
+
}
|
|
371
450
|
const hasRange = ir.analyses.segments.hour.some(function range(segment) {
|
|
372
451
|
return segment.kind === "range";
|
|
373
452
|
});
|
|
@@ -377,15 +456,18 @@ function renderCompactClockTimes(ir, plan, opts) {
|
|
|
377
456
|
const fold = { minute: plan.minute, second: ir.analyses.clockSecond };
|
|
378
457
|
return interpretDayQualifier(ir, opts) + "at " + hourSegmentTimes(ir, fold, true, opts);
|
|
379
458
|
}
|
|
380
|
-
const
|
|
381
|
-
// The non-fold branch is a minute list, which has segments.
|
|
382
|
-
|
|
459
|
+
const minuteLead = (
|
|
460
|
+
// The non-fold branch is a minute list, which has segments. An
|
|
461
|
+
// offset/uneven step enumerated to that list reads as a stride.
|
|
462
|
+
strideFromSegments(ir.analyses.segments.minute, "minute", "hour", opts) ?? listPastThe(
|
|
383
463
|
segmentWords(ir.analyses.segments.minute, opts),
|
|
384
464
|
"minute",
|
|
385
465
|
"hour",
|
|
386
466
|
opts
|
|
387
|
-
)
|
|
467
|
+
)
|
|
388
468
|
);
|
|
469
|
+
const cadence = unevenHourCadence(ir, opts);
|
|
470
|
+
const phrase = cadence ? minuteLead + ", " + cadence + trailingQualifier(ir, opts) : minuteLead + ", at " + hourSegmentTimes(ir, { minute: 0, second: null }, true, opts) + trailingQualifier(ir, opts);
|
|
389
471
|
return ir.analyses.clockSecond ? secondsLeadClause(ir, opts) + ", " + phrase : phrase;
|
|
390
472
|
}
|
|
391
473
|
function foldedHourWindows(ir, plan, opts) {
|
|
@@ -432,24 +514,50 @@ var renderers = {
|
|
|
432
514
|
singleMinute: renderSingleMinute,
|
|
433
515
|
standaloneSeconds: renderStandaloneSeconds
|
|
434
516
|
};
|
|
517
|
+
function renderStride(stride, opts) {
|
|
518
|
+
const { interval, start, last, cycle, unit, anchor } = stride;
|
|
519
|
+
const cadence = "every " + getNumber(interval, opts) + " " + unit + "s";
|
|
520
|
+
const tiles = cycle % interval === 0;
|
|
521
|
+
if (start === 0 && tiles) {
|
|
522
|
+
return cadence;
|
|
523
|
+
}
|
|
524
|
+
if (start < interval && tiles) {
|
|
525
|
+
return cadence + " from " + getNumber(start, opts) + " " + pluralize(start, unit) + " past the " + anchor;
|
|
526
|
+
}
|
|
527
|
+
const num = seriesNumber([start, last], opts);
|
|
528
|
+
return cadence + " from " + num(start) + through(opts) + num(last) + " " + pluralize(last, unit) + " past the " + anchor;
|
|
529
|
+
}
|
|
530
|
+
function singleValues(segments) {
|
|
531
|
+
const values = [];
|
|
532
|
+
for (const segment of segments) {
|
|
533
|
+
if (segment.kind !== "single") {
|
|
534
|
+
return null;
|
|
535
|
+
}
|
|
536
|
+
values.push(+segment.value);
|
|
537
|
+
}
|
|
538
|
+
return values;
|
|
539
|
+
}
|
|
540
|
+
function strideFromSegments(segments, unit, anchor, opts) {
|
|
541
|
+
const values = singleValues(segments);
|
|
542
|
+
const step = values && arithmeticStep(values);
|
|
543
|
+
return step ? renderStride({ ...step, cycle: 60, unit, anchor }, opts) : null;
|
|
544
|
+
}
|
|
435
545
|
function stepCycle60(segment, unit, anchor, opts) {
|
|
436
546
|
if (segment.startToken.indexOf("-") !== -1) {
|
|
437
547
|
return listPastThe(numberWords(segment.fires, opts), unit, anchor, opts);
|
|
438
548
|
}
|
|
439
549
|
const start = segment.startToken === "*" ? 0 : +segment.startToken;
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
if (segment.fires.length <= 3) {
|
|
443
|
-
return listPastThe(
|
|
444
|
-
numberWords(segment.fires, opts),
|
|
445
|
-
unit,
|
|
446
|
-
anchor,
|
|
447
|
-
opts
|
|
448
|
-
);
|
|
449
|
-
}
|
|
450
|
-
return "every " + getNumber(interval, opts) + " " + unit + "s from " + getNumber(start, opts) + " " + pluralize(start, unit) + " past the " + anchor;
|
|
550
|
+
if (start !== 0 && segment.fires.length <= 3) {
|
|
551
|
+
return listPastThe(numberWords(segment.fires, opts), unit, anchor, opts);
|
|
451
552
|
}
|
|
452
|
-
return
|
|
553
|
+
return renderStride({
|
|
554
|
+
interval: segment.interval,
|
|
555
|
+
start,
|
|
556
|
+
last: segment.fires[segment.fires.length - 1],
|
|
557
|
+
cycle: 60,
|
|
558
|
+
unit,
|
|
559
|
+
anchor
|
|
560
|
+
}, opts);
|
|
453
561
|
}
|
|
454
562
|
function stepHours(segment, opts) {
|
|
455
563
|
if (segment.startToken.indexOf("-") !== -1) {
|
|
@@ -465,6 +573,141 @@ function stepHours(segment, opts) {
|
|
|
465
573
|
}
|
|
466
574
|
return "every " + getNumber(interval, opts) + " hours from " + getTime({ hour: start, minute: 0 }, opts);
|
|
467
575
|
}
|
|
576
|
+
function hourStrideCadence(stride, opts) {
|
|
577
|
+
const { start, interval, last } = stride;
|
|
578
|
+
const cadence = "every " + getNumber(interval, opts) + " hours";
|
|
579
|
+
const tiles = 24 % interval === 0;
|
|
580
|
+
if (start === 0 && tiles) {
|
|
581
|
+
return cadence;
|
|
582
|
+
}
|
|
583
|
+
if (start < interval && tiles) {
|
|
584
|
+
return cadence + " from " + getTime({ hour: start, minute: 0 }, opts);
|
|
585
|
+
}
|
|
586
|
+
return cadence + " from " + getTime({ hour: start, minute: 0 }, opts) + through(opts) + getTime({ hour: last, minute: 0 }, opts);
|
|
587
|
+
}
|
|
588
|
+
function offsetCleanStride(stride) {
|
|
589
|
+
return stride.start < stride.interval && 24 % stride.interval === 0;
|
|
590
|
+
}
|
|
591
|
+
function unevenHourCadence(ir, opts) {
|
|
592
|
+
const stride = hourStride(ir);
|
|
593
|
+
if (!stride || offsetCleanStride(stride)) {
|
|
594
|
+
return null;
|
|
595
|
+
}
|
|
596
|
+
return hourStrideCadence(stride, opts);
|
|
597
|
+
}
|
|
598
|
+
function hourListStride(values) {
|
|
599
|
+
if (values.length < 2) {
|
|
600
|
+
return null;
|
|
601
|
+
}
|
|
602
|
+
const interval = values[1] - values[0];
|
|
603
|
+
if (interval < 2) {
|
|
604
|
+
return null;
|
|
605
|
+
}
|
|
606
|
+
for (let i = 2; i < values.length; i += 1) {
|
|
607
|
+
if (values[i] - values[i - 1] !== interval) {
|
|
608
|
+
return null;
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
if (values[0] !== 0 && values.length < 5) {
|
|
612
|
+
return null;
|
|
613
|
+
}
|
|
614
|
+
return { interval, last: values[values.length - 1], start: values[0] };
|
|
615
|
+
}
|
|
616
|
+
function hourStride(ir) {
|
|
617
|
+
const segments = ir.analyses.segments.hour;
|
|
618
|
+
if (segments.length === 1 && segments[0].kind === "step") {
|
|
619
|
+
const segment = segments[0];
|
|
620
|
+
if (segment.fires.length < 2) {
|
|
621
|
+
return null;
|
|
622
|
+
}
|
|
623
|
+
const start = segment.startToken === "*" ? 0 : +segment.startToken.split("-")[0];
|
|
624
|
+
return { interval: segment.interval, last: segment.fires[segment.fires.length - 1], start };
|
|
625
|
+
}
|
|
626
|
+
const values = singleValues(segments);
|
|
627
|
+
return values && hourListStride(values);
|
|
628
|
+
}
|
|
629
|
+
function subMinuteSecond(ir) {
|
|
630
|
+
return ir.pattern.second === "*" || ir.shapes.second === "step";
|
|
631
|
+
}
|
|
632
|
+
function hourCadenceLead(ir, minute, opts) {
|
|
633
|
+
if (minute === 0) {
|
|
634
|
+
if (subMinuteSecond(ir)) {
|
|
635
|
+
return secondsClause(ir, "minute", opts) + " for one minute";
|
|
636
|
+
}
|
|
637
|
+
return secondsClause(ir, "hour", opts);
|
|
638
|
+
}
|
|
639
|
+
const minutePhrase = getNumber(minute, opts) + " " + pluralize(minute, "minute") + " past the hour";
|
|
640
|
+
if (ir.pattern.second === "0") {
|
|
641
|
+
return minutePhrase;
|
|
642
|
+
}
|
|
643
|
+
return secondsClause(ir, "minute", opts) + ", " + minutePhrase;
|
|
644
|
+
}
|
|
645
|
+
function hourCadence(ir, minute, opts) {
|
|
646
|
+
const stride = hourStride(ir);
|
|
647
|
+
if (!stride) {
|
|
648
|
+
return null;
|
|
649
|
+
}
|
|
650
|
+
const fires = (stride.last - stride.start) / stride.interval + 1;
|
|
651
|
+
if (ir.pattern.second === "0" && fires <= maxClockTimes && offsetCleanStride(stride)) {
|
|
652
|
+
return null;
|
|
653
|
+
}
|
|
654
|
+
const confinement = minute === 0 && subMinuteSecond(ir) && cleanStrideSegment(ir);
|
|
655
|
+
if (confinement) {
|
|
656
|
+
return secondsClause(ir, "minute", opts) + " for one minute " + everyNthHour(confinement, opts) + trailingQualifier(ir, opts);
|
|
657
|
+
}
|
|
658
|
+
if (minute === 0 && ir.pattern.second === "0") {
|
|
659
|
+
return hourStrideCadence(stride, opts) + trailingQualifier(ir, opts);
|
|
660
|
+
}
|
|
661
|
+
return hourCadenceLead(ir, minute, opts) + ", " + hourStrideCadence(stride, opts) + trailingQualifier(ir, opts);
|
|
662
|
+
}
|
|
663
|
+
function cleanStrideSegment(ir) {
|
|
664
|
+
const segments = ir.analyses.segments.hour;
|
|
665
|
+
const segment = segments.length === 1 && segments[0];
|
|
666
|
+
if (!segment || segment.kind !== "step" || segment.startToken.indexOf("-") !== -1 || !(segment.interval in stepOrdinals)) {
|
|
667
|
+
return null;
|
|
668
|
+
}
|
|
669
|
+
return segment;
|
|
670
|
+
}
|
|
671
|
+
function hasHourWindow(ir) {
|
|
672
|
+
return ir.analyses.segments.hour.some(function range(segment) {
|
|
673
|
+
return segment.kind === "range";
|
|
674
|
+
});
|
|
675
|
+
}
|
|
676
|
+
function hourRangeWindowTail(ir, opts) {
|
|
677
|
+
const windows = [];
|
|
678
|
+
const singles = [];
|
|
679
|
+
ir.analyses.segments.hour.forEach(function classify(segment) {
|
|
680
|
+
if (segment.kind === "range") {
|
|
681
|
+
windows.push("from " + getTime(
|
|
682
|
+
{ hour: +segment.bounds[0], minute: 0 },
|
|
683
|
+
opts
|
|
684
|
+
) + through(opts) + getTime({ hour: +segment.bounds[1], minute: 0 }, opts));
|
|
685
|
+
} else if (segment.kind === "step") {
|
|
686
|
+
singles.push(...segment.fires);
|
|
687
|
+
} else {
|
|
688
|
+
singles.push(+segment.value);
|
|
689
|
+
}
|
|
690
|
+
});
|
|
691
|
+
let phrase = "every hour " + joinList(windows, opts);
|
|
692
|
+
if (singles.length) {
|
|
693
|
+
phrase += " and at " + joinList(singles.map(function time(hour) {
|
|
694
|
+
return getTime({ hour, minute: 0 }, opts);
|
|
695
|
+
}), opts);
|
|
696
|
+
}
|
|
697
|
+
return phrase;
|
|
698
|
+
}
|
|
699
|
+
function hourRangeCadence(ir, minute, opts) {
|
|
700
|
+
if (minute !== 0 || !hasHourWindow(ir)) {
|
|
701
|
+
return null;
|
|
702
|
+
}
|
|
703
|
+
if (ir.pattern.second === "0") {
|
|
704
|
+
return null;
|
|
705
|
+
}
|
|
706
|
+
if (subMinuteSecond(ir)) {
|
|
707
|
+
return secondsClause(ir, "minute", opts) + " for one minute during the " + hourSegmentTimes(ir, { minute: 0, second: null }, false, opts) + " hours" + trailingQualifier(ir, opts);
|
|
708
|
+
}
|
|
709
|
+
return hourCadenceLead(ir, minute, opts) + ", " + hourRangeWindowTail(ir, opts) + trailingQualifier(ir, opts);
|
|
710
|
+
}
|
|
468
711
|
function seriesNumber(values, opts) {
|
|
469
712
|
const anyBig = values.some(function big(v) {
|
|
470
713
|
return +v > 10;
|