cronli5 0.8.0 → 0.8.3

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/de.cjs CHANGED
@@ -303,6 +303,20 @@ var stepOrdinals = {
303
303
  8: "achten",
304
304
  12: "zw\xF6lften"
305
305
  };
306
+ var minuteStepOrdinals = {
307
+ 3: "dritten",
308
+ 4: "vierten",
309
+ 5: "f\xFCnften",
310
+ 6: "sechsten",
311
+ 7: "siebten",
312
+ 8: "achten",
313
+ 9: "neunten",
314
+ 10: "zehnten",
315
+ 12: "zw\xF6lften",
316
+ 15: "f\xFCnfzehnten",
317
+ 20: "zwanzigsten",
318
+ 30: "drei\xDFigsten"
319
+ };
306
320
  function everyNthHour(segment) {
307
321
  const base = "in jeder " + stepOrdinals[segment.interval] + " Stunde";
308
322
  const start = segment.startToken === "*" ? 0 : +segment.startToken;
@@ -555,6 +569,28 @@ function isEveryOtherMinuteSeconds(schedule, plan) {
555
569
  const minuteStep = stepSegment(schedule, "minute");
556
570
  return minuteStep.startToken === "*" && minuteStep.interval === 2;
557
571
  }
572
+ function minuteStride(schedule) {
573
+ if (schedule.shapes.minute === "step") {
574
+ const segment = stepSegment(schedule, "minute");
575
+ const start = segment.startToken === "*" ? 0 : +segment.startToken;
576
+ return { interval: segment.interval, last: segment.fires[segment.fires.length - 1], start };
577
+ }
578
+ const values = singleValues(segmentsOf(schedule, "minute"));
579
+ return values && arithmeticStep(values);
580
+ }
581
+ function minuteStepConfinement(schedule, stride) {
582
+ const ordinal = minuteStepOrdinals[stride.interval];
583
+ const head = ordinal ? "in jeder " + ordinal + " Minute" : "alle " + stride.interval + " Minuten";
584
+ const tail = renderStride({ ...stride, cycle: 60 }, {
585
+ bare: () => "",
586
+ offset: () => " ab Minute " + stride.start,
587
+ bounded: () => " von Minute " + stride.start + " bis " + stride.last
588
+ });
589
+ return secondsLead(schedule) + " " + head + tail + " jeder Stunde";
590
+ }
591
+ function isSteppedMinuteSeconds(schedule, plan) {
592
+ return (plan.rest.kind === "minuteFrequency" || plan.rest.kind === "multipleMinutes") && (schedule.shapes.second === "wildcard" || schedule.shapes.second === "step") && schedule.shapes.hour === "wildcard" && schedule.pattern.minute !== "*/2" && minuteStride(schedule) !== null;
593
+ }
558
594
  function renderComposeSeconds(schedule, plan, opts) {
559
595
  if ((plan.rest.kind === "clockTimes" || plan.rest.kind === "compactClockTimes") && schedule.shapes.minute === "single") {
560
596
  const minute = +schedule.pattern.minute;
@@ -563,9 +599,12 @@ function renderComposeSeconds(schedule, plan, opts) {
563
599
  return cadence;
564
600
  }
565
601
  }
566
- if (composeMinuteZero(schedule, plan)) {
602
+ if (composeSingleMinute(schedule, plan)) {
567
603
  return secondsLead(schedule) + " " + clockMinuteGenitive(plan.rest.times, opts.style.sep);
568
604
  }
605
+ if (isSteppedMinuteSeconds(schedule, plan)) {
606
+ return minuteStepConfinement(schedule, minuteStride(schedule));
607
+ }
569
608
  if (isEveryOtherMinuteSeconds(schedule, plan)) {
570
609
  return secondsLead(schedule) + " jeder zweiten Minute";
571
610
  }
@@ -573,8 +612,8 @@ function renderComposeSeconds(schedule, plan, opts) {
573
612
  const lead = restOwnsLead ? "" : secondsLead(schedule) + ", ";
574
613
  return lead + render(schedule, plan.rest, opts);
575
614
  }
576
- function composeMinuteZero(schedule, plan) {
577
- return plan.rest.kind === "clockTimes" && plan.rest.times.every((time) => +time.minute === 0);
615
+ function composeSingleMinute(schedule, plan) {
616
+ return plan.rest.kind === "clockTimes" && schedule.shapes.minute === "single";
578
617
  }
579
618
  function clockMinuteGenitive(times, sep) {
580
619
  const clocks = times.map(function clock(time) {
@@ -645,10 +684,10 @@ function renderMinuteFrequency(schedule, plan, opts) {
645
684
  const base = stepClause(segment, UNITS.minute, "jeder Stunde");
646
685
  if (plan.hours.kind === "during") {
647
686
  const cadence = unevenHourCadence(schedule);
648
- return cadence ? base + ", " + cadence : base + " " + duringHours(schedule, plan.hours.times, sep);
687
+ return cadence ? stepClause(segment, UNITS.minute, "") + ", " + cadence : base + " " + duringHours(schedule, plan.hours.times, sep);
649
688
  }
650
689
  if (plan.hours.kind === "step") {
651
- return base + " " + everyNthHour(stepSegment(schedule, "hour"));
690
+ return stepClause(segment, UNITS.minute, "") + " " + everyNthHour(stepSegment(schedule, "hour"));
652
691
  }
653
692
  return base;
654
693
  }
@@ -859,16 +898,16 @@ function qualifier(schedule, months2) {
859
898
  }
860
899
  var LEADING_PLANS = /* @__PURE__ */ new Set(["clockTimes"]);
861
900
  function leadsQualifier(schedule) {
862
- return LEADING_PLANS.has(schedule.plan.kind) || isComposeMinuteZero(schedule);
901
+ return LEADING_PLANS.has(schedule.plan.kind) || isComposeSingleMinute(schedule);
863
902
  }
864
- function isComposeMinuteZero(schedule) {
865
- return schedule.plan.kind === "composeSeconds" && composeMinuteZero(schedule, schedule.plan);
903
+ function isComposeSingleMinute(schedule) {
904
+ return schedule.plan.kind === "composeSeconds" && composeSingleMinute(schedule, schedule.plan);
866
905
  }
867
906
  function needsDailyFrame(schedule) {
868
907
  if (hourCadenceApplies(schedule)) {
869
908
  return false;
870
909
  }
871
- if (schedule.plan.kind === "clockTimes" || isComposeMinuteZero(schedule)) {
910
+ if (schedule.plan.kind === "clockTimes" || isComposeSingleMinute(schedule)) {
872
911
  return true;
873
912
  }
874
913
  if (schedule.plan.kind !== "hourStep") {
package/dist/lang/de.js CHANGED
@@ -277,6 +277,20 @@ var stepOrdinals = {
277
277
  8: "achten",
278
278
  12: "zw\xF6lften"
279
279
  };
280
+ var minuteStepOrdinals = {
281
+ 3: "dritten",
282
+ 4: "vierten",
283
+ 5: "f\xFCnften",
284
+ 6: "sechsten",
285
+ 7: "siebten",
286
+ 8: "achten",
287
+ 9: "neunten",
288
+ 10: "zehnten",
289
+ 12: "zw\xF6lften",
290
+ 15: "f\xFCnfzehnten",
291
+ 20: "zwanzigsten",
292
+ 30: "drei\xDFigsten"
293
+ };
280
294
  function everyNthHour(segment) {
281
295
  const base = "in jeder " + stepOrdinals[segment.interval] + " Stunde";
282
296
  const start = segment.startToken === "*" ? 0 : +segment.startToken;
@@ -529,6 +543,28 @@ function isEveryOtherMinuteSeconds(schedule, plan) {
529
543
  const minuteStep = stepSegment(schedule, "minute");
530
544
  return minuteStep.startToken === "*" && minuteStep.interval === 2;
531
545
  }
546
+ function minuteStride(schedule) {
547
+ if (schedule.shapes.minute === "step") {
548
+ const segment = stepSegment(schedule, "minute");
549
+ const start = segment.startToken === "*" ? 0 : +segment.startToken;
550
+ return { interval: segment.interval, last: segment.fires[segment.fires.length - 1], start };
551
+ }
552
+ const values = singleValues(segmentsOf(schedule, "minute"));
553
+ return values && arithmeticStep(values);
554
+ }
555
+ function minuteStepConfinement(schedule, stride) {
556
+ const ordinal = minuteStepOrdinals[stride.interval];
557
+ const head = ordinal ? "in jeder " + ordinal + " Minute" : "alle " + stride.interval + " Minuten";
558
+ const tail = renderStride({ ...stride, cycle: 60 }, {
559
+ bare: () => "",
560
+ offset: () => " ab Minute " + stride.start,
561
+ bounded: () => " von Minute " + stride.start + " bis " + stride.last
562
+ });
563
+ return secondsLead(schedule) + " " + head + tail + " jeder Stunde";
564
+ }
565
+ function isSteppedMinuteSeconds(schedule, plan) {
566
+ return (plan.rest.kind === "minuteFrequency" || plan.rest.kind === "multipleMinutes") && (schedule.shapes.second === "wildcard" || schedule.shapes.second === "step") && schedule.shapes.hour === "wildcard" && schedule.pattern.minute !== "*/2" && minuteStride(schedule) !== null;
567
+ }
532
568
  function renderComposeSeconds(schedule, plan, opts) {
533
569
  if ((plan.rest.kind === "clockTimes" || plan.rest.kind === "compactClockTimes") && schedule.shapes.minute === "single") {
534
570
  const minute = +schedule.pattern.minute;
@@ -537,9 +573,12 @@ function renderComposeSeconds(schedule, plan, opts) {
537
573
  return cadence;
538
574
  }
539
575
  }
540
- if (composeMinuteZero(schedule, plan)) {
576
+ if (composeSingleMinute(schedule, plan)) {
541
577
  return secondsLead(schedule) + " " + clockMinuteGenitive(plan.rest.times, opts.style.sep);
542
578
  }
579
+ if (isSteppedMinuteSeconds(schedule, plan)) {
580
+ return minuteStepConfinement(schedule, minuteStride(schedule));
581
+ }
543
582
  if (isEveryOtherMinuteSeconds(schedule, plan)) {
544
583
  return secondsLead(schedule) + " jeder zweiten Minute";
545
584
  }
@@ -547,8 +586,8 @@ function renderComposeSeconds(schedule, plan, opts) {
547
586
  const lead = restOwnsLead ? "" : secondsLead(schedule) + ", ";
548
587
  return lead + render(schedule, plan.rest, opts);
549
588
  }
550
- function composeMinuteZero(schedule, plan) {
551
- return plan.rest.kind === "clockTimes" && plan.rest.times.every((time) => +time.minute === 0);
589
+ function composeSingleMinute(schedule, plan) {
590
+ return plan.rest.kind === "clockTimes" && schedule.shapes.minute === "single";
552
591
  }
553
592
  function clockMinuteGenitive(times, sep) {
554
593
  const clocks = times.map(function clock(time) {
@@ -619,10 +658,10 @@ function renderMinuteFrequency(schedule, plan, opts) {
619
658
  const base = stepClause(segment, UNITS.minute, "jeder Stunde");
620
659
  if (plan.hours.kind === "during") {
621
660
  const cadence = unevenHourCadence(schedule);
622
- return cadence ? base + ", " + cadence : base + " " + duringHours(schedule, plan.hours.times, sep);
661
+ return cadence ? stepClause(segment, UNITS.minute, "") + ", " + cadence : base + " " + duringHours(schedule, plan.hours.times, sep);
623
662
  }
624
663
  if (plan.hours.kind === "step") {
625
- return base + " " + everyNthHour(stepSegment(schedule, "hour"));
664
+ return stepClause(segment, UNITS.minute, "") + " " + everyNthHour(stepSegment(schedule, "hour"));
626
665
  }
627
666
  return base;
628
667
  }
@@ -833,16 +872,16 @@ function qualifier(schedule, months2) {
833
872
  }
834
873
  var LEADING_PLANS = /* @__PURE__ */ new Set(["clockTimes"]);
835
874
  function leadsQualifier(schedule) {
836
- return LEADING_PLANS.has(schedule.plan.kind) || isComposeMinuteZero(schedule);
875
+ return LEADING_PLANS.has(schedule.plan.kind) || isComposeSingleMinute(schedule);
837
876
  }
838
- function isComposeMinuteZero(schedule) {
839
- return schedule.plan.kind === "composeSeconds" && composeMinuteZero(schedule, schedule.plan);
877
+ function isComposeSingleMinute(schedule) {
878
+ return schedule.plan.kind === "composeSeconds" && composeSingleMinute(schedule, schedule.plan);
840
879
  }
841
880
  function needsDailyFrame(schedule) {
842
881
  if (hourCadenceApplies(schedule)) {
843
882
  return false;
844
883
  }
845
- if (schedule.plan.kind === "clockTimes" || isComposeMinuteZero(schedule)) {
884
+ if (schedule.plan.kind === "clockTimes" || isComposeSingleMinute(schedule)) {
846
885
  return true;
847
886
  }
848
887
  if (schedule.plan.kind !== "hourStep") {
package/dist/lang/en.cjs CHANGED
@@ -467,7 +467,8 @@ function renderMinuteFrequency(schedule, plan, opts) {
467
467
  to: plan.hours.to
468
468
  }, opts);
469
469
  } else if (plan.hours.kind === "step") {
470
- phrase += " " + everyNthHour(stepSegment(schedule, "hour"), opts);
470
+ const bound = withoutHourAnchor(phrase);
471
+ phrase = bound + (bound === phrase ? " " : ", ") + everyNthHour(stepSegment(schedule, "hour"), opts);
471
472
  }
472
473
  return phrase + trailingQualifier(schedule, opts);
473
474
  }
@@ -520,6 +521,45 @@ var stepOrdinals = {
520
521
  8: "eighth",
521
522
  12: "twelfth"
522
523
  };
524
+ var spelledOrdinals = {
525
+ 2: "other",
526
+ 3: "third",
527
+ 4: "fourth",
528
+ 5: "fifth",
529
+ 6: "sixth",
530
+ 7: "seventh",
531
+ 8: "eighth",
532
+ 9: "ninth",
533
+ 10: "tenth",
534
+ 11: "eleventh",
535
+ 12: "twelfth",
536
+ 15: "fifteenth",
537
+ 20: "twentieth",
538
+ 30: "thirtieth"
539
+ };
540
+ function ordinalWord(interval) {
541
+ return spelledOrdinals[interval] ?? getOrdinal(interval);
542
+ }
543
+ function minuteStrideConfinement(stride, opts) {
544
+ const base = " during every " + ordinalWord(stride.interval) + " minute";
545
+ return renderStride({ ...stride, cycle: 60 }, {
546
+ bare: () => base,
547
+ offset: () => base + " from " + getNumber(stride.start, opts) + " " + pluralize(stride.start, "minute") + " past the hour",
548
+ bounded: () => {
549
+ const num = seriesNumber();
550
+ return base + " from " + num(stride.start) + through(opts) + num(stride.last) + " " + pluralize(stride.last, "minute") + " past the hour";
551
+ }
552
+ });
553
+ }
554
+ function minuteStride(schedule) {
555
+ if (schedule.shapes.minute === "step") {
556
+ const segment = stepSegment(schedule, "minute");
557
+ const start = segment.startToken === "*" ? 0 : +segment.startToken;
558
+ return { interval: segment.interval, last: segment.fires[segment.fires.length - 1], start };
559
+ }
560
+ const values = singleValues(segmentsOf(schedule, "minute"));
561
+ return values && arithmeticStep(values);
562
+ }
523
563
  function everyNthHour(segment, opts) {
524
564
  const base = "during every " + stepOrdinals[segment.interval] + " hour";
525
565
  const start = segment.startToken === "*" ? 0 : +segment.startToken;
@@ -530,7 +570,7 @@ function renderMinuteSpanAcrossHourStep(schedule, plan, opts) {
530
570
  if (plan.form === "wildcard") {
531
571
  return "every minute " + everyNthHour(segment, opts) + trailingQualifier(schedule, opts);
532
572
  }
533
- const lead = plan.form === "list" ? strideFromSegments(
573
+ const lead = withoutHourAnchor(plan.form === "list" ? strideFromSegments(
534
574
  segmentsOf(schedule, "minute"),
535
575
  "minute",
536
576
  "hour",
@@ -540,7 +580,7 @@ function renderMinuteSpanAcrossHourStep(schedule, plan, opts) {
540
580
  "minute",
541
581
  "hour",
542
582
  opts
543
- ) : minuteRangeLead(schedule.pattern.minute, opts);
583
+ ) : minuteRangeLead(schedule.pattern.minute, opts));
544
584
  const cadence = unevenHourCadence(schedule, opts);
545
585
  return lead + ", " + (cadence ?? stepHours(segment, opts)) + trailingQualifier(schedule, opts);
546
586
  }
@@ -659,7 +699,7 @@ function renderCompactClockTimes(schedule, plan, opts) {
659
699
  )
660
700
  );
661
701
  const cadence = unevenHourCadence(schedule, opts);
662
- const phrase = cadence ? minuteLead + ", " + cadence + trailingQualifier(schedule, opts) : minuteLead + ", at " + hourSegmentTimes(schedule, { minute: 0, second: null }, true, opts) + trailingQualifier(schedule, opts);
702
+ const phrase = cadence ? withoutHourAnchor(minuteLead) + ", " + cadence + trailingQualifier(schedule, opts) : minuteLead + ", at " + hourSegmentTimes(schedule, { minute: 0, second: null }, true, opts) + trailingQualifier(schedule, opts);
663
703
  return schedule.analyses.clockSecond ? secondsLeadClause(schedule, opts) + ", " + phrase : phrase;
664
704
  }
665
705
  function foldedHourWindows(schedule, plan, opts) {
@@ -725,9 +765,13 @@ function minuteConfinement(schedule, opts) {
725
765
  if (minute === "*") {
726
766
  return "";
727
767
  }
728
- if (isCadenceField(minute)) {
768
+ if (minute === "*/2") {
729
769
  return " of every other minute";
730
770
  }
771
+ const stride = minuteStride(schedule);
772
+ if (stride) {
773
+ return minuteStrideConfinement(stride, opts);
774
+ }
731
775
  const segments = segmentsOf(schedule, "minute");
732
776
  if (schedule.shapes.minute === "single") {
733
777
  return " during minute :" + pad(minute);
@@ -744,7 +788,7 @@ function minuteConfinement(schedule, opts) {
744
788
  function hourConfinement(schedule, opts) {
745
789
  const hour = schedule.pattern.hour;
746
790
  if (hour === "*") {
747
- const minutePinned = schedule.pattern.minute !== "*" && !isCadenceField(schedule.pattern.minute);
791
+ const minutePinned = schedule.pattern.minute !== "*" && !isCadenceField(schedule.pattern.minute) && !minuteStride(schedule);
748
792
  return minutePinned ? " of every hour" : "";
749
793
  }
750
794
  if (isCadenceField(hour)) {
@@ -793,9 +837,12 @@ function confinementEligible(schedule, lead) {
793
837
  }
794
838
  if (lead.secondLead) {
795
839
  if (minuteStep) {
796
- return minute === "*/2" && schedule.shapes.hour !== "range";
840
+ return minute === "*/2" ? schedule.shapes.hour !== "range" : schedule.pattern.hour === "*";
797
841
  }
798
- if (isMinuteStride(schedule) || schedule.shapes.minute === "list" && schedule.shapes.hour === "list") {
842
+ if (isMinuteStride(schedule)) {
843
+ return schedule.pattern.hour === "*";
844
+ }
845
+ if (schedule.shapes.minute === "list" && schedule.shapes.hour === "list") {
799
846
  return false;
800
847
  }
801
848
  return true;
@@ -1033,6 +1080,9 @@ function segmentWords(segments, opts) {
1033
1080
  function listPastThe(words, unit, anchor, opts) {
1034
1081
  return "at " + joinList(words, opts) + " " + unit + "s past the " + anchor;
1035
1082
  }
1083
+ function withoutHourAnchor(lead) {
1084
+ return lead.replace(/ past the hour$/, "");
1085
+ }
1036
1086
  function wordTime(hour, minute, second) {
1037
1087
  return (+hour === 0 || +hour === 12) && +minute === 0 && !(typeof second === "number" && second > 0);
1038
1088
  }
package/dist/lang/en.js CHANGED
@@ -441,7 +441,8 @@ function renderMinuteFrequency(schedule, plan, opts) {
441
441
  to: plan.hours.to
442
442
  }, opts);
443
443
  } else if (plan.hours.kind === "step") {
444
- phrase += " " + everyNthHour(stepSegment(schedule, "hour"), opts);
444
+ const bound = withoutHourAnchor(phrase);
445
+ phrase = bound + (bound === phrase ? " " : ", ") + everyNthHour(stepSegment(schedule, "hour"), opts);
445
446
  }
446
447
  return phrase + trailingQualifier(schedule, opts);
447
448
  }
@@ -494,6 +495,45 @@ var stepOrdinals = {
494
495
  8: "eighth",
495
496
  12: "twelfth"
496
497
  };
498
+ var spelledOrdinals = {
499
+ 2: "other",
500
+ 3: "third",
501
+ 4: "fourth",
502
+ 5: "fifth",
503
+ 6: "sixth",
504
+ 7: "seventh",
505
+ 8: "eighth",
506
+ 9: "ninth",
507
+ 10: "tenth",
508
+ 11: "eleventh",
509
+ 12: "twelfth",
510
+ 15: "fifteenth",
511
+ 20: "twentieth",
512
+ 30: "thirtieth"
513
+ };
514
+ function ordinalWord(interval) {
515
+ return spelledOrdinals[interval] ?? getOrdinal(interval);
516
+ }
517
+ function minuteStrideConfinement(stride, opts) {
518
+ const base = " during every " + ordinalWord(stride.interval) + " minute";
519
+ return renderStride({ ...stride, cycle: 60 }, {
520
+ bare: () => base,
521
+ offset: () => base + " from " + getNumber(stride.start, opts) + " " + pluralize(stride.start, "minute") + " past the hour",
522
+ bounded: () => {
523
+ const num = seriesNumber();
524
+ return base + " from " + num(stride.start) + through(opts) + num(stride.last) + " " + pluralize(stride.last, "minute") + " past the hour";
525
+ }
526
+ });
527
+ }
528
+ function minuteStride(schedule) {
529
+ if (schedule.shapes.minute === "step") {
530
+ const segment = stepSegment(schedule, "minute");
531
+ const start = segment.startToken === "*" ? 0 : +segment.startToken;
532
+ return { interval: segment.interval, last: segment.fires[segment.fires.length - 1], start };
533
+ }
534
+ const values = singleValues(segmentsOf(schedule, "minute"));
535
+ return values && arithmeticStep(values);
536
+ }
497
537
  function everyNthHour(segment, opts) {
498
538
  const base = "during every " + stepOrdinals[segment.interval] + " hour";
499
539
  const start = segment.startToken === "*" ? 0 : +segment.startToken;
@@ -504,7 +544,7 @@ function renderMinuteSpanAcrossHourStep(schedule, plan, opts) {
504
544
  if (plan.form === "wildcard") {
505
545
  return "every minute " + everyNthHour(segment, opts) + trailingQualifier(schedule, opts);
506
546
  }
507
- const lead = plan.form === "list" ? strideFromSegments(
547
+ const lead = withoutHourAnchor(plan.form === "list" ? strideFromSegments(
508
548
  segmentsOf(schedule, "minute"),
509
549
  "minute",
510
550
  "hour",
@@ -514,7 +554,7 @@ function renderMinuteSpanAcrossHourStep(schedule, plan, opts) {
514
554
  "minute",
515
555
  "hour",
516
556
  opts
517
- ) : minuteRangeLead(schedule.pattern.minute, opts);
557
+ ) : minuteRangeLead(schedule.pattern.minute, opts));
518
558
  const cadence = unevenHourCadence(schedule, opts);
519
559
  return lead + ", " + (cadence ?? stepHours(segment, opts)) + trailingQualifier(schedule, opts);
520
560
  }
@@ -633,7 +673,7 @@ function renderCompactClockTimes(schedule, plan, opts) {
633
673
  )
634
674
  );
635
675
  const cadence = unevenHourCadence(schedule, opts);
636
- const phrase = cadence ? minuteLead + ", " + cadence + trailingQualifier(schedule, opts) : minuteLead + ", at " + hourSegmentTimes(schedule, { minute: 0, second: null }, true, opts) + trailingQualifier(schedule, opts);
676
+ const phrase = cadence ? withoutHourAnchor(minuteLead) + ", " + cadence + trailingQualifier(schedule, opts) : minuteLead + ", at " + hourSegmentTimes(schedule, { minute: 0, second: null }, true, opts) + trailingQualifier(schedule, opts);
637
677
  return schedule.analyses.clockSecond ? secondsLeadClause(schedule, opts) + ", " + phrase : phrase;
638
678
  }
639
679
  function foldedHourWindows(schedule, plan, opts) {
@@ -699,9 +739,13 @@ function minuteConfinement(schedule, opts) {
699
739
  if (minute === "*") {
700
740
  return "";
701
741
  }
702
- if (isCadenceField(minute)) {
742
+ if (minute === "*/2") {
703
743
  return " of every other minute";
704
744
  }
745
+ const stride = minuteStride(schedule);
746
+ if (stride) {
747
+ return minuteStrideConfinement(stride, opts);
748
+ }
705
749
  const segments = segmentsOf(schedule, "minute");
706
750
  if (schedule.shapes.minute === "single") {
707
751
  return " during minute :" + pad(minute);
@@ -718,7 +762,7 @@ function minuteConfinement(schedule, opts) {
718
762
  function hourConfinement(schedule, opts) {
719
763
  const hour = schedule.pattern.hour;
720
764
  if (hour === "*") {
721
- const minutePinned = schedule.pattern.minute !== "*" && !isCadenceField(schedule.pattern.minute);
765
+ const minutePinned = schedule.pattern.minute !== "*" && !isCadenceField(schedule.pattern.minute) && !minuteStride(schedule);
722
766
  return minutePinned ? " of every hour" : "";
723
767
  }
724
768
  if (isCadenceField(hour)) {
@@ -767,9 +811,12 @@ function confinementEligible(schedule, lead) {
767
811
  }
768
812
  if (lead.secondLead) {
769
813
  if (minuteStep) {
770
- return minute === "*/2" && schedule.shapes.hour !== "range";
814
+ return minute === "*/2" ? schedule.shapes.hour !== "range" : schedule.pattern.hour === "*";
771
815
  }
772
- if (isMinuteStride(schedule) || schedule.shapes.minute === "list" && schedule.shapes.hour === "list") {
816
+ if (isMinuteStride(schedule)) {
817
+ return schedule.pattern.hour === "*";
818
+ }
819
+ if (schedule.shapes.minute === "list" && schedule.shapes.hour === "list") {
773
820
  return false;
774
821
  }
775
822
  return true;
@@ -1007,6 +1054,9 @@ function segmentWords(segments, opts) {
1007
1054
  function listPastThe(words, unit, anchor, opts) {
1008
1055
  return "at " + joinList(words, opts) + " " + unit + "s past the " + anchor;
1009
1056
  }
1057
+ function withoutHourAnchor(lead) {
1058
+ return lead.replace(/ past the hour$/, "");
1059
+ }
1010
1060
  function wordTime(hour, minute, second) {
1011
1061
  return (+hour === 0 || +hour === 12) && +minute === 0 && !(typeof second === "number" && second > 0);
1012
1062
  }
package/dist/lang/es.cjs CHANGED
@@ -223,6 +223,20 @@ var weekdayNames = [
223
223
  "s\xE1bado"
224
224
  ];
225
225
  var nthWeekdayNames = [null, "primer", "segundo", "tercer", "cuarto", "quinto"];
226
+ var stepOrdinals = {
227
+ 3: "tercer",
228
+ 4: "cuarto",
229
+ 5: "quinto",
230
+ 6: "sexto",
231
+ 7: "s\xE9ptimo",
232
+ 8: "octavo",
233
+ 9: "noveno",
234
+ 10: "d\xE9cimo",
235
+ 12: "duod\xE9cimo",
236
+ 15: "decimoquinto",
237
+ 20: "vig\xE9simo",
238
+ 30: "trig\xE9simo"
239
+ };
226
240
  function normalizeOptions(options) {
227
241
  options = options || {};
228
242
  const style = resolveDialect(options.dialect);
@@ -287,6 +301,28 @@ function composeHourCadence(schedule, plan, opts) {
287
301
  function isPinnedMinuteSeconds(schedule, plan) {
288
302
  return plan.rest.kind === "clockTimes" && (schedule.shapes.second === "wildcard" || schedule.shapes.second === "step");
289
303
  }
304
+ function minuteStride(schedule) {
305
+ if (schedule.shapes.minute === "step") {
306
+ const segment = stepSegment(schedule, "minute");
307
+ const start = segment.startToken === "*" ? 0 : +segment.startToken;
308
+ return { interval: segment.interval, last: segment.fires[segment.fires.length - 1], start };
309
+ }
310
+ const values = singleValues(segmentsOf(schedule, "minute"));
311
+ return values && arithmeticStep(values);
312
+ }
313
+ function minuteStepConfinement(schedule, stride, opts) {
314
+ const ordinal = stepOrdinals[stride.interval];
315
+ const head = ordinal ? "cada " + ordinal + " minuto" : "cada " + numero(stride.interval, opts) + " minutos";
316
+ const tail = renderStride({ ...stride, cycle: 60 }, {
317
+ bare: () => "",
318
+ offset: () => " a partir del minuto " + stride.start,
319
+ bounded: () => " del minuto " + stride.start + " al " + stride.last
320
+ });
321
+ return secondsLeadClause(schedule, opts) + " en " + head + tail + " de cada hora" + trailingQualifier(schedule, opts);
322
+ }
323
+ function isSteppedMinuteSeconds(schedule, plan) {
324
+ return (plan.rest.kind === "minuteFrequency" || plan.rest.kind === "multipleMinutes") && (schedule.shapes.second === "wildcard" || schedule.shapes.second === "step") && schedule.shapes.hour === "wildcard" && schedule.pattern.minute !== "*/2" && minuteStride(schedule) !== null;
325
+ }
290
326
  function renderComposeSeconds(schedule, plan, opts) {
291
327
  const hourCad = composeHourCadence(schedule, plan, opts);
292
328
  if (hourCad !== null) {
@@ -305,6 +341,9 @@ function renderComposeSeconds(schedule, plan, opts) {
305
341
  const cadence = "cada " + numero(stepSegment(schedule, "second").interval, opts) + " segundos del minuto " + schedule.pattern.minute;
306
342
  return dayFrame + ", " + window + ", " + cadence;
307
343
  }
344
+ if (isSteppedMinuteSeconds(schedule, plan)) {
345
+ return minuteStepConfinement(schedule, minuteStride(schedule), opts);
346
+ }
308
347
  if (isEveryOtherMinuteSeconds(schedule, plan)) {
309
348
  return secondsLeadClause(schedule, opts) + " de " + render(schedule, plan.rest, opts);
310
349
  }
@@ -378,6 +417,9 @@ function minutesList(schedule, opts) {
378
417
  opts
379
418
  ) ?? "en los minutos " + joinList(segmentWords(segmentsOf(schedule, "minute"))) + " de cada hora";
380
419
  }
420
+ function withoutHourAnchor(lead) {
421
+ return lead.replace(/ de cada hora$/, "");
422
+ }
381
423
  function minuteRangeLead(minuteField) {
382
424
  const bounds = minuteField.split("-");
383
425
  return "cada minuto del " + bounds[0] + " al " + bounds[1];
@@ -448,7 +490,7 @@ function renderMinuteFrequency(schedule, plan, opts) {
448
490
  } else if (plan.hours.kind === "window") {
449
491
  phrase += " " + hourWindow(plan.hours, opts);
450
492
  } else if (plan.hours.kind === "step") {
451
- phrase += ", " + stepHourSpan(stepSegment(schedule, "hour"), opts);
493
+ phrase = withoutHourAnchor(phrase) + ", " + stepHourSpan(stepSegment(schedule, "hour"), opts);
452
494
  }
453
495
  return phrase + trailingQualifier(schedule, opts);
454
496
  }
@@ -485,7 +527,7 @@ function renderMinuteSpanAcrossHourStep(schedule, plan, opts) {
485
527
  if (plan.form === "wildcard") {
486
528
  return "cada minuto, " + stepHourSpan(segment, opts) + trailingQualifier(schedule, opts);
487
529
  }
488
- const lead = plan.form === "list" ? minutesList(schedule, opts) : minuteRangeLead(schedule.pattern.minute);
530
+ const lead = withoutHourAnchor(plan.form === "list" ? minutesList(schedule, opts) : minuteRangeLead(schedule.pattern.minute));
489
531
  return lead + ", " + (cadence ?? stepHours(segment, opts)) + trailingQualifier(schedule, opts);
490
532
  }
491
533
  function renderEveryHour(schedule, plan, opts) {
@@ -796,7 +838,7 @@ function renderCompactClockTimes(schedule, plan, opts) {
796
838
  );
797
839
  }
798
840
  const cadence = unevenHourCadence(schedule, opts);
799
- const phrase = cadence ? minutesList(schedule, opts) + ", " + cadence + trailingQualifier(schedule, opts) : minutesList(schedule, opts) + ", " + hourContextTimes(schedule, opts) + trailingQualifier(schedule, opts);
841
+ const phrase = cadence ? withoutHourAnchor(minutesList(schedule, opts)) + ", " + cadence + trailingQualifier(schedule, opts) : minutesList(schedule, opts) + ", " + hourContextTimes(schedule, opts) + trailingQualifier(schedule, opts);
800
842
  return schedule.analyses.clockSecond ? secondsLeadClause(schedule, opts) + ", " + phrase : phrase;
801
843
  }
802
844
  var renderers = {
package/dist/lang/es.js CHANGED
@@ -197,6 +197,20 @@ var weekdayNames = [
197
197
  "s\xE1bado"
198
198
  ];
199
199
  var nthWeekdayNames = [null, "primer", "segundo", "tercer", "cuarto", "quinto"];
200
+ var stepOrdinals = {
201
+ 3: "tercer",
202
+ 4: "cuarto",
203
+ 5: "quinto",
204
+ 6: "sexto",
205
+ 7: "s\xE9ptimo",
206
+ 8: "octavo",
207
+ 9: "noveno",
208
+ 10: "d\xE9cimo",
209
+ 12: "duod\xE9cimo",
210
+ 15: "decimoquinto",
211
+ 20: "vig\xE9simo",
212
+ 30: "trig\xE9simo"
213
+ };
200
214
  function normalizeOptions(options) {
201
215
  options = options || {};
202
216
  const style = resolveDialect(options.dialect);
@@ -261,6 +275,28 @@ function composeHourCadence(schedule, plan, opts) {
261
275
  function isPinnedMinuteSeconds(schedule, plan) {
262
276
  return plan.rest.kind === "clockTimes" && (schedule.shapes.second === "wildcard" || schedule.shapes.second === "step");
263
277
  }
278
+ function minuteStride(schedule) {
279
+ if (schedule.shapes.minute === "step") {
280
+ const segment = stepSegment(schedule, "minute");
281
+ const start = segment.startToken === "*" ? 0 : +segment.startToken;
282
+ return { interval: segment.interval, last: segment.fires[segment.fires.length - 1], start };
283
+ }
284
+ const values = singleValues(segmentsOf(schedule, "minute"));
285
+ return values && arithmeticStep(values);
286
+ }
287
+ function minuteStepConfinement(schedule, stride, opts) {
288
+ const ordinal = stepOrdinals[stride.interval];
289
+ const head = ordinal ? "cada " + ordinal + " minuto" : "cada " + numero(stride.interval, opts) + " minutos";
290
+ const tail = renderStride({ ...stride, cycle: 60 }, {
291
+ bare: () => "",
292
+ offset: () => " a partir del minuto " + stride.start,
293
+ bounded: () => " del minuto " + stride.start + " al " + stride.last
294
+ });
295
+ return secondsLeadClause(schedule, opts) + " en " + head + tail + " de cada hora" + trailingQualifier(schedule, opts);
296
+ }
297
+ function isSteppedMinuteSeconds(schedule, plan) {
298
+ return (plan.rest.kind === "minuteFrequency" || plan.rest.kind === "multipleMinutes") && (schedule.shapes.second === "wildcard" || schedule.shapes.second === "step") && schedule.shapes.hour === "wildcard" && schedule.pattern.minute !== "*/2" && minuteStride(schedule) !== null;
299
+ }
264
300
  function renderComposeSeconds(schedule, plan, opts) {
265
301
  const hourCad = composeHourCadence(schedule, plan, opts);
266
302
  if (hourCad !== null) {
@@ -279,6 +315,9 @@ function renderComposeSeconds(schedule, plan, opts) {
279
315
  const cadence = "cada " + numero(stepSegment(schedule, "second").interval, opts) + " segundos del minuto " + schedule.pattern.minute;
280
316
  return dayFrame + ", " + window + ", " + cadence;
281
317
  }
318
+ if (isSteppedMinuteSeconds(schedule, plan)) {
319
+ return minuteStepConfinement(schedule, minuteStride(schedule), opts);
320
+ }
282
321
  if (isEveryOtherMinuteSeconds(schedule, plan)) {
283
322
  return secondsLeadClause(schedule, opts) + " de " + render(schedule, plan.rest, opts);
284
323
  }
@@ -352,6 +391,9 @@ function minutesList(schedule, opts) {
352
391
  opts
353
392
  ) ?? "en los minutos " + joinList(segmentWords(segmentsOf(schedule, "minute"))) + " de cada hora";
354
393
  }
394
+ function withoutHourAnchor(lead) {
395
+ return lead.replace(/ de cada hora$/, "");
396
+ }
355
397
  function minuteRangeLead(minuteField) {
356
398
  const bounds = minuteField.split("-");
357
399
  return "cada minuto del " + bounds[0] + " al " + bounds[1];
@@ -422,7 +464,7 @@ function renderMinuteFrequency(schedule, plan, opts) {
422
464
  } else if (plan.hours.kind === "window") {
423
465
  phrase += " " + hourWindow(plan.hours, opts);
424
466
  } else if (plan.hours.kind === "step") {
425
- phrase += ", " + stepHourSpan(stepSegment(schedule, "hour"), opts);
467
+ phrase = withoutHourAnchor(phrase) + ", " + stepHourSpan(stepSegment(schedule, "hour"), opts);
426
468
  }
427
469
  return phrase + trailingQualifier(schedule, opts);
428
470
  }
@@ -459,7 +501,7 @@ function renderMinuteSpanAcrossHourStep(schedule, plan, opts) {
459
501
  if (plan.form === "wildcard") {
460
502
  return "cada minuto, " + stepHourSpan(segment, opts) + trailingQualifier(schedule, opts);
461
503
  }
462
- const lead = plan.form === "list" ? minutesList(schedule, opts) : minuteRangeLead(schedule.pattern.minute);
504
+ const lead = withoutHourAnchor(plan.form === "list" ? minutesList(schedule, opts) : minuteRangeLead(schedule.pattern.minute));
463
505
  return lead + ", " + (cadence ?? stepHours(segment, opts)) + trailingQualifier(schedule, opts);
464
506
  }
465
507
  function renderEveryHour(schedule, plan, opts) {
@@ -770,7 +812,7 @@ function renderCompactClockTimes(schedule, plan, opts) {
770
812
  );
771
813
  }
772
814
  const cadence = unevenHourCadence(schedule, opts);
773
- const phrase = cadence ? minutesList(schedule, opts) + ", " + cadence + trailingQualifier(schedule, opts) : minutesList(schedule, opts) + ", " + hourContextTimes(schedule, opts) + trailingQualifier(schedule, opts);
815
+ const phrase = cadence ? withoutHourAnchor(minutesList(schedule, opts)) + ", " + cadence + trailingQualifier(schedule, opts) : minutesList(schedule, opts) + ", " + hourContextTimes(schedule, opts) + trailingQualifier(schedule, opts);
774
816
  return schedule.analyses.clockSecond ? secondsLeadClause(schedule, opts) + ", " + phrase : phrase;
775
817
  }
776
818
  var renderers = {