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/dist/lang/de.cjs CHANGED
@@ -62,6 +62,26 @@ function arithmeticStep(values) {
62
62
  }
63
63
  return { start: values[0], interval, last: values[values.length - 1] };
64
64
  }
65
+ function weekdayDisplayKey(value) {
66
+ return value === 0 ? 7 : value;
67
+ }
68
+ function orderWeekdaysForDisplay(segments) {
69
+ const flattened = segments.flatMap(function flat(segment) {
70
+ return segment.kind === "step" ? segment.fires.map(function single(value) {
71
+ return { kind: "single", value: "" + value };
72
+ }) : [segment];
73
+ });
74
+ function key(segment) {
75
+ return segment.kind === "range" ? weekdayDisplayKey(+segment.bounds[0]) : weekdayDisplayKey(+segment.value);
76
+ }
77
+ return flattened.map(function index(segment, position) {
78
+ return [segment, position];
79
+ }).sort(function byDisplayKey(a, b) {
80
+ return key(a[0]) - key(b[0]) || a[1] - b[1];
81
+ }).map(function unwrap(pair) {
82
+ return pair[0];
83
+ });
84
+ }
65
85
  function toFieldNumber(token, numberMap) {
66
86
  return isNonNegativeInteger(token) ? +token : numberMap[token.toUpperCase()];
67
87
  }
@@ -122,6 +142,9 @@ function everyUnit(unit) {
122
142
  function everyN(interval, unit) {
123
143
  return "alle " + interval + " " + unit.plural;
124
144
  }
145
+ function withAnchor(clause, anchor) {
146
+ return anchor ? clause + " " + anchor : clause;
147
+ }
125
148
  function stepSegment(segments) {
126
149
  return segments[0];
127
150
  }
@@ -145,7 +168,10 @@ function stepClause(segment, unit, anchor) {
145
168
  const start = segment.startToken === "*" ? 0 : +segment.startToken;
146
169
  const short = start !== 0 && segment.fires.length <= 3;
147
170
  if (segment.startToken.indexOf("-") !== -1 || short) {
148
- return "in den " + unit.plural + " " + joinList(segment.fires.map(String)) + " " + anchor;
171
+ return withAnchor(
172
+ "in den " + unit.plural + " " + joinList(segment.fires.map(String)),
173
+ anchor
174
+ );
149
175
  }
150
176
  return renderStride({
151
177
  interval: segment.interval,
@@ -206,7 +232,7 @@ function weekdayRange(bounds) {
206
232
  return weekdayName(bounds[0]) + " bis " + weekdayName(bounds[1]);
207
233
  }
208
234
  function weekdayQualifier(ir) {
209
- const segments = flattenSteps(fieldSegments(ir, "weekday"));
235
+ const segments = orderWeekdaysForDisplay(fieldSegments(ir, "weekday"));
210
236
  if (segments.length === 1 && segments[0].kind === "range") {
211
237
  return weekdayRange(segments[0].bounds);
212
238
  }
@@ -346,8 +372,11 @@ function countedPhrase(ir, field, singular, plural) {
346
372
  }
347
373
  return "in den " + plural + " " + joinList(fieldValues(ir, field));
348
374
  }
375
+ function minuteAnchor(ir) {
376
+ return ir.pattern.minute === "*" ? "jeder Minute" : "";
377
+ }
349
378
  function secondsLead(ir) {
350
- return secondsClause(ir, "jeder Minute");
379
+ return secondsClause(ir, minuteAnchor(ir));
351
380
  }
352
381
  function secondsClause(ir, anchor) {
353
382
  if (ir.pattern.second === "*") {
@@ -357,7 +386,7 @@ function secondsClause(ir, anchor) {
357
386
  if (ir.shapes.second === "step") {
358
387
  return stepClause(stepSegment(segments), UNITS.second, anchor);
359
388
  }
360
- return strideFromSegments(segments, UNITS.second, anchor) ?? countedPhrase(ir, "second", "Sekunde", "Sekunden") + " " + anchor;
389
+ return strideFromSegments(segments, UNITS.second, anchor) ?? withAnchor(countedPhrase(ir, "second", "Sekunde", "Sekunden"), anchor);
361
390
  }
362
391
  function spanTime(hour, minute, sep) {
363
392
  return hour + sep + pad(minute);
@@ -458,9 +487,17 @@ function renderMinuteSpanInHour(ir, plan, opts) {
458
487
  const sep = opts.style.sep;
459
488
  return "jede Minute von " + spanTime(plan.hour, plan.span[0], sep) + " bis " + spanTime(plan.hour, plan.span[1], sep) + " Uhr";
460
489
  }
490
+ function isEveryOtherMinuteSeconds(ir, plan) {
491
+ if (plan.rest.kind !== "minuteFrequency" || ir.shapes.second !== "wildcard" || ir.shapes.hour !== "wildcard") {
492
+ return false;
493
+ }
494
+ const minuteStep = stepSegment(ir.analyses.segments.minute);
495
+ return minuteStep.startToken === "*" && minuteStep.interval === 2;
496
+ }
461
497
  function renderComposeSeconds(ir, plan, opts) {
462
498
  if ((plan.rest.kind === "clockTimes" || plan.rest.kind === "compactClockTimes") && ir.shapes.minute === "single") {
463
- const cadence = hourCadence(ir, +ir.pattern.minute);
499
+ const minute = +ir.pattern.minute;
500
+ const cadence = hourCadence(ir, minute) ?? hourRangeCadence(ir, minute);
464
501
  if (cadence !== null) {
465
502
  return cadence;
466
503
  }
@@ -468,13 +505,12 @@ function renderComposeSeconds(ir, plan, opts) {
468
505
  if (composeMinuteZero(ir, plan)) {
469
506
  return secondsLead(ir) + " " + clockMinuteGenitive(plan.rest.times, opts.style.sep);
470
507
  }
471
- if (plan.rest.kind === "minuteFrequency" && ir.shapes.second === "wildcard" && ir.shapes.hour === "wildcard") {
472
- const minuteStep = stepSegment(ir.analyses.segments.minute);
473
- if (minuteStep.startToken === "*" && minuteStep.interval === 2) {
474
- return secondsLead(ir) + " jeder zweiten Minute";
475
- }
508
+ if (isEveryOtherMinuteSeconds(ir, plan)) {
509
+ return secondsLead(ir) + " jeder zweiten Minute";
476
510
  }
477
- return secondsLead(ir) + ", " + render(ir, plan.rest, opts);
511
+ const restOwnsLead = plan.rest.kind === "compactClockTimes" && ir.analyses.clockSecond;
512
+ const lead = restOwnsLead ? "" : secondsLead(ir) + ", ";
513
+ return lead + render(ir, plan.rest, opts);
478
514
  }
479
515
  function composeMinuteZero(ir, plan) {
480
516
  return plan.rest.kind === "clockTimes" && plan.rest.times.every((time) => +time.minute === 0);
@@ -487,31 +523,37 @@ function clockMinuteGenitive(times, sep) {
487
523
  }
488
524
  function renderMinutesAcrossHours(ir, plan, opts) {
489
525
  const sep = opts.style.sep;
526
+ const cadence = unevenHourCadence(ir);
490
527
  if (plan.form === "wildcard") {
491
- return "jede Minute " + duringHours(ir, plan.times, sep);
528
+ return cadence ? "jede Minute, " + cadence : "jede Minute " + duringHours(ir, plan.times, sep);
529
+ }
530
+ const minuteLead = strideFromSegments(fieldSegments(ir, "minute"), UNITS.minute, "") ?? countedPhrase(ir, "minute", "Minute", "Minuten");
531
+ if (cadence !== null) {
532
+ return minuteLead + ", " + cadence;
492
533
  }
493
534
  const hours = plan.times.kind === "fires" ? atHours(plan.times.fires) : joinList(hourSegmentParts(ir, 0, 0, sep));
494
- return (strideFromSegments(fieldSegments(ir, "minute"), UNITS.minute, "") ?? countedPhrase(ir, "minute", "Minute", "Minuten")) + ", " + hours;
535
+ return minuteLead + ", " + hours;
495
536
  }
496
537
  function renderMinuteSpanAcrossHourStep(ir, plan) {
538
+ const cadence = unevenHourCadence(ir);
497
539
  if (plan.form === "wildcard") {
498
540
  return "jede Minute " + everyNthHour(stepSegment(ir.analyses.segments.hour));
499
541
  }
500
542
  const segment = stepSegment(ir.analyses.segments.hour);
501
- const hours = confinedHourStride(segment) ? everyNthHour(segment) : atHours(segment.fires);
543
+ const hours = cadence ?? (confinedHourStride(segment) ? everyNthHour(segment) : atHours(segment.fires));
502
544
  return (strideFromSegments(fieldSegments(ir, "minute"), UNITS.minute, "") ?? countedPhrase(ir, "minute", "Minute", "Minuten")) + ", " + hours;
503
545
  }
504
546
  function renderCompactClockTimes(ir, plan, opts) {
505
547
  const sep = opts.style.sep;
506
548
  if (plan.fold) {
507
- const cadence = hourCadence(ir, plan.minute);
549
+ const cadence = hourCadence(ir, plan.minute) ?? hourRangeCadence(ir, plan.minute);
508
550
  if (cadence !== null) {
509
551
  return cadence;
510
552
  }
511
553
  const hourly = fieldSegments(ir, "hour").some((segment) => segment.kind === "range");
512
554
  return (hourly ? "st\xFCndlich " : "t\xE4glich ") + joinList(hourSegmentParts(ir, plan.minute, ir.analyses.clockSecond, sep));
513
555
  }
514
- const hours = fieldSegments(ir, "hour").some((segment) => segment.kind === "range") ? joinList(hourSegmentParts(ir, 0, 0, sep)) : atHours(hourFires(ir));
556
+ const hours = unevenHourCadence(ir) ?? (fieldSegments(ir, "hour").some((segment) => segment.kind === "range") ? joinList(hourSegmentParts(ir, 0, 0, sep)) : atHours(hourFires(ir)));
515
557
  const lead = ir.analyses.clockSecond ? countedPhrase(ir, "second", "Sekunde", "Sekunden") + ", " : "";
516
558
  return lead + (strideFromSegments(fieldSegments(ir, "minute"), UNITS.minute, "") ?? countedPhrase(ir, "minute", "Minute", "Minuten")) + ", " + hours;
517
559
  }
@@ -519,18 +561,25 @@ function renderMinuteFrequency(ir, plan, opts) {
519
561
  const segment = stepSegment(ir.analyses.segments.minute);
520
562
  const sep = opts.style.sep;
521
563
  const clean = cleanStep(segment, 60);
522
- const base = stepClause(segment, UNITS.minute, "jeder Stunde");
523
564
  if (plan.hours.kind === "window") {
565
+ const singleHour = plan.hours.from === plan.hours.to;
566
+ const base2 = stepClause(
567
+ segment,
568
+ UNITS.minute,
569
+ singleHour ? "" : "jeder Stunde"
570
+ );
524
571
  const window = hourWindow(
525
572
  plan.hours.from,
526
573
  plan.hours.to,
527
574
  plan.hours.last,
528
575
  sep
529
576
  );
530
- return clean ? base + " " + window : base + ", " + window;
577
+ return clean ? base2 + " " + window : base2 + ", " + window;
531
578
  }
579
+ const base = stepClause(segment, UNITS.minute, "jeder Stunde");
532
580
  if (plan.hours.kind === "during") {
533
- return base + " " + duringHours(ir, plan.hours.times, sep);
581
+ const cadence = unevenHourCadence(ir);
582
+ return cadence ? base + ", " + cadence : base + " " + duringHours(ir, plan.hours.times, sep);
534
583
  }
535
584
  if (plan.hours.kind === "step") {
536
585
  return base + " " + everyNthHour(stepSegment(ir.analyses.segments.hour));
@@ -538,8 +587,23 @@ function renderMinuteFrequency(ir, plan, opts) {
538
587
  return base;
539
588
  }
540
589
  function hourStepPhrase(ir) {
590
+ const cadence = unevenHourCadence(ir);
591
+ if (cadence !== null) {
592
+ return cadence;
593
+ }
541
594
  const segment = stepSegment(ir.analyses.segments.hour);
542
- return cleanStep(segment, 24) ? everyN(segment.interval, UNITS.hour) : atHours(segment.fires);
595
+ if (cleanStep(segment, 24)) {
596
+ return everyN(segment.interval, UNITS.hour);
597
+ }
598
+ const stride = openOffsetCleanStride(ir, segment);
599
+ return stride ? hourStrideCadence(stride) : atHours(segment.fires);
600
+ }
601
+ function openOffsetCleanStride(ir, segment) {
602
+ if (segment.startToken.indexOf("-") !== -1) {
603
+ return null;
604
+ }
605
+ const stride = hourStride(ir);
606
+ return stride && offsetCleanStride(stride) ? stride : null;
543
607
  }
544
608
  function hourStrideCadence(stride) {
545
609
  const { start, interval, last } = stride;
@@ -553,6 +617,27 @@ function hourStrideCadence(stride) {
553
617
  }
554
618
  return cadence + " von " + start + " bis " + last + " Uhr";
555
619
  }
620
+ function hourListStride(values) {
621
+ if (values.length < 2) {
622
+ return null;
623
+ }
624
+ const interval = values[1] - values[0];
625
+ if (interval < 2) {
626
+ return null;
627
+ }
628
+ for (let i = 2; i < values.length; i += 1) {
629
+ if (values[i] - values[i - 1] !== interval) {
630
+ return null;
631
+ }
632
+ }
633
+ if (values[0] !== 0 && values.length < 5) {
634
+ return null;
635
+ }
636
+ return { interval, last: values[values.length - 1], start: values[0] };
637
+ }
638
+ function offsetCleanStride(stride) {
639
+ return stride.start < stride.interval && 24 % stride.interval === 0;
640
+ }
556
641
  function hourStride(ir) {
557
642
  const segments = fieldSegments(ir, "hour");
558
643
  if (!segments) {
@@ -560,12 +645,21 @@ function hourStride(ir) {
560
645
  }
561
646
  if (segments.length === 1 && segments[0].kind === "step") {
562
647
  const segment = segments[0];
648
+ if (segment.fires.length < 2) {
649
+ return null;
650
+ }
563
651
  const start = segment.startToken === "*" ? 0 : +segment.startToken.split("-")[0];
564
652
  return { interval: segment.interval, last: segment.fires[segment.fires.length - 1], start };
565
653
  }
566
654
  const values = singleValues(segments);
567
- const step = values && arithmeticStep(values);
568
- return step || null;
655
+ return values && hourListStride(values);
656
+ }
657
+ function unevenHourCadence(ir) {
658
+ const stride = hourStride(ir);
659
+ if (!stride || offsetCleanStride(stride)) {
660
+ return null;
661
+ }
662
+ return hourStrideCadence(stride);
569
663
  }
570
664
  function subMinuteSecond(ir) {
571
665
  return ir.pattern.second === "*" || ir.shapes.second === "step";
@@ -573,7 +667,7 @@ function subMinuteSecond(ir) {
573
667
  function hourCadenceLead(ir, minute) {
574
668
  if (minute === 0) {
575
669
  if (subMinuteSecond(ir)) {
576
- return secondsClause(ir, "jeder Minute") + " f\xFCr eine Minute";
670
+ return withAnchor(secondsClause(ir, minuteAnchor(ir)), "f\xFCr eine Minute");
577
671
  }
578
672
  return secondsClause(ir, "jeder Stunde");
579
673
  }
@@ -581,7 +675,7 @@ function hourCadenceLead(ir, minute) {
581
675
  if (ir.pattern.second === "0") {
582
676
  return minutePhrase;
583
677
  }
584
- return secondsClause(ir, "jeder Minute") + ", " + minutePhrase;
678
+ return secondsClause(ir, minuteAnchor(ir)) + ", " + minutePhrase;
585
679
  }
586
680
  function hourCadence(ir, minute) {
587
681
  const stride = hourStride(ir);
@@ -589,37 +683,60 @@ function hourCadence(ir, minute) {
589
683
  return null;
590
684
  }
591
685
  const fires = (stride.last - stride.start) / stride.interval + 1;
592
- if (ir.pattern.second === "0" && fires <= maxClockTimes) {
686
+ if (ir.pattern.second === "0" && fires <= maxClockTimes && offsetCleanStride(stride)) {
593
687
  return null;
594
688
  }
595
689
  const segment = fieldSegments(ir, "hour")[0];
596
690
  const confined = minute === 0 && subMinuteSecond(ir) && fieldSegments(ir, "hour").length === 1 && segment.kind === "step" && confinedHourStride(segment);
597
691
  if (confined) {
598
- return secondsClause(ir, "jeder Minute") + " f\xFCr eine Minute " + everyNthHour(segment);
692
+ return withAnchor(secondsClause(ir, minuteAnchor(ir)), "f\xFCr eine Minute") + " " + everyNthHour(segment);
693
+ }
694
+ if (minute === 0 && ir.pattern.second === "0") {
695
+ return hourStrideCadence(stride);
599
696
  }
600
697
  return hourCadenceLead(ir, minute) + ", " + hourStrideCadence(stride);
601
698
  }
602
699
  function hourCadenceApplies(ir) {
603
- return ir.shapes.minute === "single" && hourCadence(ir, +ir.pattern.minute) !== null;
700
+ if (ir.shapes.minute !== "single") {
701
+ return false;
702
+ }
703
+ const minute = +ir.pattern.minute;
704
+ return hourCadence(ir, minute) !== null || hourRangeCadence(ir, minute) !== null;
705
+ }
706
+ function hasHourWindow(ir) {
707
+ const segments = fieldSegments(ir, "hour");
708
+ return !!segments && segments.some(function range(segment) {
709
+ return segment.kind === "range";
710
+ });
711
+ }
712
+ function hourRangeCadence(ir, minute) {
713
+ if (minute !== 0 || !hasHourWindow(ir) || ir.pattern.second === "0") {
714
+ return null;
715
+ }
716
+ return hourCadenceLead(ir, minute) + ", " + hourRangeWindowTail(ir);
717
+ }
718
+ function hourRangeWindowTail(ir) {
719
+ return joinList(hourSegmentParts(ir, 0, 0, ":"));
604
720
  }
605
721
  function renderHourRange(ir, plan, opts) {
606
- const window = hourWindow(
607
- plan.from,
608
- plan.to,
609
- plan.boundMinute ?? 0,
610
- opts.style.sep
611
- );
722
+ const last = plan.minuteForm === "wildcard" ? plan.boundMinute ?? 0 : 0;
723
+ const window = hourWindow(plan.from, plan.to, last, opts.style.sep);
612
724
  if (plan.minuteForm === "wildcard") {
613
725
  return "jede Minute " + window;
614
726
  }
615
727
  if (plan.minuteForm === "lead" && ir.pattern.minute === "0") {
616
728
  return "st\xFCndlich " + window;
617
729
  }
618
- return countedPhrase(ir, "minute", "Minute", "Minuten") + " jeder Stunde, " + window;
730
+ return (strideFromSegments(
731
+ fieldSegments(ir, "minute"),
732
+ UNITS.minute,
733
+ "jeder Stunde"
734
+ ) ?? countedPhrase(ir, "minute", "Minute", "Minuten") + " jeder Stunde") + ", " + window;
619
735
  }
620
736
  function renderClockTimes(ir, plan, opts) {
621
737
  if (ir.shapes.minute === "single") {
622
- const cadence = hourCadence(ir, +ir.pattern.minute);
738
+ const minute = +ir.pattern.minute;
739
+ const cadence = hourCadence(ir, minute) ?? hourRangeCadence(ir, minute);
623
740
  if (cadence !== null) {
624
741
  return cadence;
625
742
  }
@@ -679,7 +796,11 @@ function needsDailyFrame(ir) {
679
796
  if (ir.plan.kind === "clockTimes" || isComposeMinuteZero(ir)) {
680
797
  return true;
681
798
  }
682
- return ir.plan.kind === "hourStep" && !cleanStep(stepSegment(ir.analyses.segments.hour), 24);
799
+ if (ir.plan.kind !== "hourStep") {
800
+ return false;
801
+ }
802
+ const segment = stepSegment(ir.analyses.segments.hour);
803
+ return !cleanStep(segment, 24) && !openOffsetCleanStride(ir, segment);
683
804
  }
684
805
  function render(ir, plan, opts) {
685
806
  return renderers[plan.kind](