cronli5 0.1.5 → 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 +28 -0
- package/cronli5.min.js +2 -2
- package/dist/cronli5.cjs +117 -20
- package/dist/cronli5.js +117 -20
- package/dist/lang/de.cjs +94 -19
- package/dist/lang/de.js +94 -19
- package/dist/lang/en.cjs +117 -20
- package/dist/lang/en.js +117 -20
- package/dist/lang/es.cjs +89 -14
- package/dist/lang/es.js +89 -14
- package/dist/lang/fi.cjs +107 -19
- package/dist/lang/fi.js +107 -19
- package/dist/lang/zh.cjs +90 -53
- package/dist/lang/zh.js +90 -53
- package/package.json +2 -2
- package/src/lang/de/index.ts +238 -51
- package/src/lang/en/index.ts +280 -46
- package/src/lang/es/index.ts +222 -31
- package/src/lang/fi/index.ts +245 -39
- package/src/lang/zh/index.ts +209 -94
package/dist/lang/en.js
CHANGED
|
@@ -175,7 +175,17 @@ function renderSecondsWithinMinute(ir, plan, opts) {
|
|
|
175
175
|
}
|
|
176
176
|
function composeHourCadence(ir, plan, opts) {
|
|
177
177
|
const clockRest = plan.rest.kind === "clockTimes" || plan.rest.kind === "compactClockTimes";
|
|
178
|
-
|
|
178
|
+
if (!clockRest || ir.shapes.minute !== "single") {
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
const minute = +ir.pattern.minute;
|
|
182
|
+
return hourCadence(ir, minute, opts) ?? hourRangeCadence(ir, minute, opts);
|
|
183
|
+
}
|
|
184
|
+
function clockTimesConfinement(ir, rest, opts) {
|
|
185
|
+
if (+rest.times[0].minute === 0 && ir.shapes.minute === "single") {
|
|
186
|
+
return secondsLeadClause(ir, opts) + " for one minute at " + durationHours(ir, rest, opts);
|
|
187
|
+
}
|
|
188
|
+
return secondsLeadClause(ir, opts) + " of " + clockTimesOf(ir, rest, opts);
|
|
179
189
|
}
|
|
180
190
|
function renderComposeSeconds(ir, plan, opts) {
|
|
181
191
|
const cadence = composeHourCadence(ir, plan, opts);
|
|
@@ -183,16 +193,14 @@ function renderComposeSeconds(ir, plan, opts) {
|
|
|
183
193
|
return cadence;
|
|
184
194
|
}
|
|
185
195
|
if (plan.rest.kind === "clockTimes" && (ir.shapes.second === "wildcard" || ir.shapes.second === "step")) {
|
|
186
|
-
|
|
187
|
-
if (+minute === 0) {
|
|
188
|
-
return secondsLeadClause(ir, opts) + " for one minute at " + durationHours(ir, plan.rest, opts);
|
|
189
|
-
}
|
|
190
|
-
return secondsLeadClause(ir, opts) + " of " + clockTimesOf(ir, plan.rest, opts);
|
|
196
|
+
return clockTimesConfinement(ir, plan.rest, opts);
|
|
191
197
|
}
|
|
192
198
|
if (ir.shapes.second === "wildcard" && plan.rest.kind === "minuteFrequency" && plan.rest.hours.kind === "none" && ir.pattern.minute === "*/2") {
|
|
193
199
|
return "every second of every other minute" + trailingQualifier(ir, opts);
|
|
194
200
|
}
|
|
195
|
-
|
|
201
|
+
const restOwnsLead = plan.rest.kind === "compactClockTimes" && ir.analyses.clockSecond;
|
|
202
|
+
const lead = restOwnsLead ? "" : secondsLeadClause(ir, opts) + ", ";
|
|
203
|
+
return lead + render(ir, plan.rest, opts);
|
|
196
204
|
}
|
|
197
205
|
function durationHours(ir, plan, opts) {
|
|
198
206
|
const hours = plan.times.map(function clock(time) {
|
|
@@ -275,7 +283,8 @@ function renderMinuteFrequency(ir, plan, opts) {
|
|
|
275
283
|
opts
|
|
276
284
|
);
|
|
277
285
|
if (plan.hours.kind === "during") {
|
|
278
|
-
|
|
286
|
+
const cadence = unevenHourCadence(ir, opts);
|
|
287
|
+
phrase += cadence ? ", " + cadence : " during the " + hourTimesFromPlan(ir, plan.hours.times, false, opts) + " hours";
|
|
279
288
|
} else if (plan.hours.kind === "window") {
|
|
280
289
|
phrase += " " + hourWindow(plan.hours, opts);
|
|
281
290
|
} else if (plan.hours.kind === "step") {
|
|
@@ -290,10 +299,13 @@ function renderMinuteSpanInHour(ir, plan, opts) {
|
|
|
290
299
|
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);
|
|
291
300
|
}
|
|
292
301
|
function renderMinutesAcrossHours(ir, plan, opts) {
|
|
302
|
+
const cadence = unevenHourCadence(ir, opts);
|
|
293
303
|
if (plan.form === "wildcard") {
|
|
304
|
+
if (cadence !== null) {
|
|
305
|
+
return "every minute, " + cadence + trailingQualifier(ir, opts);
|
|
306
|
+
}
|
|
294
307
|
return "every minute during the " + hourTimesFromPlan(ir, plan.times, false, opts) + " hours" + trailingQualifier(ir, opts);
|
|
295
308
|
}
|
|
296
|
-
const times = hourTimesFromPlan(ir, plan.times, true, opts);
|
|
297
309
|
const lead = plan.form === "range" ? minuteRangeLead(ir.pattern.minute, opts) : (
|
|
298
310
|
// The 'list' form is a minute list, which has segments; an offset/uneven
|
|
299
311
|
// step enumerated to that list reads as a stride.
|
|
@@ -304,6 +316,10 @@ function renderMinutesAcrossHours(ir, plan, opts) {
|
|
|
304
316
|
opts
|
|
305
317
|
)
|
|
306
318
|
);
|
|
319
|
+
if (cadence !== null) {
|
|
320
|
+
return lead + ", " + cadence + trailingQualifier(ir, opts);
|
|
321
|
+
}
|
|
322
|
+
const times = hourTimesFromPlan(ir, plan.times, true, opts);
|
|
307
323
|
return lead + ", at " + times + trailingQualifier(ir, opts);
|
|
308
324
|
}
|
|
309
325
|
var stepOrdinals = {
|
|
@@ -330,7 +346,8 @@ function renderMinuteSpanAcrossHourStep(ir, plan, opts) {
|
|
|
330
346
|
"hour",
|
|
331
347
|
opts
|
|
332
348
|
) : minuteRangeLead(ir.pattern.minute, opts);
|
|
333
|
-
|
|
349
|
+
const cadence = unevenHourCadence(ir, opts);
|
|
350
|
+
return lead + ", " + (cadence ?? stepHours(segment, opts)) + trailingQualifier(ir, opts);
|
|
334
351
|
}
|
|
335
352
|
function minuteRangeLead(minuteField, opts) {
|
|
336
353
|
const bounds = minuteField.split("-");
|
|
@@ -367,6 +384,10 @@ function rangeMinuteLead(ir, opts) {
|
|
|
367
384
|
);
|
|
368
385
|
}
|
|
369
386
|
function renderHourStep(ir, plan, opts) {
|
|
387
|
+
const cadence = unevenHourCadence(ir, opts);
|
|
388
|
+
if (cadence !== null) {
|
|
389
|
+
return cadence + trailingQualifier(ir, opts);
|
|
390
|
+
}
|
|
370
391
|
return stepHours(ir.analyses.segments.hour[0], opts) + trailingQualifier(ir, opts);
|
|
371
392
|
}
|
|
372
393
|
function boundedWindow(plan) {
|
|
@@ -377,7 +398,8 @@ function hourWindow(window, opts) {
|
|
|
377
398
|
}
|
|
378
399
|
function renderClockTimes(ir, plan, opts) {
|
|
379
400
|
if (ir.shapes.minute === "single") {
|
|
380
|
-
const
|
|
401
|
+
const minute = +ir.pattern.minute;
|
|
402
|
+
const cadence = hourCadence(ir, minute, opts) ?? hourRangeCadence(ir, minute, opts);
|
|
381
403
|
if (cadence !== null) {
|
|
382
404
|
return cadence;
|
|
383
405
|
}
|
|
@@ -395,9 +417,9 @@ function renderClockTimes(ir, plan, opts) {
|
|
|
395
417
|
}
|
|
396
418
|
function renderCompactClockTimes(ir, plan, opts) {
|
|
397
419
|
if (plan.fold) {
|
|
398
|
-
const
|
|
399
|
-
if (
|
|
400
|
-
return
|
|
420
|
+
const cadence2 = hourCadence(ir, +plan.minute, opts) ?? hourRangeCadence(ir, +plan.minute, opts);
|
|
421
|
+
if (cadence2 !== null) {
|
|
422
|
+
return cadence2;
|
|
401
423
|
}
|
|
402
424
|
const hasRange = ir.analyses.segments.hour.some(function range(segment) {
|
|
403
425
|
return segment.kind === "range";
|
|
@@ -408,16 +430,18 @@ function renderCompactClockTimes(ir, plan, opts) {
|
|
|
408
430
|
const fold = { minute: plan.minute, second: ir.analyses.clockSecond };
|
|
409
431
|
return interpretDayQualifier(ir, opts) + "at " + hourSegmentTimes(ir, fold, true, opts);
|
|
410
432
|
}
|
|
411
|
-
const
|
|
433
|
+
const minuteLead = (
|
|
412
434
|
// The non-fold branch is a minute list, which has segments. An
|
|
413
435
|
// offset/uneven step enumerated to that list reads as a stride.
|
|
414
|
-
|
|
436
|
+
strideFromSegments(ir.analyses.segments.minute, "minute", "hour", opts) ?? listPastThe(
|
|
415
437
|
segmentWords(ir.analyses.segments.minute, opts),
|
|
416
438
|
"minute",
|
|
417
439
|
"hour",
|
|
418
440
|
opts
|
|
419
|
-
)
|
|
441
|
+
)
|
|
420
442
|
);
|
|
443
|
+
const cadence = unevenHourCadence(ir, opts);
|
|
444
|
+
const phrase = cadence ? minuteLead + ", " + cadence + trailingQualifier(ir, opts) : minuteLead + ", at " + hourSegmentTimes(ir, { minute: 0, second: null }, true, opts) + trailingQualifier(ir, opts);
|
|
421
445
|
return ir.analyses.clockSecond ? secondsLeadClause(ir, opts) + ", " + phrase : phrase;
|
|
422
446
|
}
|
|
423
447
|
function foldedHourWindows(ir, plan, opts) {
|
|
@@ -535,16 +559,46 @@ function hourStrideCadence(stride, opts) {
|
|
|
535
559
|
}
|
|
536
560
|
return cadence + " from " + getTime({ hour: start, minute: 0 }, opts) + through(opts) + getTime({ hour: last, minute: 0 }, opts);
|
|
537
561
|
}
|
|
562
|
+
function offsetCleanStride(stride) {
|
|
563
|
+
return stride.start < stride.interval && 24 % stride.interval === 0;
|
|
564
|
+
}
|
|
565
|
+
function unevenHourCadence(ir, opts) {
|
|
566
|
+
const stride = hourStride(ir);
|
|
567
|
+
if (!stride || offsetCleanStride(stride)) {
|
|
568
|
+
return null;
|
|
569
|
+
}
|
|
570
|
+
return hourStrideCadence(stride, opts);
|
|
571
|
+
}
|
|
572
|
+
function hourListStride(values) {
|
|
573
|
+
if (values.length < 2) {
|
|
574
|
+
return null;
|
|
575
|
+
}
|
|
576
|
+
const interval = values[1] - values[0];
|
|
577
|
+
if (interval < 2) {
|
|
578
|
+
return null;
|
|
579
|
+
}
|
|
580
|
+
for (let i = 2; i < values.length; i += 1) {
|
|
581
|
+
if (values[i] - values[i - 1] !== interval) {
|
|
582
|
+
return null;
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
if (values[0] !== 0 && values.length < 5) {
|
|
586
|
+
return null;
|
|
587
|
+
}
|
|
588
|
+
return { interval, last: values[values.length - 1], start: values[0] };
|
|
589
|
+
}
|
|
538
590
|
function hourStride(ir) {
|
|
539
591
|
const segments = ir.analyses.segments.hour;
|
|
540
592
|
if (segments.length === 1 && segments[0].kind === "step") {
|
|
541
593
|
const segment = segments[0];
|
|
594
|
+
if (segment.fires.length < 2) {
|
|
595
|
+
return null;
|
|
596
|
+
}
|
|
542
597
|
const start = segment.startToken === "*" ? 0 : +segment.startToken.split("-")[0];
|
|
543
598
|
return { interval: segment.interval, last: segment.fires[segment.fires.length - 1], start };
|
|
544
599
|
}
|
|
545
600
|
const values = singleValues(segments);
|
|
546
|
-
|
|
547
|
-
return step || null;
|
|
601
|
+
return values && hourListStride(values);
|
|
548
602
|
}
|
|
549
603
|
function subMinuteSecond(ir) {
|
|
550
604
|
return ir.pattern.second === "*" || ir.shapes.second === "step";
|
|
@@ -568,13 +622,16 @@ function hourCadence(ir, minute, opts) {
|
|
|
568
622
|
return null;
|
|
569
623
|
}
|
|
570
624
|
const fires = (stride.last - stride.start) / stride.interval + 1;
|
|
571
|
-
if (ir.pattern.second === "0" && fires <= maxClockTimes) {
|
|
625
|
+
if (ir.pattern.second === "0" && fires <= maxClockTimes && offsetCleanStride(stride)) {
|
|
572
626
|
return null;
|
|
573
627
|
}
|
|
574
628
|
const confinement = minute === 0 && subMinuteSecond(ir) && cleanStrideSegment(ir);
|
|
575
629
|
if (confinement) {
|
|
576
630
|
return secondsClause(ir, "minute", opts) + " for one minute " + everyNthHour(confinement, opts) + trailingQualifier(ir, opts);
|
|
577
631
|
}
|
|
632
|
+
if (minute === 0 && ir.pattern.second === "0") {
|
|
633
|
+
return hourStrideCadence(stride, opts) + trailingQualifier(ir, opts);
|
|
634
|
+
}
|
|
578
635
|
return hourCadenceLead(ir, minute, opts) + ", " + hourStrideCadence(stride, opts) + trailingQualifier(ir, opts);
|
|
579
636
|
}
|
|
580
637
|
function cleanStrideSegment(ir) {
|
|
@@ -585,6 +642,46 @@ function cleanStrideSegment(ir) {
|
|
|
585
642
|
}
|
|
586
643
|
return segment;
|
|
587
644
|
}
|
|
645
|
+
function hasHourWindow(ir) {
|
|
646
|
+
return ir.analyses.segments.hour.some(function range(segment) {
|
|
647
|
+
return segment.kind === "range";
|
|
648
|
+
});
|
|
649
|
+
}
|
|
650
|
+
function hourRangeWindowTail(ir, opts) {
|
|
651
|
+
const windows = [];
|
|
652
|
+
const singles = [];
|
|
653
|
+
ir.analyses.segments.hour.forEach(function classify(segment) {
|
|
654
|
+
if (segment.kind === "range") {
|
|
655
|
+
windows.push("from " + getTime(
|
|
656
|
+
{ hour: +segment.bounds[0], minute: 0 },
|
|
657
|
+
opts
|
|
658
|
+
) + through(opts) + getTime({ hour: +segment.bounds[1], minute: 0 }, opts));
|
|
659
|
+
} else if (segment.kind === "step") {
|
|
660
|
+
singles.push(...segment.fires);
|
|
661
|
+
} else {
|
|
662
|
+
singles.push(+segment.value);
|
|
663
|
+
}
|
|
664
|
+
});
|
|
665
|
+
let phrase = "every hour " + joinList(windows, opts);
|
|
666
|
+
if (singles.length) {
|
|
667
|
+
phrase += " and at " + joinList(singles.map(function time(hour) {
|
|
668
|
+
return getTime({ hour, minute: 0 }, opts);
|
|
669
|
+
}), opts);
|
|
670
|
+
}
|
|
671
|
+
return phrase;
|
|
672
|
+
}
|
|
673
|
+
function hourRangeCadence(ir, minute, opts) {
|
|
674
|
+
if (minute !== 0 || !hasHourWindow(ir)) {
|
|
675
|
+
return null;
|
|
676
|
+
}
|
|
677
|
+
if (ir.pattern.second === "0") {
|
|
678
|
+
return null;
|
|
679
|
+
}
|
|
680
|
+
if (subMinuteSecond(ir)) {
|
|
681
|
+
return secondsClause(ir, "minute", opts) + " for one minute during the " + hourSegmentTimes(ir, { minute: 0, second: null }, false, opts) + " hours" + trailingQualifier(ir, opts);
|
|
682
|
+
}
|
|
683
|
+
return hourCadenceLead(ir, minute, opts) + ", " + hourRangeWindowTail(ir, opts) + trailingQualifier(ir, opts);
|
|
684
|
+
}
|
|
588
685
|
function seriesNumber(values, opts) {
|
|
589
686
|
const anyBig = values.some(function big(v) {
|
|
590
687
|
return +v > 10;
|
package/dist/lang/es.cjs
CHANGED
|
@@ -202,14 +202,21 @@ function secondsListAtClock(ir, rest, opts) {
|
|
|
202
202
|
}
|
|
203
203
|
function composeHourCadence(ir, plan, opts) {
|
|
204
204
|
const clockRest = plan.rest.kind === "clockTimes" || plan.rest.kind === "compactClockTimes";
|
|
205
|
-
|
|
205
|
+
if (!clockRest || ir.shapes.minute !== "single") {
|
|
206
|
+
return null;
|
|
207
|
+
}
|
|
208
|
+
const minute = +ir.pattern.minute;
|
|
209
|
+
return hourCadence(ir, minute, opts) ?? hourRangeCadence(ir, minute, opts);
|
|
210
|
+
}
|
|
211
|
+
function isPinnedMinuteSeconds(ir, plan) {
|
|
212
|
+
return plan.rest.kind === "clockTimes" && (ir.shapes.second === "wildcard" || ir.shapes.second === "step");
|
|
206
213
|
}
|
|
207
214
|
function renderComposeSeconds(ir, plan, opts) {
|
|
208
215
|
const hourCad = composeHourCadence(ir, plan, opts);
|
|
209
216
|
if (hourCad !== null) {
|
|
210
217
|
return hourCad;
|
|
211
218
|
}
|
|
212
|
-
if (
|
|
219
|
+
if (isPinnedMinuteSeconds(ir, plan)) {
|
|
213
220
|
return pinnedMinuteSeconds(ir, plan.rest, opts);
|
|
214
221
|
}
|
|
215
222
|
if (plan.rest.kind === "clockTimes" && ir.shapes.second === "list") {
|
|
@@ -225,7 +232,9 @@ function renderComposeSeconds(ir, plan, opts) {
|
|
|
225
232
|
if (isEveryOtherMinuteSeconds(ir, plan)) {
|
|
226
233
|
return secondsLeadClause(ir, opts) + " de " + render(ir, plan.rest, opts);
|
|
227
234
|
}
|
|
228
|
-
|
|
235
|
+
const restOwnsLead = plan.rest.kind === "compactClockTimes" && ir.analyses.clockSecond;
|
|
236
|
+
const lead = restOwnsLead ? "" : secondsLeadClause(ir, opts) + ", ";
|
|
237
|
+
return lead + render(ir, plan.rest, opts);
|
|
229
238
|
}
|
|
230
239
|
function isEveryOtherMinuteSeconds(ir, plan) {
|
|
231
240
|
if (plan.rest.kind !== "minuteFrequency" || ir.shapes.second !== "wildcard" || ir.shapes.hour !== "wildcard") {
|
|
@@ -237,7 +246,7 @@ function isEveryOtherMinuteSeconds(ir, plan) {
|
|
|
237
246
|
function pinnedMinuteSeconds(ir, rest, opts) {
|
|
238
247
|
const dayTrail = leadingQualifier(ir, opts).trimEnd();
|
|
239
248
|
const trail = dayTrail ? ", " + dayTrail : "";
|
|
240
|
-
if (+rest.times[0].minute === 0) {
|
|
249
|
+
if (+rest.times[0].minute === 0 && ir.shapes.minute === "single") {
|
|
241
250
|
return secondsLeadClause(ir, opts) + " durante un minuto " + durationHourList(rest.times, opts) + trail;
|
|
242
251
|
}
|
|
243
252
|
return secondsLeadClause(ir, opts) + " de " + explicitClockList(rest.times, opts) + trail;
|
|
@@ -354,7 +363,12 @@ function renderMinuteFrequency(ir, plan, opts) {
|
|
|
354
363
|
opts
|
|
355
364
|
);
|
|
356
365
|
if (plan.hours.kind === "during") {
|
|
357
|
-
|
|
366
|
+
const cadence = unevenHourCadence(ir, opts);
|
|
367
|
+
if (cadence) {
|
|
368
|
+
phrase += ", " + cadence;
|
|
369
|
+
} else {
|
|
370
|
+
phrase += singleHourStep(ir.analyses.segments.hour) ? ", " + stepHourSpan(stepSegment(ir.analyses.segments.hour), opts) : " " + hourSpanFromTimes(ir, plan.hours.times, opts);
|
|
371
|
+
}
|
|
358
372
|
} else if (plan.hours.kind === "window") {
|
|
359
373
|
phrase += " " + hourWindow(plan.hours, opts);
|
|
360
374
|
} else if (plan.hours.kind === "step") {
|
|
@@ -373,22 +387,30 @@ function renderMinuteSpanInHour(ir, plan, opts) {
|
|
|
373
387
|
) + trailingQualifier(ir, opts);
|
|
374
388
|
}
|
|
375
389
|
function renderMinutesAcrossHours(ir, plan, opts) {
|
|
390
|
+
const cadence = unevenHourCadence(ir, opts);
|
|
376
391
|
if (plan.form === "wildcard") {
|
|
392
|
+
if (cadence !== null) {
|
|
393
|
+
return "cada minuto, " + cadence + trailingQualifier(ir, opts);
|
|
394
|
+
}
|
|
377
395
|
if (singleHourStep(ir.analyses.segments.hour)) {
|
|
378
396
|
return "cada minuto, " + stepHourSpan(stepSegment(ir.analyses.segments.hour), opts) + trailingQualifier(ir, opts);
|
|
379
397
|
}
|
|
380
398
|
return "cada minuto " + hourSpanFromTimes(ir, plan.times, opts) + trailingQualifier(ir, opts);
|
|
381
399
|
}
|
|
382
400
|
const lead = plan.form === "range" ? minuteRangeLead(ir.pattern.minute) : minutesList(ir, opts);
|
|
401
|
+
if (cadence !== null) {
|
|
402
|
+
return lead + ", " + cadence + trailingQualifier(ir, opts);
|
|
403
|
+
}
|
|
383
404
|
return lead + ", " + atHourTimes(ir, plan.times, opts) + trailingQualifier(ir, opts);
|
|
384
405
|
}
|
|
385
406
|
function renderMinuteSpanAcrossHourStep(ir, plan, opts) {
|
|
386
407
|
const segment = stepSegment(ir.analyses.segments.hour);
|
|
408
|
+
const cadence = unevenHourCadence(ir, opts);
|
|
387
409
|
if (plan.form === "wildcard") {
|
|
388
410
|
return "cada minuto, " + stepHourSpan(segment, opts) + trailingQualifier(ir, opts);
|
|
389
411
|
}
|
|
390
412
|
const lead = plan.form === "list" ? minutesList(ir, opts) : minuteRangeLead(ir.pattern.minute);
|
|
391
|
-
return lead + ", " + stepHours(segment, opts) + trailingQualifier(ir, opts);
|
|
413
|
+
return lead + ", " + (cadence ?? stepHours(segment, opts)) + trailingQualifier(ir, opts);
|
|
392
414
|
}
|
|
393
415
|
function renderEveryHour(ir, plan, opts) {
|
|
394
416
|
return "cada hora" + trailingQualifier(ir, opts);
|
|
@@ -408,6 +430,10 @@ function renderHourRange(ir, plan, opts) {
|
|
|
408
430
|
return lead + ", " + window + trailingQualifier(ir, opts);
|
|
409
431
|
}
|
|
410
432
|
function renderHourStep(ir, plan, opts) {
|
|
433
|
+
const cadence = unevenHourCadence(ir, opts);
|
|
434
|
+
if (cadence !== null) {
|
|
435
|
+
return cadence + trailingQualifier(ir, opts);
|
|
436
|
+
}
|
|
411
437
|
return stepHours(stepSegment(ir.analyses.segments.hour), opts) + trailingQualifier(ir, opts);
|
|
412
438
|
}
|
|
413
439
|
function boundedWindow(plan) {
|
|
@@ -479,7 +505,8 @@ function unionYaseaSuffix(ir, opts) {
|
|
|
479
505
|
}
|
|
480
506
|
function renderClockTimes(ir, plan, opts) {
|
|
481
507
|
if (ir.shapes.minute === "single") {
|
|
482
|
-
const
|
|
508
|
+
const minute = +ir.pattern.minute;
|
|
509
|
+
const cadence = hourCadence(ir, minute, opts) ?? hourRangeCadence(ir, minute, opts);
|
|
483
510
|
if (cadence !== null) {
|
|
484
511
|
return cadence;
|
|
485
512
|
}
|
|
@@ -665,9 +692,9 @@ function groupClockTimesByArticle(phrases) {
|
|
|
665
692
|
}
|
|
666
693
|
function renderCompactClockTimes(ir, plan, opts) {
|
|
667
694
|
if (plan.fold) {
|
|
668
|
-
const
|
|
669
|
-
if (
|
|
670
|
-
return
|
|
695
|
+
const cadence2 = hourCadence(ir, plan.minute, opts) ?? hourRangeCadence(ir, plan.minute, opts);
|
|
696
|
+
if (cadence2 !== null) {
|
|
697
|
+
return cadence2;
|
|
671
698
|
}
|
|
672
699
|
const ranged = hourSegments(ir).some(function range(segment) {
|
|
673
700
|
return segment.kind === "range";
|
|
@@ -677,7 +704,8 @@ function renderCompactClockTimes(ir, plan, opts) {
|
|
|
677
704
|
}
|
|
678
705
|
return leadingQualifier(ir, opts) + hourSegmentTimes(ir, plan.minute, ir.analyses.clockSecond, opts);
|
|
679
706
|
}
|
|
680
|
-
const
|
|
707
|
+
const cadence = unevenHourCadence(ir, opts);
|
|
708
|
+
const phrase = cadence ? minutesList(ir, opts) + ", " + cadence + trailingQualifier(ir, opts) : minutesList(ir, opts) + ", " + hourSegmentTimes(ir, 0, null, opts) + trailingQualifier(ir, opts);
|
|
681
709
|
return ir.analyses.clockSecond ? secondsLeadClause(ir, opts) + ", " + phrase : phrase;
|
|
682
710
|
}
|
|
683
711
|
var renderers = {
|
|
@@ -771,16 +799,46 @@ function hourStrideCadence(stride, opts) {
|
|
|
771
799
|
}
|
|
772
800
|
return cadence + " de " + timePhrase(start, 0, null, opts) + " a " + timePhrase(last, 0, null, opts);
|
|
773
801
|
}
|
|
802
|
+
function offsetCleanStride(stride) {
|
|
803
|
+
return stride.start < stride.interval && 24 % stride.interval === 0;
|
|
804
|
+
}
|
|
805
|
+
function unevenHourCadence(ir, opts) {
|
|
806
|
+
const stride = hourStride(ir);
|
|
807
|
+
if (!stride || offsetCleanStride(stride)) {
|
|
808
|
+
return null;
|
|
809
|
+
}
|
|
810
|
+
return hourStrideCadence(stride, opts);
|
|
811
|
+
}
|
|
812
|
+
function hourListStride(values) {
|
|
813
|
+
if (values.length < 2) {
|
|
814
|
+
return null;
|
|
815
|
+
}
|
|
816
|
+
const interval = values[1] - values[0];
|
|
817
|
+
if (interval < 2) {
|
|
818
|
+
return null;
|
|
819
|
+
}
|
|
820
|
+
for (let i = 2; i < values.length; i += 1) {
|
|
821
|
+
if (values[i] - values[i - 1] !== interval) {
|
|
822
|
+
return null;
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
if (values[0] !== 0 && values.length < 5) {
|
|
826
|
+
return null;
|
|
827
|
+
}
|
|
828
|
+
return { interval, last: values[values.length - 1], start: values[0] };
|
|
829
|
+
}
|
|
774
830
|
function hourStride(ir) {
|
|
775
831
|
const segments = fieldSegments(ir, "hour");
|
|
776
832
|
if (segments.length === 1 && segments[0].kind === "step") {
|
|
777
833
|
const segment = segments[0];
|
|
834
|
+
if (segment.fires.length < 2) {
|
|
835
|
+
return null;
|
|
836
|
+
}
|
|
778
837
|
const start = segment.startToken === "*" ? 0 : +segment.startToken.split("-")[0];
|
|
779
838
|
return { interval: segment.interval, last: segment.fires[segment.fires.length - 1], start };
|
|
780
839
|
}
|
|
781
840
|
const values = singleValues(segments);
|
|
782
|
-
|
|
783
|
-
return step || null;
|
|
841
|
+
return values && hourListStride(values);
|
|
784
842
|
}
|
|
785
843
|
function subMinuteSecond(ir) {
|
|
786
844
|
return ir.pattern.second === "*" || ir.shapes.second === "step";
|
|
@@ -804,13 +862,16 @@ function hourCadence(ir, minute, opts) {
|
|
|
804
862
|
return null;
|
|
805
863
|
}
|
|
806
864
|
const fires = (stride.last - stride.start) / stride.interval + 1;
|
|
807
|
-
if (ir.pattern.second === "0" && fires <= maxClockTimes) {
|
|
865
|
+
if (ir.pattern.second === "0" && fires <= maxClockTimes && offsetCleanStride(stride)) {
|
|
808
866
|
return null;
|
|
809
867
|
}
|
|
810
868
|
const confinement = minute === 0 && subMinuteSecond(ir) && cleanStrideSegment(ir);
|
|
811
869
|
if (confinement) {
|
|
812
870
|
return secondsClause(ir, "minuto", opts) + " durante un minuto, " + stepHourSpan(confinement, opts) + trailingQualifier(ir, opts);
|
|
813
871
|
}
|
|
872
|
+
if (minute === 0 && ir.pattern.second === "0") {
|
|
873
|
+
return hourStrideCadence(stride, opts) + trailingQualifier(ir, opts);
|
|
874
|
+
}
|
|
814
875
|
return hourCadenceLead(ir, minute, opts) + ", " + hourStrideCadence(stride, opts) + trailingQualifier(ir, opts);
|
|
815
876
|
}
|
|
816
877
|
function cleanStrideSegment(ir) {
|
|
@@ -821,6 +882,20 @@ function cleanStrideSegment(ir) {
|
|
|
821
882
|
}
|
|
822
883
|
return segment;
|
|
823
884
|
}
|
|
885
|
+
function hasHourWindow(ir) {
|
|
886
|
+
return hourSegments(ir).some(function range(segment) {
|
|
887
|
+
return segment.kind === "range";
|
|
888
|
+
});
|
|
889
|
+
}
|
|
890
|
+
function hourRangeCadence(ir, minute, opts) {
|
|
891
|
+
if (minute !== 0 || !hasHourWindow(ir) || ir.pattern.second === "0") {
|
|
892
|
+
return null;
|
|
893
|
+
}
|
|
894
|
+
if (subMinuteSecond(ir)) {
|
|
895
|
+
return secondsClause(ir, "minuto", opts) + " durante un minuto, durante las horas " + hourSegmentTimes(ir, 0, null, opts) + trailingQualifier(ir, opts);
|
|
896
|
+
}
|
|
897
|
+
return hourCadenceLead(ir, minute, opts) + ", " + hourSegmentTimes(ir, 0, null, opts) + trailingQualifier(ir, opts);
|
|
898
|
+
}
|
|
824
899
|
function atTimes(hours, opts) {
|
|
825
900
|
return hours.map(function each(hour) {
|
|
826
901
|
return atTime(timePhrase(hour, 0, null, opts));
|