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/dist/lang/es.cjs CHANGED
@@ -50,12 +50,28 @@ var weekdayNumbers = {
50
50
  FRI: 5,
51
51
  SAT: 6
52
52
  };
53
+ var maxClockTimes = 6;
53
54
 
54
55
  // src/core/util.ts
55
56
  function isNonNegativeInteger(value) {
56
57
  const digits = /^\d+$/;
57
58
  return digits.test(value);
58
59
  }
60
+ function arithmeticStep(values) {
61
+ if (values.length < 5) {
62
+ return null;
63
+ }
64
+ const interval = values[1] - values[0];
65
+ if (interval < 2) {
66
+ return null;
67
+ }
68
+ for (let i = 2; i < values.length; i += 1) {
69
+ if (values[i] - values[i - 1] !== interval) {
70
+ return null;
71
+ }
72
+ }
73
+ return { start: values[0], interval, last: values[values.length - 1] };
74
+ }
59
75
  function toFieldNumber(token, numberMap) {
60
76
  return isNonNegativeInteger(token) ? +token : numberMap[token.toUpperCase()];
61
77
  }
@@ -173,19 +189,38 @@ function renderSecondsWithinMinute(ir, plan, opts) {
173
189
  }
174
190
  return secondsLeadClause(ir, opts) + ", en el minuto " + minuteField + " de cada hora" + trailingQualifier(ir, opts);
175
191
  }
192
+ function secondsListAtClock(ir, rest, opts) {
193
+ const clockPhrases = rest.times.map(function clock(time) {
194
+ return atTime(timePhrase(time.hour, time.minute, null, opts));
195
+ });
196
+ const grouped = groupClockTimesByArticle(clockPhrases);
197
+ const clockList = grouped.startsWith("a ") ? grouped.slice(2) : grouped;
198
+ const stride = strideFromSegments(fieldSegments(ir, "second"), "segundo", "", opts);
199
+ const secondsPhrase = stride ?? "en los segundos " + joinList(segmentWords(fieldSegments(ir, "second")));
200
+ const dayFrame = trailingQualifier(ir, opts);
201
+ return (dayFrame ? dayFrame.trimStart() + ", " : "") + secondsPhrase + " de " + clockList;
202
+ }
203
+ function composeHourCadence(ir, plan, opts) {
204
+ const clockRest = plan.rest.kind === "clockTimes" || plan.rest.kind === "compactClockTimes";
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");
213
+ }
176
214
  function renderComposeSeconds(ir, plan, opts) {
177
- if (plan.rest.kind === "clockTimes" && (ir.shapes.second === "wildcard" || ir.shapes.second === "step")) {
215
+ const hourCad = composeHourCadence(ir, plan, opts);
216
+ if (hourCad !== null) {
217
+ return hourCad;
218
+ }
219
+ if (isPinnedMinuteSeconds(ir, plan)) {
178
220
  return pinnedMinuteSeconds(ir, plan.rest, opts);
179
221
  }
180
222
  if (plan.rest.kind === "clockTimes" && ir.shapes.second === "list") {
181
- const clockPhrases = plan.rest.times.map(function clock(time) {
182
- return atTime(timePhrase(time.hour, time.minute, null, opts));
183
- });
184
- const grouped = groupClockTimesByArticle(clockPhrases);
185
- const clockList = grouped.startsWith("a ") ? grouped.slice(2) : grouped;
186
- const secondsPhrase = "en los segundos " + joinList(segmentWords(fieldSegments(ir, "second")));
187
- const dayFrame = trailingQualifier(ir, opts);
188
- return (dayFrame ? dayFrame.trimStart() + ", " : "") + secondsPhrase + " de " + clockList;
223
+ return secondsListAtClock(ir, plan.rest, opts);
189
224
  }
190
225
  if (plan.rest.kind === "hourRange" && ir.shapes.second === "step" && ir.pattern.weekday !== "*") {
191
226
  const restNode = plan.rest;
@@ -194,17 +229,32 @@ function renderComposeSeconds(ir, plan, opts) {
194
229
  const cadence = "cada " + numero(stepSegment(ir.analyses.segments.second).interval, opts) + " segundos del minuto " + ir.pattern.minute;
195
230
  return dayFrame + ", " + window + ", " + cadence;
196
231
  }
197
- return secondsLeadClause(ir, opts) + ", " + render(ir, plan.rest, opts);
232
+ if (isEveryOtherMinuteSeconds(ir, plan)) {
233
+ return secondsLeadClause(ir, opts) + " de " + render(ir, plan.rest, opts);
234
+ }
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);
238
+ }
239
+ function isEveryOtherMinuteSeconds(ir, plan) {
240
+ if (plan.rest.kind !== "minuteFrequency" || ir.shapes.second !== "wildcard" || ir.shapes.hour !== "wildcard") {
241
+ return false;
242
+ }
243
+ const minuteStep = stepSegment(ir.analyses.segments.minute);
244
+ return minuteStep.startToken === "*" && minuteStep.interval === 2;
198
245
  }
199
246
  function pinnedMinuteSeconds(ir, rest, opts) {
200
247
  const dayTrail = leadingQualifier(ir, opts).trimEnd();
201
248
  const trail = dayTrail ? ", " + dayTrail : "";
202
- if (+rest.times[0].minute === 0) {
249
+ if (+rest.times[0].minute === 0 && ir.shapes.minute === "single") {
203
250
  return secondsLeadClause(ir, opts) + " durante un minuto " + durationHourList(rest.times, opts) + trail;
204
251
  }
205
252
  return secondsLeadClause(ir, opts) + " de " + explicitClockList(rest.times, opts) + trail;
206
253
  }
207
254
  function secondsLeadClause(ir, opts) {
255
+ return secondsClause(ir, "minuto", opts);
256
+ }
257
+ function secondsClause(ir, anchor, opts) {
208
258
  const secondField = ir.pattern.second;
209
259
  const shape = ir.shapes.second;
210
260
  if (secondField === "*") {
@@ -214,18 +264,23 @@ function secondsLeadClause(ir, opts) {
214
264
  return stepCycle60(
215
265
  stepSegment(ir.analyses.segments.second),
216
266
  "segundo",
217
- "minuto",
267
+ anchor,
218
268
  opts
219
269
  );
220
270
  }
221
271
  if (shape === "range") {
222
272
  const bounds = secondField.split("-");
223
- return "cada segundo del " + bounds[0] + " al " + bounds[1] + " de cada minuto";
273
+ return "cada segundo del " + bounds[0] + " al " + bounds[1] + " de cada " + anchor;
224
274
  }
225
275
  if (shape === "single") {
226
- return "en el segundo " + secondField + " de cada minuto";
276
+ return "en el segundo " + secondField + " de cada " + anchor;
227
277
  }
228
- return "en los segundos " + joinList(segmentWords(fieldSegments(ir, "second"))) + " de cada minuto";
278
+ return strideFromSegments(
279
+ fieldSegments(ir, "second"),
280
+ "segundo",
281
+ anchor,
282
+ opts
283
+ ) ?? "en los segundos " + joinList(segmentWords(fieldSegments(ir, "second"))) + " de cada " + anchor;
229
284
  }
230
285
  function renderEveryMinute(ir, plan, opts) {
231
286
  return "cada minuto" + trailingQualifier(ir, opts);
@@ -237,10 +292,15 @@ function renderRangeOfMinutes(ir, plan, opts) {
237
292
  return minuteRangeLead(ir.pattern.minute) + " de cada hora" + trailingQualifier(ir, opts);
238
293
  }
239
294
  function renderMultipleMinutes(ir, plan, opts) {
240
- return minutesList(ir) + trailingQualifier(ir, opts);
295
+ return minutesList(ir, opts) + trailingQualifier(ir, opts);
241
296
  }
242
- function minutesList(ir) {
243
- return "en los minutos " + joinList(segmentWords(fieldSegments(ir, "minute"))) + " de cada hora";
297
+ function minutesList(ir, opts) {
298
+ return strideFromSegments(
299
+ fieldSegments(ir, "minute"),
300
+ "minuto",
301
+ "hora",
302
+ opts
303
+ ) ?? "en los minutos " + joinList(segmentWords(fieldSegments(ir, "minute"))) + " de cada hora";
244
304
  }
245
305
  function minuteRangeLead(minuteField) {
246
306
  const bounds = minuteField.split("-");
@@ -303,7 +363,12 @@ function renderMinuteFrequency(ir, plan, opts) {
303
363
  opts
304
364
  );
305
365
  if (plan.hours.kind === "during") {
306
- phrase += singleHourStep(ir.analyses.segments.hour) ? ", " + stepHourSpan(stepSegment(ir.analyses.segments.hour), opts) : " " + hourSpanFromTimes(ir, plan.hours.times, opts);
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
+ }
307
372
  } else if (plan.hours.kind === "window") {
308
373
  phrase += " " + hourWindow(plan.hours, opts);
309
374
  } else if (plan.hours.kind === "step") {
@@ -322,21 +387,30 @@ function renderMinuteSpanInHour(ir, plan, opts) {
322
387
  ) + trailingQualifier(ir, opts);
323
388
  }
324
389
  function renderMinutesAcrossHours(ir, plan, opts) {
390
+ const cadence = unevenHourCadence(ir, opts);
325
391
  if (plan.form === "wildcard") {
392
+ if (cadence !== null) {
393
+ return "cada minuto, " + cadence + trailingQualifier(ir, opts);
394
+ }
326
395
  if (singleHourStep(ir.analyses.segments.hour)) {
327
396
  return "cada minuto, " + stepHourSpan(stepSegment(ir.analyses.segments.hour), opts) + trailingQualifier(ir, opts);
328
397
  }
329
398
  return "cada minuto " + hourSpanFromTimes(ir, plan.times, opts) + trailingQualifier(ir, opts);
330
399
  }
331
- const lead = plan.form === "range" ? minuteRangeLead(ir.pattern.minute) : minutesList(ir);
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
+ }
332
404
  return lead + ", " + atHourTimes(ir, plan.times, opts) + trailingQualifier(ir, opts);
333
405
  }
334
406
  function renderMinuteSpanAcrossHourStep(ir, plan, opts) {
335
407
  const segment = stepSegment(ir.analyses.segments.hour);
408
+ const cadence = unevenHourCadence(ir, opts);
336
409
  if (plan.form === "wildcard") {
337
410
  return "cada minuto, " + stepHourSpan(segment, opts) + trailingQualifier(ir, opts);
338
411
  }
339
- return minuteRangeLead(ir.pattern.minute) + ", " + stepHours(segment, opts) + trailingQualifier(ir, opts);
412
+ const lead = plan.form === "list" ? minutesList(ir, opts) : minuteRangeLead(ir.pattern.minute);
413
+ return lead + ", " + (cadence ?? stepHours(segment, opts)) + trailingQualifier(ir, opts);
340
414
  }
341
415
  function renderEveryHour(ir, plan, opts) {
342
416
  return "cada hora" + trailingQualifier(ir, opts);
@@ -352,10 +426,14 @@ function renderHourRange(ir, plan, opts) {
352
426
  if (ir.pattern.minute === "0") {
353
427
  return "cada hora " + window + trailingQualifier(ir, opts);
354
428
  }
355
- const lead = ir.shapes.minute === "single" ? "en el minuto " + ir.pattern.minute + " de cada hora" : minutesList(ir);
429
+ const lead = ir.shapes.minute === "single" ? "en el minuto " + ir.pattern.minute + " de cada hora" : minutesList(ir, opts);
356
430
  return lead + ", " + window + trailingQualifier(ir, opts);
357
431
  }
358
432
  function renderHourStep(ir, plan, opts) {
433
+ const cadence = unevenHourCadence(ir, opts);
434
+ if (cadence !== null) {
435
+ return cadence + trailingQualifier(ir, opts);
436
+ }
359
437
  return stepHours(stepSegment(ir.analyses.segments.hour), opts) + trailingQualifier(ir, opts);
360
438
  }
361
439
  function boundedWindow(plan) {
@@ -426,6 +504,13 @@ function unionYaseaSuffix(ir, opts) {
426
504
  return ", ya sea " + domArm(ir, opts) + " o " + dowArm(ir);
427
505
  }
428
506
  function renderClockTimes(ir, plan, opts) {
507
+ if (ir.shapes.minute === "single") {
508
+ const minute = +ir.pattern.minute;
509
+ const cadence = hourCadence(ir, minute, opts) ?? hourRangeCadence(ir, minute, opts);
510
+ if (cadence !== null) {
511
+ return cadence;
512
+ }
513
+ }
429
514
  const phrases = plan.times.map(function clock(time) {
430
515
  return atTime(timePhrase(time.hour, time.minute, time.second, opts));
431
516
  });
@@ -607,6 +692,10 @@ function groupClockTimesByArticle(phrases) {
607
692
  }
608
693
  function renderCompactClockTimes(ir, plan, opts) {
609
694
  if (plan.fold) {
695
+ const cadence2 = hourCadence(ir, plan.minute, opts) ?? hourRangeCadence(ir, plan.minute, opts);
696
+ if (cadence2 !== null) {
697
+ return cadence2;
698
+ }
610
699
  const ranged = hourSegments(ir).some(function range(segment) {
611
700
  return segment.kind === "range";
612
701
  });
@@ -615,7 +704,8 @@ function renderCompactClockTimes(ir, plan, opts) {
615
704
  }
616
705
  return leadingQualifier(ir, opts) + hourSegmentTimes(ir, plan.minute, ir.analyses.clockSecond, opts);
617
706
  }
618
- const phrase = minutesList(ir) + ", " + hourSegmentTimes(ir, 0, null, opts) + trailingQualifier(ir, opts);
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);
619
709
  return ir.analyses.clockSecond ? secondsLeadClause(ir, opts) + ", " + phrase : phrase;
620
710
  }
621
711
  var renderers = {
@@ -638,19 +728,50 @@ var renderers = {
638
728
  singleMinute: renderSingleMinute,
639
729
  standaloneSeconds: renderStandaloneSeconds
640
730
  };
731
+ function renderStride(stride, opts) {
732
+ const { interval, start, last, cycle, unit, anchor } = stride;
733
+ const cadence = "cada " + numero(interval, opts) + " " + unit + "s";
734
+ const tiles = cycle % interval === 0;
735
+ if (start === 0 && tiles) {
736
+ return cadence;
737
+ }
738
+ const tail = anchor ? " de cada " + anchor : "";
739
+ if (start < interval && tiles) {
740
+ return cadence + " a partir del " + unit + " " + start + tail;
741
+ }
742
+ return cadence + " del " + unit + " " + start + " al " + last + tail;
743
+ }
641
744
  function stepCycle60(segment, unit, anchor, opts) {
642
745
  if (segment.startToken.indexOf("-") !== -1) {
643
746
  return "en los " + unit + "s " + joinList(wordList(segment.fires)) + " de cada " + anchor;
644
747
  }
645
748
  const start = segment.startToken === "*" ? 0 : +segment.startToken;
646
- const interval = segment.interval;
647
- if (start !== 0) {
648
- if (segment.fires.length <= 3) {
649
- return "en los " + unit + "s " + joinList(wordList(segment.fires)) + " de cada " + anchor;
749
+ if (start !== 0 && segment.fires.length <= 3) {
750
+ return "en los " + unit + "s " + joinList(wordList(segment.fires)) + " de cada " + anchor;
751
+ }
752
+ return renderStride({
753
+ interval: segment.interval,
754
+ start,
755
+ last: segment.fires[segment.fires.length - 1],
756
+ cycle: 60,
757
+ unit,
758
+ anchor
759
+ }, opts);
760
+ }
761
+ function strideFromSegments(segments, unit, anchor, opts) {
762
+ const values = singleValues(segments);
763
+ const step = values && arithmeticStep(values);
764
+ return step ? renderStride({ ...step, cycle: 60, unit, anchor }, opts) : null;
765
+ }
766
+ function singleValues(segments) {
767
+ const values = [];
768
+ for (const segment of segments) {
769
+ if (segment.kind !== "single") {
770
+ return null;
650
771
  }
651
- return "cada " + numero(interval, opts) + " " + unit + "s a partir del " + unit + " " + start + " de cada " + anchor;
772
+ values.push(+segment.value);
652
773
  }
653
- return "cada " + numero(interval, opts) + " " + unit + "s";
774
+ return values;
654
775
  }
655
776
  function stepHours(segment, opts) {
656
777
  if (segment.startToken.indexOf("-") !== -1) {
@@ -666,6 +787,115 @@ function stepHours(segment, opts) {
666
787
  }
667
788
  return "cada " + numero(interval, opts) + " horas a partir de " + timePhrase(start, 0, null, opts);
668
789
  }
790
+ function hourStrideCadence(stride, opts) {
791
+ const { start, interval, last } = stride;
792
+ const cadence = "cada " + numero(interval, opts) + " horas";
793
+ const tiles = 24 % interval === 0;
794
+ if (start === 0 && tiles) {
795
+ return cadence;
796
+ }
797
+ if (start < interval && tiles) {
798
+ return cadence + " a partir de " + timePhrase(start, 0, null, opts);
799
+ }
800
+ return cadence + " de " + timePhrase(start, 0, null, opts) + " a " + timePhrase(last, 0, null, opts);
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
+ }
830
+ function hourStride(ir) {
831
+ const segments = fieldSegments(ir, "hour");
832
+ if (segments.length === 1 && segments[0].kind === "step") {
833
+ const segment = segments[0];
834
+ if (segment.fires.length < 2) {
835
+ return null;
836
+ }
837
+ const start = segment.startToken === "*" ? 0 : +segment.startToken.split("-")[0];
838
+ return { interval: segment.interval, last: segment.fires[segment.fires.length - 1], start };
839
+ }
840
+ const values = singleValues(segments);
841
+ return values && hourListStride(values);
842
+ }
843
+ function subMinuteSecond(ir) {
844
+ return ir.pattern.second === "*" || ir.shapes.second === "step";
845
+ }
846
+ function hourCadenceLead(ir, minute, opts) {
847
+ if (minute === 0) {
848
+ if (subMinuteSecond(ir)) {
849
+ return secondsClause(ir, "minuto", opts) + " durante un minuto";
850
+ }
851
+ return secondsClause(ir, "hora", opts);
852
+ }
853
+ const minutePhrase = "en el minuto " + minute;
854
+ if (ir.pattern.second === "0") {
855
+ return minutePhrase;
856
+ }
857
+ return secondsClause(ir, "minuto", opts) + ", " + minutePhrase;
858
+ }
859
+ function hourCadence(ir, minute, opts) {
860
+ const stride = hourStride(ir);
861
+ if (!stride) {
862
+ return null;
863
+ }
864
+ const fires = (stride.last - stride.start) / stride.interval + 1;
865
+ if (ir.pattern.second === "0" && fires <= maxClockTimes && offsetCleanStride(stride)) {
866
+ return null;
867
+ }
868
+ const confinement = minute === 0 && subMinuteSecond(ir) && cleanStrideSegment(ir);
869
+ if (confinement) {
870
+ return secondsClause(ir, "minuto", opts) + " durante un minuto, " + stepHourSpan(confinement, opts) + trailingQualifier(ir, opts);
871
+ }
872
+ if (minute === 0 && ir.pattern.second === "0") {
873
+ return hourStrideCadence(stride, opts) + trailingQualifier(ir, opts);
874
+ }
875
+ return hourCadenceLead(ir, minute, opts) + ", " + hourStrideCadence(stride, opts) + trailingQualifier(ir, opts);
876
+ }
877
+ function cleanStrideSegment(ir) {
878
+ const segments = fieldSegments(ir, "hour");
879
+ const segment = segments.length === 1 && segments[0];
880
+ if (!segment || segment.kind !== "step" || segment.startToken.indexOf("-") !== -1) {
881
+ return null;
882
+ }
883
+ return segment;
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
+ }
669
899
  function atTimes(hours, opts) {
670
900
  return hours.map(function each(hour) {
671
901
  return atTime(timePhrase(hour, 0, null, opts));