cronli5 0.1.5 → 0.1.7
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 +71 -0
- package/README.md +2 -2
- package/cronli5.min.js +2 -2
- package/dist/cronli5.cjs +156 -27
- package/dist/cronli5.js +156 -27
- package/dist/lang/de.cjs +157 -36
- package/dist/lang/de.js +157 -36
- package/dist/lang/en.cjs +156 -27
- package/dist/lang/en.js +156 -27
- package/dist/lang/es.cjs +156 -18
- package/dist/lang/es.js +156 -18
- package/dist/lang/fi.cjs +128 -20
- package/dist/lang/fi.js +128 -20
- package/dist/lang/zh.cjs +126 -58
- package/dist/lang/zh.js +126 -58
- package/package.json +2 -2
- package/src/core/util.ts +52 -1
- package/src/lang/de/index.ts +331 -74
- package/src/lang/en/index.ts +327 -62
- package/src/lang/es/index.ts +306 -39
- package/src/lang/fi/index.ts +251 -41
- package/src/lang/zh/index.ts +246 -105
- package/types/core/util.d.ts +10 -1
package/dist/lang/es.cjs
CHANGED
|
@@ -72,6 +72,26 @@ function arithmeticStep(values) {
|
|
|
72
72
|
}
|
|
73
73
|
return { start: values[0], interval, last: values[values.length - 1] };
|
|
74
74
|
}
|
|
75
|
+
function weekdayDisplayKey(value) {
|
|
76
|
+
return value === 0 ? 7 : value;
|
|
77
|
+
}
|
|
78
|
+
function orderWeekdaysForDisplay(segments) {
|
|
79
|
+
const flattened = segments.flatMap(function flat(segment) {
|
|
80
|
+
return segment.kind === "step" ? segment.fires.map(function single(value) {
|
|
81
|
+
return { kind: "single", value: "" + value };
|
|
82
|
+
}) : [segment];
|
|
83
|
+
});
|
|
84
|
+
function key(segment) {
|
|
85
|
+
return segment.kind === "range" ? weekdayDisplayKey(+segment.bounds[0]) : weekdayDisplayKey(+segment.value);
|
|
86
|
+
}
|
|
87
|
+
return flattened.map(function index(segment, position) {
|
|
88
|
+
return [segment, position];
|
|
89
|
+
}).sort(function byDisplayKey(a, b) {
|
|
90
|
+
return key(a[0]) - key(b[0]) || a[1] - b[1];
|
|
91
|
+
}).map(function unwrap(pair) {
|
|
92
|
+
return pair[0];
|
|
93
|
+
});
|
|
94
|
+
}
|
|
75
95
|
function toFieldNumber(token, numberMap) {
|
|
76
96
|
return isNonNegativeInteger(token) ? +token : numberMap[token.toUpperCase()];
|
|
77
97
|
}
|
|
@@ -202,14 +222,21 @@ function secondsListAtClock(ir, rest, opts) {
|
|
|
202
222
|
}
|
|
203
223
|
function composeHourCadence(ir, plan, opts) {
|
|
204
224
|
const clockRest = plan.rest.kind === "clockTimes" || plan.rest.kind === "compactClockTimes";
|
|
205
|
-
|
|
225
|
+
if (!clockRest || ir.shapes.minute !== "single") {
|
|
226
|
+
return null;
|
|
227
|
+
}
|
|
228
|
+
const minute = +ir.pattern.minute;
|
|
229
|
+
return hourCadence(ir, minute, opts) ?? hourRangeCadence(ir, minute, opts);
|
|
230
|
+
}
|
|
231
|
+
function isPinnedMinuteSeconds(ir, plan) {
|
|
232
|
+
return plan.rest.kind === "clockTimes" && (ir.shapes.second === "wildcard" || ir.shapes.second === "step");
|
|
206
233
|
}
|
|
207
234
|
function renderComposeSeconds(ir, plan, opts) {
|
|
208
235
|
const hourCad = composeHourCadence(ir, plan, opts);
|
|
209
236
|
if (hourCad !== null) {
|
|
210
237
|
return hourCad;
|
|
211
238
|
}
|
|
212
|
-
if (
|
|
239
|
+
if (isPinnedMinuteSeconds(ir, plan)) {
|
|
213
240
|
return pinnedMinuteSeconds(ir, plan.rest, opts);
|
|
214
241
|
}
|
|
215
242
|
if (plan.rest.kind === "clockTimes" && ir.shapes.second === "list") {
|
|
@@ -217,7 +244,7 @@ function renderComposeSeconds(ir, plan, opts) {
|
|
|
217
244
|
}
|
|
218
245
|
if (plan.rest.kind === "hourRange" && ir.shapes.second === "step" && ir.pattern.weekday !== "*") {
|
|
219
246
|
const restNode = plan.rest;
|
|
220
|
-
const window = hourWindow(restNode, opts);
|
|
247
|
+
const window = hourWindow(boundedWindow(restNode), opts);
|
|
221
248
|
const dayFrame = weekdayQualifier(ir) + monthScope(ir);
|
|
222
249
|
const cadence = "cada " + numero(stepSegment(ir.analyses.segments.second).interval, opts) + " segundos del minuto " + ir.pattern.minute;
|
|
223
250
|
return dayFrame + ", " + window + ", " + cadence;
|
|
@@ -225,7 +252,9 @@ function renderComposeSeconds(ir, plan, opts) {
|
|
|
225
252
|
if (isEveryOtherMinuteSeconds(ir, plan)) {
|
|
226
253
|
return secondsLeadClause(ir, opts) + " de " + render(ir, plan.rest, opts);
|
|
227
254
|
}
|
|
228
|
-
|
|
255
|
+
const restOwnsLead = plan.rest.kind === "compactClockTimes" && ir.analyses.clockSecond;
|
|
256
|
+
const lead = restOwnsLead ? "" : secondsLeadClause(ir, opts) + ", ";
|
|
257
|
+
return lead + render(ir, plan.rest, opts);
|
|
229
258
|
}
|
|
230
259
|
function isEveryOtherMinuteSeconds(ir, plan) {
|
|
231
260
|
if (plan.rest.kind !== "minuteFrequency" || ir.shapes.second !== "wildcard" || ir.shapes.hour !== "wildcard") {
|
|
@@ -237,7 +266,7 @@ function isEveryOtherMinuteSeconds(ir, plan) {
|
|
|
237
266
|
function pinnedMinuteSeconds(ir, rest, opts) {
|
|
238
267
|
const dayTrail = leadingQualifier(ir, opts).trimEnd();
|
|
239
268
|
const trail = dayTrail ? ", " + dayTrail : "";
|
|
240
|
-
if (+rest.times[0].minute === 0) {
|
|
269
|
+
if (+rest.times[0].minute === 0 && ir.shapes.minute === "single") {
|
|
241
270
|
return secondsLeadClause(ir, opts) + " durante un minuto " + durationHourList(rest.times, opts) + trail;
|
|
242
271
|
}
|
|
243
272
|
return secondsLeadClause(ir, opts) + " de " + explicitClockList(rest.times, opts) + trail;
|
|
@@ -354,7 +383,12 @@ function renderMinuteFrequency(ir, plan, opts) {
|
|
|
354
383
|
opts
|
|
355
384
|
);
|
|
356
385
|
if (plan.hours.kind === "during") {
|
|
357
|
-
|
|
386
|
+
const cadence = unevenHourCadence(ir, opts);
|
|
387
|
+
if (cadence) {
|
|
388
|
+
phrase += ", " + cadence;
|
|
389
|
+
} else {
|
|
390
|
+
phrase += singleHourStep(ir.analyses.segments.hour) ? ", " + stepHourSpan(stepSegment(ir.analyses.segments.hour), opts) : " " + hourSpanFromTimes(ir, plan.hours.times, opts);
|
|
391
|
+
}
|
|
358
392
|
} else if (plan.hours.kind === "window") {
|
|
359
393
|
phrase += " " + hourWindow(plan.hours, opts);
|
|
360
394
|
} else if (plan.hours.kind === "step") {
|
|
@@ -373,22 +407,30 @@ function renderMinuteSpanInHour(ir, plan, opts) {
|
|
|
373
407
|
) + trailingQualifier(ir, opts);
|
|
374
408
|
}
|
|
375
409
|
function renderMinutesAcrossHours(ir, plan, opts) {
|
|
410
|
+
const cadence = unevenHourCadence(ir, opts);
|
|
376
411
|
if (plan.form === "wildcard") {
|
|
412
|
+
if (cadence !== null) {
|
|
413
|
+
return "cada minuto, " + cadence + trailingQualifier(ir, opts);
|
|
414
|
+
}
|
|
377
415
|
if (singleHourStep(ir.analyses.segments.hour)) {
|
|
378
416
|
return "cada minuto, " + stepHourSpan(stepSegment(ir.analyses.segments.hour), opts) + trailingQualifier(ir, opts);
|
|
379
417
|
}
|
|
380
418
|
return "cada minuto " + hourSpanFromTimes(ir, plan.times, opts) + trailingQualifier(ir, opts);
|
|
381
419
|
}
|
|
382
420
|
const lead = plan.form === "range" ? minuteRangeLead(ir.pattern.minute) : minutesList(ir, opts);
|
|
421
|
+
if (cadence !== null) {
|
|
422
|
+
return lead + ", " + cadence + trailingQualifier(ir, opts);
|
|
423
|
+
}
|
|
383
424
|
return lead + ", " + atHourTimes(ir, plan.times, opts) + trailingQualifier(ir, opts);
|
|
384
425
|
}
|
|
385
426
|
function renderMinuteSpanAcrossHourStep(ir, plan, opts) {
|
|
386
427
|
const segment = stepSegment(ir.analyses.segments.hour);
|
|
428
|
+
const cadence = unevenHourCadence(ir, opts);
|
|
387
429
|
if (plan.form === "wildcard") {
|
|
388
430
|
return "cada minuto, " + stepHourSpan(segment, opts) + trailingQualifier(ir, opts);
|
|
389
431
|
}
|
|
390
432
|
const lead = plan.form === "list" ? minutesList(ir, opts) : minuteRangeLead(ir.pattern.minute);
|
|
391
|
-
return lead + ", " + stepHours(segment, opts) + trailingQualifier(ir, opts);
|
|
433
|
+
return lead + ", " + (cadence ?? stepHours(segment, opts)) + trailingQualifier(ir, opts);
|
|
392
434
|
}
|
|
393
435
|
function renderEveryHour(ir, plan, opts) {
|
|
394
436
|
return "cada hora" + trailingQualifier(ir, opts);
|
|
@@ -408,10 +450,15 @@ function renderHourRange(ir, plan, opts) {
|
|
|
408
450
|
return lead + ", " + window + trailingQualifier(ir, opts);
|
|
409
451
|
}
|
|
410
452
|
function renderHourStep(ir, plan, opts) {
|
|
453
|
+
const cadence = unevenHourCadence(ir, opts);
|
|
454
|
+
if (cadence !== null) {
|
|
455
|
+
return cadence + trailingQualifier(ir, opts);
|
|
456
|
+
}
|
|
411
457
|
return stepHours(stepSegment(ir.analyses.segments.hour), opts) + trailingQualifier(ir, opts);
|
|
412
458
|
}
|
|
413
459
|
function boundedWindow(plan) {
|
|
414
|
-
|
|
460
|
+
const last = plan.minuteForm === "wildcard" ? plan.boundMinute ?? 0 : 0;
|
|
461
|
+
return { from: plan.from, last, to: plan.to };
|
|
415
462
|
}
|
|
416
463
|
function hourWindow(window, opts) {
|
|
417
464
|
return timeRange(
|
|
@@ -455,7 +502,7 @@ function dowArm(ir) {
|
|
|
455
502
|
if (quartz) {
|
|
456
503
|
return quartz;
|
|
457
504
|
}
|
|
458
|
-
const segments =
|
|
505
|
+
const segments = orderWeekdaysForDisplay(fieldSegments(ir, "weekday"));
|
|
459
506
|
const allSingles = segments.every(function single(segment) {
|
|
460
507
|
return segment.kind === "single";
|
|
461
508
|
});
|
|
@@ -479,7 +526,8 @@ function unionYaseaSuffix(ir, opts) {
|
|
|
479
526
|
}
|
|
480
527
|
function renderClockTimes(ir, plan, opts) {
|
|
481
528
|
if (ir.shapes.minute === "single") {
|
|
482
|
-
const
|
|
529
|
+
const minute = +ir.pattern.minute;
|
|
530
|
+
const cadence = hourCadence(ir, minute, opts) ?? hourRangeCadence(ir, minute, opts);
|
|
483
531
|
if (cadence !== null) {
|
|
484
532
|
return cadence;
|
|
485
533
|
}
|
|
@@ -665,9 +713,9 @@ function groupClockTimesByArticle(phrases) {
|
|
|
665
713
|
}
|
|
666
714
|
function renderCompactClockTimes(ir, plan, opts) {
|
|
667
715
|
if (plan.fold) {
|
|
668
|
-
const
|
|
669
|
-
if (
|
|
670
|
-
return
|
|
716
|
+
const cadence2 = hourCadence(ir, plan.minute, opts) ?? hourRangeCadence(ir, plan.minute, opts);
|
|
717
|
+
if (cadence2 !== null) {
|
|
718
|
+
return cadence2;
|
|
671
719
|
}
|
|
672
720
|
const ranged = hourSegments(ir).some(function range(segment) {
|
|
673
721
|
return segment.kind === "range";
|
|
@@ -677,7 +725,8 @@ function renderCompactClockTimes(ir, plan, opts) {
|
|
|
677
725
|
}
|
|
678
726
|
return leadingQualifier(ir, opts) + hourSegmentTimes(ir, plan.minute, ir.analyses.clockSecond, opts);
|
|
679
727
|
}
|
|
680
|
-
const
|
|
728
|
+
const cadence = unevenHourCadence(ir, opts);
|
|
729
|
+
const phrase = cadence ? minutesList(ir, opts) + ", " + cadence + trailingQualifier(ir, opts) : minutesList(ir, opts) + ", " + hourContextTimes(ir, opts) + trailingQualifier(ir, opts);
|
|
681
730
|
return ir.analyses.clockSecond ? secondsLeadClause(ir, opts) + ", " + phrase : phrase;
|
|
682
731
|
}
|
|
683
732
|
var renderers = {
|
|
@@ -771,16 +820,46 @@ function hourStrideCadence(stride, opts) {
|
|
|
771
820
|
}
|
|
772
821
|
return cadence + " de " + timePhrase(start, 0, null, opts) + " a " + timePhrase(last, 0, null, opts);
|
|
773
822
|
}
|
|
823
|
+
function offsetCleanStride(stride) {
|
|
824
|
+
return stride.start < stride.interval && 24 % stride.interval === 0;
|
|
825
|
+
}
|
|
826
|
+
function unevenHourCadence(ir, opts) {
|
|
827
|
+
const stride = hourStride(ir);
|
|
828
|
+
if (!stride || offsetCleanStride(stride)) {
|
|
829
|
+
return null;
|
|
830
|
+
}
|
|
831
|
+
return hourStrideCadence(stride, opts);
|
|
832
|
+
}
|
|
833
|
+
function hourListStride(values) {
|
|
834
|
+
if (values.length < 2) {
|
|
835
|
+
return null;
|
|
836
|
+
}
|
|
837
|
+
const interval = values[1] - values[0];
|
|
838
|
+
if (interval < 2) {
|
|
839
|
+
return null;
|
|
840
|
+
}
|
|
841
|
+
for (let i = 2; i < values.length; i += 1) {
|
|
842
|
+
if (values[i] - values[i - 1] !== interval) {
|
|
843
|
+
return null;
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
if (values[0] !== 0 && values.length < 5) {
|
|
847
|
+
return null;
|
|
848
|
+
}
|
|
849
|
+
return { interval, last: values[values.length - 1], start: values[0] };
|
|
850
|
+
}
|
|
774
851
|
function hourStride(ir) {
|
|
775
852
|
const segments = fieldSegments(ir, "hour");
|
|
776
853
|
if (segments.length === 1 && segments[0].kind === "step") {
|
|
777
854
|
const segment = segments[0];
|
|
855
|
+
if (segment.fires.length < 2) {
|
|
856
|
+
return null;
|
|
857
|
+
}
|
|
778
858
|
const start = segment.startToken === "*" ? 0 : +segment.startToken.split("-")[0];
|
|
779
859
|
return { interval: segment.interval, last: segment.fires[segment.fires.length - 1], start };
|
|
780
860
|
}
|
|
781
861
|
const values = singleValues(segments);
|
|
782
|
-
|
|
783
|
-
return step || null;
|
|
862
|
+
return values && hourListStride(values);
|
|
784
863
|
}
|
|
785
864
|
function subMinuteSecond(ir) {
|
|
786
865
|
return ir.pattern.second === "*" || ir.shapes.second === "step";
|
|
@@ -804,13 +883,16 @@ function hourCadence(ir, minute, opts) {
|
|
|
804
883
|
return null;
|
|
805
884
|
}
|
|
806
885
|
const fires = (stride.last - stride.start) / stride.interval + 1;
|
|
807
|
-
if (ir.pattern.second === "0" && fires <= maxClockTimes) {
|
|
886
|
+
if (ir.pattern.second === "0" && fires <= maxClockTimes && offsetCleanStride(stride)) {
|
|
808
887
|
return null;
|
|
809
888
|
}
|
|
810
889
|
const confinement = minute === 0 && subMinuteSecond(ir) && cleanStrideSegment(ir);
|
|
811
890
|
if (confinement) {
|
|
812
891
|
return secondsClause(ir, "minuto", opts) + " durante un minuto, " + stepHourSpan(confinement, opts) + trailingQualifier(ir, opts);
|
|
813
892
|
}
|
|
893
|
+
if (minute === 0 && ir.pattern.second === "0") {
|
|
894
|
+
return hourStrideCadence(stride, opts) + trailingQualifier(ir, opts);
|
|
895
|
+
}
|
|
814
896
|
return hourCadenceLead(ir, minute, opts) + ", " + hourStrideCadence(stride, opts) + trailingQualifier(ir, opts);
|
|
815
897
|
}
|
|
816
898
|
function cleanStrideSegment(ir) {
|
|
@@ -821,6 +903,62 @@ function cleanStrideSegment(ir) {
|
|
|
821
903
|
}
|
|
822
904
|
return segment;
|
|
823
905
|
}
|
|
906
|
+
function hasHourWindow(ir) {
|
|
907
|
+
return hourSegments(ir).some(function range(segment) {
|
|
908
|
+
return segment.kind === "range";
|
|
909
|
+
});
|
|
910
|
+
}
|
|
911
|
+
function hourRangeCadence(ir, minute, opts) {
|
|
912
|
+
if (minute !== 0 || !hasHourWindow(ir) || ir.pattern.second === "0") {
|
|
913
|
+
return null;
|
|
914
|
+
}
|
|
915
|
+
if (subMinuteSecond(ir)) {
|
|
916
|
+
return secondsClause(ir, "minuto", opts) + " durante un minuto, durante las horas " + hourSegmentTimes(ir, 0, null, opts) + trailingQualifier(ir, opts);
|
|
917
|
+
}
|
|
918
|
+
return hourCadenceLead(ir, minute, opts) + ", " + hourSegmentTimes(ir, 0, null, opts) + trailingQualifier(ir, opts);
|
|
919
|
+
}
|
|
920
|
+
function hourContextTimes(ir, opts) {
|
|
921
|
+
const segments = hourSegments(ir);
|
|
922
|
+
const points = [];
|
|
923
|
+
const hasRange = segments.some(function range(segment) {
|
|
924
|
+
return segment.kind === "range";
|
|
925
|
+
});
|
|
926
|
+
segments.forEach(function collect(segment) {
|
|
927
|
+
if (segment.kind === "step") {
|
|
928
|
+
points.push(...segment.fires);
|
|
929
|
+
} else if (segment.kind === "single") {
|
|
930
|
+
points.push(+segment.value);
|
|
931
|
+
}
|
|
932
|
+
});
|
|
933
|
+
function isWord(hour) {
|
|
934
|
+
return !opts.ampm && (hour === 0 || hour === 12);
|
|
935
|
+
}
|
|
936
|
+
if (!hasRange && points.every(isWord)) {
|
|
937
|
+
return joinList(points.map(function each(hour) {
|
|
938
|
+
return atTime(bareHourPhrase(hour, opts));
|
|
939
|
+
}));
|
|
940
|
+
}
|
|
941
|
+
function wholeHour(hour) {
|
|
942
|
+
return "de la hora " + fromTime(explicitTimePhrase(hour, 0, opts));
|
|
943
|
+
}
|
|
944
|
+
const pieces = [];
|
|
945
|
+
segments.forEach(function place(segment) {
|
|
946
|
+
if (segment.kind === "range") {
|
|
947
|
+
pieces.push(timeRange(
|
|
948
|
+
{ hour: +segment.bounds[0], minute: 0 },
|
|
949
|
+
{ hour: +segment.bounds[1], minute: 0 },
|
|
950
|
+
opts
|
|
951
|
+
));
|
|
952
|
+
} else if (segment.kind === "step") {
|
|
953
|
+
segment.fires.forEach(function each(hour) {
|
|
954
|
+
pieces.push(wholeHour(hour));
|
|
955
|
+
});
|
|
956
|
+
} else {
|
|
957
|
+
pieces.push(wholeHour(+segment.value));
|
|
958
|
+
}
|
|
959
|
+
});
|
|
960
|
+
return joinList(pieces);
|
|
961
|
+
}
|
|
824
962
|
function atTimes(hours, opts) {
|
|
825
963
|
return hours.map(function each(hour) {
|
|
826
964
|
return atTime(timePhrase(hour, 0, null, opts));
|
|
@@ -1083,7 +1221,7 @@ function weekdayQualifier(ir) {
|
|
|
1083
1221
|
if (quartz) {
|
|
1084
1222
|
return quartz;
|
|
1085
1223
|
}
|
|
1086
|
-
const segments =
|
|
1224
|
+
const segments = orderWeekdaysForDisplay(fieldSegments(ir, "weekday"));
|
|
1087
1225
|
const allSingles = segments.every(function single(segment) {
|
|
1088
1226
|
return segment.kind === "single";
|
|
1089
1227
|
});
|
package/dist/lang/es.js
CHANGED
|
@@ -46,6 +46,26 @@ function arithmeticStep(values) {
|
|
|
46
46
|
}
|
|
47
47
|
return { start: values[0], interval, last: values[values.length - 1] };
|
|
48
48
|
}
|
|
49
|
+
function weekdayDisplayKey(value) {
|
|
50
|
+
return value === 0 ? 7 : value;
|
|
51
|
+
}
|
|
52
|
+
function orderWeekdaysForDisplay(segments) {
|
|
53
|
+
const flattened = segments.flatMap(function flat(segment) {
|
|
54
|
+
return segment.kind === "step" ? segment.fires.map(function single(value) {
|
|
55
|
+
return { kind: "single", value: "" + value };
|
|
56
|
+
}) : [segment];
|
|
57
|
+
});
|
|
58
|
+
function key(segment) {
|
|
59
|
+
return segment.kind === "range" ? weekdayDisplayKey(+segment.bounds[0]) : weekdayDisplayKey(+segment.value);
|
|
60
|
+
}
|
|
61
|
+
return flattened.map(function index(segment, position) {
|
|
62
|
+
return [segment, position];
|
|
63
|
+
}).sort(function byDisplayKey(a, b) {
|
|
64
|
+
return key(a[0]) - key(b[0]) || a[1] - b[1];
|
|
65
|
+
}).map(function unwrap(pair) {
|
|
66
|
+
return pair[0];
|
|
67
|
+
});
|
|
68
|
+
}
|
|
49
69
|
function toFieldNumber(token, numberMap) {
|
|
50
70
|
return isNonNegativeInteger(token) ? +token : numberMap[token.toUpperCase()];
|
|
51
71
|
}
|
|
@@ -176,14 +196,21 @@ function secondsListAtClock(ir, rest, opts) {
|
|
|
176
196
|
}
|
|
177
197
|
function composeHourCadence(ir, plan, opts) {
|
|
178
198
|
const clockRest = plan.rest.kind === "clockTimes" || plan.rest.kind === "compactClockTimes";
|
|
179
|
-
|
|
199
|
+
if (!clockRest || ir.shapes.minute !== "single") {
|
|
200
|
+
return null;
|
|
201
|
+
}
|
|
202
|
+
const minute = +ir.pattern.minute;
|
|
203
|
+
return hourCadence(ir, minute, opts) ?? hourRangeCadence(ir, minute, opts);
|
|
204
|
+
}
|
|
205
|
+
function isPinnedMinuteSeconds(ir, plan) {
|
|
206
|
+
return plan.rest.kind === "clockTimes" && (ir.shapes.second === "wildcard" || ir.shapes.second === "step");
|
|
180
207
|
}
|
|
181
208
|
function renderComposeSeconds(ir, plan, opts) {
|
|
182
209
|
const hourCad = composeHourCadence(ir, plan, opts);
|
|
183
210
|
if (hourCad !== null) {
|
|
184
211
|
return hourCad;
|
|
185
212
|
}
|
|
186
|
-
if (
|
|
213
|
+
if (isPinnedMinuteSeconds(ir, plan)) {
|
|
187
214
|
return pinnedMinuteSeconds(ir, plan.rest, opts);
|
|
188
215
|
}
|
|
189
216
|
if (plan.rest.kind === "clockTimes" && ir.shapes.second === "list") {
|
|
@@ -191,7 +218,7 @@ function renderComposeSeconds(ir, plan, opts) {
|
|
|
191
218
|
}
|
|
192
219
|
if (plan.rest.kind === "hourRange" && ir.shapes.second === "step" && ir.pattern.weekday !== "*") {
|
|
193
220
|
const restNode = plan.rest;
|
|
194
|
-
const window = hourWindow(restNode, opts);
|
|
221
|
+
const window = hourWindow(boundedWindow(restNode), opts);
|
|
195
222
|
const dayFrame = weekdayQualifier(ir) + monthScope(ir);
|
|
196
223
|
const cadence = "cada " + numero(stepSegment(ir.analyses.segments.second).interval, opts) + " segundos del minuto " + ir.pattern.minute;
|
|
197
224
|
return dayFrame + ", " + window + ", " + cadence;
|
|
@@ -199,7 +226,9 @@ function renderComposeSeconds(ir, plan, opts) {
|
|
|
199
226
|
if (isEveryOtherMinuteSeconds(ir, plan)) {
|
|
200
227
|
return secondsLeadClause(ir, opts) + " de " + render(ir, plan.rest, opts);
|
|
201
228
|
}
|
|
202
|
-
|
|
229
|
+
const restOwnsLead = plan.rest.kind === "compactClockTimes" && ir.analyses.clockSecond;
|
|
230
|
+
const lead = restOwnsLead ? "" : secondsLeadClause(ir, opts) + ", ";
|
|
231
|
+
return lead + render(ir, plan.rest, opts);
|
|
203
232
|
}
|
|
204
233
|
function isEveryOtherMinuteSeconds(ir, plan) {
|
|
205
234
|
if (plan.rest.kind !== "minuteFrequency" || ir.shapes.second !== "wildcard" || ir.shapes.hour !== "wildcard") {
|
|
@@ -211,7 +240,7 @@ function isEveryOtherMinuteSeconds(ir, plan) {
|
|
|
211
240
|
function pinnedMinuteSeconds(ir, rest, opts) {
|
|
212
241
|
const dayTrail = leadingQualifier(ir, opts).trimEnd();
|
|
213
242
|
const trail = dayTrail ? ", " + dayTrail : "";
|
|
214
|
-
if (+rest.times[0].minute === 0) {
|
|
243
|
+
if (+rest.times[0].minute === 0 && ir.shapes.minute === "single") {
|
|
215
244
|
return secondsLeadClause(ir, opts) + " durante un minuto " + durationHourList(rest.times, opts) + trail;
|
|
216
245
|
}
|
|
217
246
|
return secondsLeadClause(ir, opts) + " de " + explicitClockList(rest.times, opts) + trail;
|
|
@@ -328,7 +357,12 @@ function renderMinuteFrequency(ir, plan, opts) {
|
|
|
328
357
|
opts
|
|
329
358
|
);
|
|
330
359
|
if (plan.hours.kind === "during") {
|
|
331
|
-
|
|
360
|
+
const cadence = unevenHourCadence(ir, opts);
|
|
361
|
+
if (cadence) {
|
|
362
|
+
phrase += ", " + cadence;
|
|
363
|
+
} else {
|
|
364
|
+
phrase += singleHourStep(ir.analyses.segments.hour) ? ", " + stepHourSpan(stepSegment(ir.analyses.segments.hour), opts) : " " + hourSpanFromTimes(ir, plan.hours.times, opts);
|
|
365
|
+
}
|
|
332
366
|
} else if (plan.hours.kind === "window") {
|
|
333
367
|
phrase += " " + hourWindow(plan.hours, opts);
|
|
334
368
|
} else if (plan.hours.kind === "step") {
|
|
@@ -347,22 +381,30 @@ function renderMinuteSpanInHour(ir, plan, opts) {
|
|
|
347
381
|
) + trailingQualifier(ir, opts);
|
|
348
382
|
}
|
|
349
383
|
function renderMinutesAcrossHours(ir, plan, opts) {
|
|
384
|
+
const cadence = unevenHourCadence(ir, opts);
|
|
350
385
|
if (plan.form === "wildcard") {
|
|
386
|
+
if (cadence !== null) {
|
|
387
|
+
return "cada minuto, " + cadence + trailingQualifier(ir, opts);
|
|
388
|
+
}
|
|
351
389
|
if (singleHourStep(ir.analyses.segments.hour)) {
|
|
352
390
|
return "cada minuto, " + stepHourSpan(stepSegment(ir.analyses.segments.hour), opts) + trailingQualifier(ir, opts);
|
|
353
391
|
}
|
|
354
392
|
return "cada minuto " + hourSpanFromTimes(ir, plan.times, opts) + trailingQualifier(ir, opts);
|
|
355
393
|
}
|
|
356
394
|
const lead = plan.form === "range" ? minuteRangeLead(ir.pattern.minute) : minutesList(ir, opts);
|
|
395
|
+
if (cadence !== null) {
|
|
396
|
+
return lead + ", " + cadence + trailingQualifier(ir, opts);
|
|
397
|
+
}
|
|
357
398
|
return lead + ", " + atHourTimes(ir, plan.times, opts) + trailingQualifier(ir, opts);
|
|
358
399
|
}
|
|
359
400
|
function renderMinuteSpanAcrossHourStep(ir, plan, opts) {
|
|
360
401
|
const segment = stepSegment(ir.analyses.segments.hour);
|
|
402
|
+
const cadence = unevenHourCadence(ir, opts);
|
|
361
403
|
if (plan.form === "wildcard") {
|
|
362
404
|
return "cada minuto, " + stepHourSpan(segment, opts) + trailingQualifier(ir, opts);
|
|
363
405
|
}
|
|
364
406
|
const lead = plan.form === "list" ? minutesList(ir, opts) : minuteRangeLead(ir.pattern.minute);
|
|
365
|
-
return lead + ", " + stepHours(segment, opts) + trailingQualifier(ir, opts);
|
|
407
|
+
return lead + ", " + (cadence ?? stepHours(segment, opts)) + trailingQualifier(ir, opts);
|
|
366
408
|
}
|
|
367
409
|
function renderEveryHour(ir, plan, opts) {
|
|
368
410
|
return "cada hora" + trailingQualifier(ir, opts);
|
|
@@ -382,10 +424,15 @@ function renderHourRange(ir, plan, opts) {
|
|
|
382
424
|
return lead + ", " + window + trailingQualifier(ir, opts);
|
|
383
425
|
}
|
|
384
426
|
function renderHourStep(ir, plan, opts) {
|
|
427
|
+
const cadence = unevenHourCadence(ir, opts);
|
|
428
|
+
if (cadence !== null) {
|
|
429
|
+
return cadence + trailingQualifier(ir, opts);
|
|
430
|
+
}
|
|
385
431
|
return stepHours(stepSegment(ir.analyses.segments.hour), opts) + trailingQualifier(ir, opts);
|
|
386
432
|
}
|
|
387
433
|
function boundedWindow(plan) {
|
|
388
|
-
|
|
434
|
+
const last = plan.minuteForm === "wildcard" ? plan.boundMinute ?? 0 : 0;
|
|
435
|
+
return { from: plan.from, last, to: plan.to };
|
|
389
436
|
}
|
|
390
437
|
function hourWindow(window, opts) {
|
|
391
438
|
return timeRange(
|
|
@@ -429,7 +476,7 @@ function dowArm(ir) {
|
|
|
429
476
|
if (quartz) {
|
|
430
477
|
return quartz;
|
|
431
478
|
}
|
|
432
|
-
const segments =
|
|
479
|
+
const segments = orderWeekdaysForDisplay(fieldSegments(ir, "weekday"));
|
|
433
480
|
const allSingles = segments.every(function single(segment) {
|
|
434
481
|
return segment.kind === "single";
|
|
435
482
|
});
|
|
@@ -453,7 +500,8 @@ function unionYaseaSuffix(ir, opts) {
|
|
|
453
500
|
}
|
|
454
501
|
function renderClockTimes(ir, plan, opts) {
|
|
455
502
|
if (ir.shapes.minute === "single") {
|
|
456
|
-
const
|
|
503
|
+
const minute = +ir.pattern.minute;
|
|
504
|
+
const cadence = hourCadence(ir, minute, opts) ?? hourRangeCadence(ir, minute, opts);
|
|
457
505
|
if (cadence !== null) {
|
|
458
506
|
return cadence;
|
|
459
507
|
}
|
|
@@ -639,9 +687,9 @@ function groupClockTimesByArticle(phrases) {
|
|
|
639
687
|
}
|
|
640
688
|
function renderCompactClockTimes(ir, plan, opts) {
|
|
641
689
|
if (plan.fold) {
|
|
642
|
-
const
|
|
643
|
-
if (
|
|
644
|
-
return
|
|
690
|
+
const cadence2 = hourCadence(ir, plan.minute, opts) ?? hourRangeCadence(ir, plan.minute, opts);
|
|
691
|
+
if (cadence2 !== null) {
|
|
692
|
+
return cadence2;
|
|
645
693
|
}
|
|
646
694
|
const ranged = hourSegments(ir).some(function range(segment) {
|
|
647
695
|
return segment.kind === "range";
|
|
@@ -651,7 +699,8 @@ function renderCompactClockTimes(ir, plan, opts) {
|
|
|
651
699
|
}
|
|
652
700
|
return leadingQualifier(ir, opts) + hourSegmentTimes(ir, plan.minute, ir.analyses.clockSecond, opts);
|
|
653
701
|
}
|
|
654
|
-
const
|
|
702
|
+
const cadence = unevenHourCadence(ir, opts);
|
|
703
|
+
const phrase = cadence ? minutesList(ir, opts) + ", " + cadence + trailingQualifier(ir, opts) : minutesList(ir, opts) + ", " + hourContextTimes(ir, opts) + trailingQualifier(ir, opts);
|
|
655
704
|
return ir.analyses.clockSecond ? secondsLeadClause(ir, opts) + ", " + phrase : phrase;
|
|
656
705
|
}
|
|
657
706
|
var renderers = {
|
|
@@ -745,16 +794,46 @@ function hourStrideCadence(stride, opts) {
|
|
|
745
794
|
}
|
|
746
795
|
return cadence + " de " + timePhrase(start, 0, null, opts) + " a " + timePhrase(last, 0, null, opts);
|
|
747
796
|
}
|
|
797
|
+
function offsetCleanStride(stride) {
|
|
798
|
+
return stride.start < stride.interval && 24 % stride.interval === 0;
|
|
799
|
+
}
|
|
800
|
+
function unevenHourCadence(ir, opts) {
|
|
801
|
+
const stride = hourStride(ir);
|
|
802
|
+
if (!stride || offsetCleanStride(stride)) {
|
|
803
|
+
return null;
|
|
804
|
+
}
|
|
805
|
+
return hourStrideCadence(stride, opts);
|
|
806
|
+
}
|
|
807
|
+
function hourListStride(values) {
|
|
808
|
+
if (values.length < 2) {
|
|
809
|
+
return null;
|
|
810
|
+
}
|
|
811
|
+
const interval = values[1] - values[0];
|
|
812
|
+
if (interval < 2) {
|
|
813
|
+
return null;
|
|
814
|
+
}
|
|
815
|
+
for (let i = 2; i < values.length; i += 1) {
|
|
816
|
+
if (values[i] - values[i - 1] !== interval) {
|
|
817
|
+
return null;
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
if (values[0] !== 0 && values.length < 5) {
|
|
821
|
+
return null;
|
|
822
|
+
}
|
|
823
|
+
return { interval, last: values[values.length - 1], start: values[0] };
|
|
824
|
+
}
|
|
748
825
|
function hourStride(ir) {
|
|
749
826
|
const segments = fieldSegments(ir, "hour");
|
|
750
827
|
if (segments.length === 1 && segments[0].kind === "step") {
|
|
751
828
|
const segment = segments[0];
|
|
829
|
+
if (segment.fires.length < 2) {
|
|
830
|
+
return null;
|
|
831
|
+
}
|
|
752
832
|
const start = segment.startToken === "*" ? 0 : +segment.startToken.split("-")[0];
|
|
753
833
|
return { interval: segment.interval, last: segment.fires[segment.fires.length - 1], start };
|
|
754
834
|
}
|
|
755
835
|
const values = singleValues(segments);
|
|
756
|
-
|
|
757
|
-
return step || null;
|
|
836
|
+
return values && hourListStride(values);
|
|
758
837
|
}
|
|
759
838
|
function subMinuteSecond(ir) {
|
|
760
839
|
return ir.pattern.second === "*" || ir.shapes.second === "step";
|
|
@@ -778,13 +857,16 @@ function hourCadence(ir, minute, opts) {
|
|
|
778
857
|
return null;
|
|
779
858
|
}
|
|
780
859
|
const fires = (stride.last - stride.start) / stride.interval + 1;
|
|
781
|
-
if (ir.pattern.second === "0" && fires <= maxClockTimes) {
|
|
860
|
+
if (ir.pattern.second === "0" && fires <= maxClockTimes && offsetCleanStride(stride)) {
|
|
782
861
|
return null;
|
|
783
862
|
}
|
|
784
863
|
const confinement = minute === 0 && subMinuteSecond(ir) && cleanStrideSegment(ir);
|
|
785
864
|
if (confinement) {
|
|
786
865
|
return secondsClause(ir, "minuto", opts) + " durante un minuto, " + stepHourSpan(confinement, opts) + trailingQualifier(ir, opts);
|
|
787
866
|
}
|
|
867
|
+
if (minute === 0 && ir.pattern.second === "0") {
|
|
868
|
+
return hourStrideCadence(stride, opts) + trailingQualifier(ir, opts);
|
|
869
|
+
}
|
|
788
870
|
return hourCadenceLead(ir, minute, opts) + ", " + hourStrideCadence(stride, opts) + trailingQualifier(ir, opts);
|
|
789
871
|
}
|
|
790
872
|
function cleanStrideSegment(ir) {
|
|
@@ -795,6 +877,62 @@ function cleanStrideSegment(ir) {
|
|
|
795
877
|
}
|
|
796
878
|
return segment;
|
|
797
879
|
}
|
|
880
|
+
function hasHourWindow(ir) {
|
|
881
|
+
return hourSegments(ir).some(function range(segment) {
|
|
882
|
+
return segment.kind === "range";
|
|
883
|
+
});
|
|
884
|
+
}
|
|
885
|
+
function hourRangeCadence(ir, minute, opts) {
|
|
886
|
+
if (minute !== 0 || !hasHourWindow(ir) || ir.pattern.second === "0") {
|
|
887
|
+
return null;
|
|
888
|
+
}
|
|
889
|
+
if (subMinuteSecond(ir)) {
|
|
890
|
+
return secondsClause(ir, "minuto", opts) + " durante un minuto, durante las horas " + hourSegmentTimes(ir, 0, null, opts) + trailingQualifier(ir, opts);
|
|
891
|
+
}
|
|
892
|
+
return hourCadenceLead(ir, minute, opts) + ", " + hourSegmentTimes(ir, 0, null, opts) + trailingQualifier(ir, opts);
|
|
893
|
+
}
|
|
894
|
+
function hourContextTimes(ir, opts) {
|
|
895
|
+
const segments = hourSegments(ir);
|
|
896
|
+
const points = [];
|
|
897
|
+
const hasRange = segments.some(function range(segment) {
|
|
898
|
+
return segment.kind === "range";
|
|
899
|
+
});
|
|
900
|
+
segments.forEach(function collect(segment) {
|
|
901
|
+
if (segment.kind === "step") {
|
|
902
|
+
points.push(...segment.fires);
|
|
903
|
+
} else if (segment.kind === "single") {
|
|
904
|
+
points.push(+segment.value);
|
|
905
|
+
}
|
|
906
|
+
});
|
|
907
|
+
function isWord(hour) {
|
|
908
|
+
return !opts.ampm && (hour === 0 || hour === 12);
|
|
909
|
+
}
|
|
910
|
+
if (!hasRange && points.every(isWord)) {
|
|
911
|
+
return joinList(points.map(function each(hour) {
|
|
912
|
+
return atTime(bareHourPhrase(hour, opts));
|
|
913
|
+
}));
|
|
914
|
+
}
|
|
915
|
+
function wholeHour(hour) {
|
|
916
|
+
return "de la hora " + fromTime(explicitTimePhrase(hour, 0, opts));
|
|
917
|
+
}
|
|
918
|
+
const pieces = [];
|
|
919
|
+
segments.forEach(function place(segment) {
|
|
920
|
+
if (segment.kind === "range") {
|
|
921
|
+
pieces.push(timeRange(
|
|
922
|
+
{ hour: +segment.bounds[0], minute: 0 },
|
|
923
|
+
{ hour: +segment.bounds[1], minute: 0 },
|
|
924
|
+
opts
|
|
925
|
+
));
|
|
926
|
+
} else if (segment.kind === "step") {
|
|
927
|
+
segment.fires.forEach(function each(hour) {
|
|
928
|
+
pieces.push(wholeHour(hour));
|
|
929
|
+
});
|
|
930
|
+
} else {
|
|
931
|
+
pieces.push(wholeHour(+segment.value));
|
|
932
|
+
}
|
|
933
|
+
});
|
|
934
|
+
return joinList(pieces);
|
|
935
|
+
}
|
|
798
936
|
function atTimes(hours, opts) {
|
|
799
937
|
return hours.map(function each(hour) {
|
|
800
938
|
return atTime(timePhrase(hour, 0, null, opts));
|
|
@@ -1057,7 +1195,7 @@ function weekdayQualifier(ir) {
|
|
|
1057
1195
|
if (quartz) {
|
|
1058
1196
|
return quartz;
|
|
1059
1197
|
}
|
|
1060
|
-
const segments =
|
|
1198
|
+
const segments = orderWeekdaysForDisplay(fieldSegments(ir, "weekday"));
|
|
1061
1199
|
const allSingles = segments.every(function single(segment) {
|
|
1062
1200
|
return segment.kind === "single";
|
|
1063
1201
|
});
|