cronli5 0.8.0 → 0.8.2

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.js CHANGED
@@ -352,6 +352,9 @@ function minutesList(schedule, opts) {
352
352
  opts
353
353
  ) ?? "en los minutos " + joinList(segmentWords(segmentsOf(schedule, "minute"))) + " de cada hora";
354
354
  }
355
+ function withoutHourAnchor(lead) {
356
+ return lead.replace(/ de cada hora$/, "");
357
+ }
355
358
  function minuteRangeLead(minuteField) {
356
359
  const bounds = minuteField.split("-");
357
360
  return "cada minuto del " + bounds[0] + " al " + bounds[1];
@@ -422,7 +425,7 @@ function renderMinuteFrequency(schedule, plan, opts) {
422
425
  } else if (plan.hours.kind === "window") {
423
426
  phrase += " " + hourWindow(plan.hours, opts);
424
427
  } else if (plan.hours.kind === "step") {
425
- phrase += ", " + stepHourSpan(stepSegment(schedule, "hour"), opts);
428
+ phrase = withoutHourAnchor(phrase) + ", " + stepHourSpan(stepSegment(schedule, "hour"), opts);
426
429
  }
427
430
  return phrase + trailingQualifier(schedule, opts);
428
431
  }
@@ -459,7 +462,7 @@ function renderMinuteSpanAcrossHourStep(schedule, plan, opts) {
459
462
  if (plan.form === "wildcard") {
460
463
  return "cada minuto, " + stepHourSpan(segment, opts) + trailingQualifier(schedule, opts);
461
464
  }
462
- const lead = plan.form === "list" ? minutesList(schedule, opts) : minuteRangeLead(schedule.pattern.minute);
465
+ const lead = withoutHourAnchor(plan.form === "list" ? minutesList(schedule, opts) : minuteRangeLead(schedule.pattern.minute));
463
466
  return lead + ", " + (cadence ?? stepHours(segment, opts)) + trailingQualifier(schedule, opts);
464
467
  }
465
468
  function renderEveryHour(schedule, plan, opts) {
@@ -770,7 +773,7 @@ function renderCompactClockTimes(schedule, plan, opts) {
770
773
  );
771
774
  }
772
775
  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);
776
+ const phrase = cadence ? withoutHourAnchor(minutesList(schedule, opts)) + ", " + cadence + trailingQualifier(schedule, opts) : minutesList(schedule, opts) + ", " + hourContextTimes(schedule, opts) + trailingQualifier(schedule, opts);
774
777
  return schedule.analyses.clockSecond ? secondsLeadClause(schedule, opts) + ", " + phrase : phrase;
775
778
  }
776
779
  var renderers = {
package/dist/lang/fi.cjs CHANGED
@@ -399,8 +399,8 @@ function renderComposeSeconds(schedule, plan, opts) {
399
399
  if (plan.rest.kind === "minuteFrequency" && schedule.pattern.second !== "*") {
400
400
  return composeSecondsOverMinuteStep(schedule, plan.rest, opts);
401
401
  }
402
- if (plan.rest.kind === "clockTimes" && plan.rest.times.every((time) => +time.minute === 0)) {
403
- return composeMinuteZero(schedule, plan.rest, opts);
402
+ if (plan.rest.kind === "clockTimes" && schedule.shapes.minute === "single") {
403
+ return composeSingleMinute(schedule, plan.rest, opts);
404
404
  }
405
405
  if (isEveryOtherMinuteSeconds(schedule, plan)) {
406
406
  return secondsLeadClause(schedule, opts) + " joka toisena minuuttina";
@@ -416,7 +416,7 @@ function isEveryOtherMinuteSeconds(schedule, plan) {
416
416
  const seg = stepSegment(schedule, "minute");
417
417
  return seg.startToken === "*" && seg.interval === 2;
418
418
  }
419
- function composeMinuteZero(schedule, rest, opts) {
419
+ function composeSingleMinute(schedule, rest, opts) {
420
420
  const clocks = rest.times.map(function clock(time) {
421
421
  return clockDigits(
422
422
  { hour: time.hour, minute: time.minute },
@@ -540,7 +540,7 @@ function renderMinuteFrequency(schedule, plan, opts) {
540
540
  if (plan.hours.kind === "during") {
541
541
  const cadence = unevenHourCadence(schedule, opts);
542
542
  if (cadence !== null) {
543
- return stepCycle60(seg, units.minute, opts) + ", " + cadence + trailingQualifier(schedule, opts);
543
+ return withoutHourAnchor(stepCycle60(seg, units.minute, opts)) + ", " + cadence + trailingQualifier(schedule, opts);
544
544
  }
545
545
  if (minuteStepIsAnchored(seg)) {
546
546
  const bareHours = kloFromTimes(schedule, plan.hours.times, opts);
@@ -548,11 +548,12 @@ function renderMinuteFrequency(schedule, plan, opts) {
548
548
  }
549
549
  return stepCycle60(seg, units.minute, opts) + " " + hourWindowsFromTimes(schedule, plan.hours.times, opts) + trailingQualifier(schedule, opts);
550
550
  }
551
- let phrase = stepCycle60(seg, units.minute, opts);
551
+ const phraseBase = stepCycle60(seg, units.minute, opts);
552
+ let phrase = phraseBase;
552
553
  if (plan.hours.kind === "window") {
553
554
  phrase += " " + hourWindow(plan.hours, opts);
554
555
  } else if (plan.hours.kind === "step") {
555
- phrase += " " + everyNthHour(stepSegment(schedule, "hour"), opts);
556
+ phrase = withoutHourAnchor(phraseBase) + " " + everyNthHour(stepSegment(schedule, "hour"), opts);
556
557
  }
557
558
  return phrase + trailingQualifier(schedule, opts);
558
559
  }
@@ -785,6 +786,9 @@ function stepCycle60(segment, unit, opts) {
785
786
  unit
786
787
  }, opts);
787
788
  }
789
+ function withoutHourAnchor(lead) {
790
+ return lead.replace(" " + units.minute.anchor + " ", " ");
791
+ }
788
792
  function stepHours(segment, opts) {
789
793
  if (segment.startToken.indexOf("-") !== -1) {
790
794
  return kloList(segment.fires, opts);
package/dist/lang/fi.js CHANGED
@@ -373,8 +373,8 @@ function renderComposeSeconds(schedule, plan, opts) {
373
373
  if (plan.rest.kind === "minuteFrequency" && schedule.pattern.second !== "*") {
374
374
  return composeSecondsOverMinuteStep(schedule, plan.rest, opts);
375
375
  }
376
- if (plan.rest.kind === "clockTimes" && plan.rest.times.every((time) => +time.minute === 0)) {
377
- return composeMinuteZero(schedule, plan.rest, opts);
376
+ if (plan.rest.kind === "clockTimes" && schedule.shapes.minute === "single") {
377
+ return composeSingleMinute(schedule, plan.rest, opts);
378
378
  }
379
379
  if (isEveryOtherMinuteSeconds(schedule, plan)) {
380
380
  return secondsLeadClause(schedule, opts) + " joka toisena minuuttina";
@@ -390,7 +390,7 @@ function isEveryOtherMinuteSeconds(schedule, plan) {
390
390
  const seg = stepSegment(schedule, "minute");
391
391
  return seg.startToken === "*" && seg.interval === 2;
392
392
  }
393
- function composeMinuteZero(schedule, rest, opts) {
393
+ function composeSingleMinute(schedule, rest, opts) {
394
394
  const clocks = rest.times.map(function clock(time) {
395
395
  return clockDigits(
396
396
  { hour: time.hour, minute: time.minute },
@@ -514,7 +514,7 @@ function renderMinuteFrequency(schedule, plan, opts) {
514
514
  if (plan.hours.kind === "during") {
515
515
  const cadence = unevenHourCadence(schedule, opts);
516
516
  if (cadence !== null) {
517
- return stepCycle60(seg, units.minute, opts) + ", " + cadence + trailingQualifier(schedule, opts);
517
+ return withoutHourAnchor(stepCycle60(seg, units.minute, opts)) + ", " + cadence + trailingQualifier(schedule, opts);
518
518
  }
519
519
  if (minuteStepIsAnchored(seg)) {
520
520
  const bareHours = kloFromTimes(schedule, plan.hours.times, opts);
@@ -522,11 +522,12 @@ function renderMinuteFrequency(schedule, plan, opts) {
522
522
  }
523
523
  return stepCycle60(seg, units.minute, opts) + " " + hourWindowsFromTimes(schedule, plan.hours.times, opts) + trailingQualifier(schedule, opts);
524
524
  }
525
- let phrase = stepCycle60(seg, units.minute, opts);
525
+ const phraseBase = stepCycle60(seg, units.minute, opts);
526
+ let phrase = phraseBase;
526
527
  if (plan.hours.kind === "window") {
527
528
  phrase += " " + hourWindow(plan.hours, opts);
528
529
  } else if (plan.hours.kind === "step") {
529
- phrase += " " + everyNthHour(stepSegment(schedule, "hour"), opts);
530
+ phrase = withoutHourAnchor(phraseBase) + " " + everyNthHour(stepSegment(schedule, "hour"), opts);
530
531
  }
531
532
  return phrase + trailingQualifier(schedule, opts);
532
533
  }
@@ -759,6 +760,9 @@ function stepCycle60(segment, unit, opts) {
759
760
  unit
760
761
  }, opts);
761
762
  }
763
+ function withoutHourAnchor(lead) {
764
+ return lead.replace(" " + units.minute.anchor + " ", " ");
765
+ }
762
766
  function stepHours(segment, opts) {
763
767
  if (segment.startToken.indexOf("-") !== -1) {
764
768
  return kloList(segment.fires, opts);
package/dist/lang/fr.cjs CHANGED
@@ -365,6 +365,9 @@ function minutesList(schedule, opts) {
365
365
  opts
366
366
  ) ?? "aux minutes " + joinList(segmentWords(segmentsOf(schedule, "minute"))) + " de chaque heure";
367
367
  }
368
+ function withoutHourAnchor(lead) {
369
+ return lead.replace(/ de chaque heure$/, "");
370
+ }
368
371
  function minuteRangeLead(minuteField) {
369
372
  const bounds = minuteField.split("-");
370
373
  return "chaque minute de " + bounds[0] + " \xE0 " + bounds[1];
@@ -402,7 +405,7 @@ function renderMinuteFrequency(schedule, plan, opts) {
402
405
  } else if (plan.hours.kind === "window") {
403
406
  phrase += " " + hourWindow(plan.hours, opts);
404
407
  } else if (plan.hours.kind === "step") {
405
- phrase += ", " + stepHourSpan(stepSegment(schedule, "hour"), opts);
408
+ phrase = withoutHourAnchor(phrase) + ", " + stepHourSpan(stepSegment(schedule, "hour"), opts);
406
409
  }
407
410
  return phrase + trailingQualifier(schedule, opts);
408
411
  }
@@ -439,7 +442,7 @@ function renderMinuteSpanAcrossHourStep(schedule, plan, opts) {
439
442
  if (plan.form === "wildcard") {
440
443
  return "chaque minute, " + stepHourSpan(segment, opts) + trailingQualifier(schedule, opts);
441
444
  }
442
- const lead = plan.form === "list" ? minutesList(schedule, opts) : minuteRangeLead(schedule.pattern.minute);
445
+ const lead = withoutHourAnchor(plan.form === "list" ? minutesList(schedule, opts) : minuteRangeLead(schedule.pattern.minute));
443
446
  return lead + ", " + (cadence ?? stepHours(segment, opts)) + trailingQualifier(schedule, opts);
444
447
  }
445
448
  function renderEveryHour(schedule, plan, opts) {
@@ -612,7 +615,7 @@ function renderCompactClockTimes(schedule, plan, opts) {
612
615
  );
613
616
  }
614
617
  const cadence = unevenHourCadence(schedule, opts);
615
- const phrase = cadence ? minutesList(schedule, opts) + ", " + cadence + trailingQualifier(schedule, opts) : minutesList(schedule, opts) + ", " + hourContextTimes(schedule, opts) + trailingQualifier(schedule, opts);
618
+ const phrase = cadence ? withoutHourAnchor(minutesList(schedule, opts)) + ", " + cadence + trailingQualifier(schedule, opts) : minutesList(schedule, opts) + ", " + hourContextTimes(schedule, opts) + trailingQualifier(schedule, opts);
616
619
  return schedule.analyses.clockSecond ? secondsLeadClause(schedule, opts) + ", " + phrase : phrase;
617
620
  }
618
621
  var renderers = {
package/dist/lang/fr.js CHANGED
@@ -339,6 +339,9 @@ function minutesList(schedule, opts) {
339
339
  opts
340
340
  ) ?? "aux minutes " + joinList(segmentWords(segmentsOf(schedule, "minute"))) + " de chaque heure";
341
341
  }
342
+ function withoutHourAnchor(lead) {
343
+ return lead.replace(/ de chaque heure$/, "");
344
+ }
342
345
  function minuteRangeLead(minuteField) {
343
346
  const bounds = minuteField.split("-");
344
347
  return "chaque minute de " + bounds[0] + " \xE0 " + bounds[1];
@@ -376,7 +379,7 @@ function renderMinuteFrequency(schedule, plan, opts) {
376
379
  } else if (plan.hours.kind === "window") {
377
380
  phrase += " " + hourWindow(plan.hours, opts);
378
381
  } else if (plan.hours.kind === "step") {
379
- phrase += ", " + stepHourSpan(stepSegment(schedule, "hour"), opts);
382
+ phrase = withoutHourAnchor(phrase) + ", " + stepHourSpan(stepSegment(schedule, "hour"), opts);
380
383
  }
381
384
  return phrase + trailingQualifier(schedule, opts);
382
385
  }
@@ -413,7 +416,7 @@ function renderMinuteSpanAcrossHourStep(schedule, plan, opts) {
413
416
  if (plan.form === "wildcard") {
414
417
  return "chaque minute, " + stepHourSpan(segment, opts) + trailingQualifier(schedule, opts);
415
418
  }
416
- const lead = plan.form === "list" ? minutesList(schedule, opts) : minuteRangeLead(schedule.pattern.minute);
419
+ const lead = withoutHourAnchor(plan.form === "list" ? minutesList(schedule, opts) : minuteRangeLead(schedule.pattern.minute));
417
420
  return lead + ", " + (cadence ?? stepHours(segment, opts)) + trailingQualifier(schedule, opts);
418
421
  }
419
422
  function renderEveryHour(schedule, plan, opts) {
@@ -586,7 +589,7 @@ function renderCompactClockTimes(schedule, plan, opts) {
586
589
  );
587
590
  }
588
591
  const cadence = unevenHourCadence(schedule, opts);
589
- const phrase = cadence ? minutesList(schedule, opts) + ", " + cadence + trailingQualifier(schedule, opts) : minutesList(schedule, opts) + ", " + hourContextTimes(schedule, opts) + trailingQualifier(schedule, opts);
592
+ const phrase = cadence ? withoutHourAnchor(minutesList(schedule, opts)) + ", " + cadence + trailingQualifier(schedule, opts) : minutesList(schedule, opts) + ", " + hourContextTimes(schedule, opts) + trailingQualifier(schedule, opts);
590
593
  return schedule.analyses.clockSecond ? secondsLeadClause(schedule, opts) + ", " + phrase : phrase;
591
594
  }
592
595
  var renderers = {
package/dist/lang/pt.cjs CHANGED
@@ -453,6 +453,9 @@ function minutesList(schedule, opts) {
453
453
  opts
454
454
  ) ?? "nos minutos " + joinList(segmentWords(segmentsOf(schedule, "minute"))) + " de cada hora";
455
455
  }
456
+ function withoutHourAnchor(lead) {
457
+ return lead.replace(/ de cada hora$/, "");
458
+ }
456
459
  function minuteRangeLead(minuteField) {
457
460
  const bounds = minuteField.split("-");
458
461
  return "a cada minuto do " + bounds[0] + " ao " + bounds[1];
@@ -523,7 +526,7 @@ function renderMinuteFrequency(schedule, plan, opts) {
523
526
  } else if (plan.hours.kind === "window") {
524
527
  phrase += " " + hourWindow(plan.hours, opts);
525
528
  } else if (plan.hours.kind === "step") {
526
- phrase += ", " + stepHourSpan(stepSegment(schedule, "hour"), opts);
529
+ phrase = withoutHourAnchor(phrase) + ", " + stepHourSpan(stepSegment(schedule, "hour"), opts);
527
530
  }
528
531
  return phrase + trailingQualifier(schedule, opts);
529
532
  }
@@ -560,7 +563,7 @@ function renderMinuteSpanAcrossHourStep(schedule, plan, opts) {
560
563
  if (plan.form === "wildcard") {
561
564
  return "a cada minuto, " + stepHourSpan(segment, opts) + trailingQualifier(schedule, opts);
562
565
  }
563
- const lead = plan.form === "list" ? minutesList(schedule, opts) : minuteRangeLead(schedule.pattern.minute);
566
+ const lead = withoutHourAnchor(plan.form === "list" ? minutesList(schedule, opts) : minuteRangeLead(schedule.pattern.minute));
564
567
  return lead + ", " + (cadence ?? stepHours(segment, opts)) + trailingQualifier(schedule, opts);
565
568
  }
566
569
  function renderEveryHour(schedule, plan, opts) {
@@ -865,7 +868,7 @@ function renderCompactClockTimes(schedule, plan, opts) {
865
868
  );
866
869
  }
867
870
  const cadence = unevenHourCadence(schedule, opts);
868
- const phrase = cadence ? minutesList(schedule, opts) + ", " + cadence + trailingQualifier(schedule, opts) : minutesList(schedule, opts) + ", " + hourContextTimes(schedule, opts) + trailingQualifier(schedule, opts);
871
+ const phrase = cadence ? withoutHourAnchor(minutesList(schedule, opts)) + ", " + cadence + trailingQualifier(schedule, opts) : minutesList(schedule, opts) + ", " + hourContextTimes(schedule, opts) + trailingQualifier(schedule, opts);
869
872
  return schedule.analyses.clockSecond ? secondsLeadClause(schedule, opts) + ", " + phrase : phrase;
870
873
  }
871
874
  var renderers = {
package/dist/lang/pt.js CHANGED
@@ -427,6 +427,9 @@ function minutesList(schedule, opts) {
427
427
  opts
428
428
  ) ?? "nos minutos " + joinList(segmentWords(segmentsOf(schedule, "minute"))) + " de cada hora";
429
429
  }
430
+ function withoutHourAnchor(lead) {
431
+ return lead.replace(/ de cada hora$/, "");
432
+ }
430
433
  function minuteRangeLead(minuteField) {
431
434
  const bounds = minuteField.split("-");
432
435
  return "a cada minuto do " + bounds[0] + " ao " + bounds[1];
@@ -497,7 +500,7 @@ function renderMinuteFrequency(schedule, plan, opts) {
497
500
  } else if (plan.hours.kind === "window") {
498
501
  phrase += " " + hourWindow(plan.hours, opts);
499
502
  } else if (plan.hours.kind === "step") {
500
- phrase += ", " + stepHourSpan(stepSegment(schedule, "hour"), opts);
503
+ phrase = withoutHourAnchor(phrase) + ", " + stepHourSpan(stepSegment(schedule, "hour"), opts);
501
504
  }
502
505
  return phrase + trailingQualifier(schedule, opts);
503
506
  }
@@ -534,7 +537,7 @@ function renderMinuteSpanAcrossHourStep(schedule, plan, opts) {
534
537
  if (plan.form === "wildcard") {
535
538
  return "a cada minuto, " + stepHourSpan(segment, opts) + trailingQualifier(schedule, opts);
536
539
  }
537
- const lead = plan.form === "list" ? minutesList(schedule, opts) : minuteRangeLead(schedule.pattern.minute);
540
+ const lead = withoutHourAnchor(plan.form === "list" ? minutesList(schedule, opts) : minuteRangeLead(schedule.pattern.minute));
538
541
  return lead + ", " + (cadence ?? stepHours(segment, opts)) + trailingQualifier(schedule, opts);
539
542
  }
540
543
  function renderEveryHour(schedule, plan, opts) {
@@ -839,7 +842,7 @@ function renderCompactClockTimes(schedule, plan, opts) {
839
842
  );
840
843
  }
841
844
  const cadence = unevenHourCadence(schedule, opts);
842
- const phrase = cadence ? minutesList(schedule, opts) + ", " + cadence + trailingQualifier(schedule, opts) : minutesList(schedule, opts) + ", " + hourContextTimes(schedule, opts) + trailingQualifier(schedule, opts);
845
+ const phrase = cadence ? withoutHourAnchor(minutesList(schedule, opts)) + ", " + cadence + trailingQualifier(schedule, opts) : minutesList(schedule, opts) + ", " + hourContextTimes(schedule, opts) + trailingQualifier(schedule, opts);
843
846
  return schedule.analyses.clockSecond ? secondsLeadClause(schedule, opts) + ", " + phrase : phrase;
844
847
  }
845
848
  var renderers = {
package/dist/lang/zh.cjs CHANGED
@@ -346,6 +346,9 @@ function minuteHourClause(schedule) {
346
346
  function renderMinutePast(schedule) {
347
347
  return minuteHourClause(schedule);
348
348
  }
349
+ function withoutHourAnchor(clause) {
350
+ return clause.replace(/^每小时/, "");
351
+ }
349
352
  function hourSegmentWords(segment) {
350
353
  if (segment.kind === "range") {
351
354
  return [hourWord(+segment.bounds[0]) + "\u81F3" + hourWord(+segment.bounds[1])];
@@ -373,7 +376,8 @@ function renderMinuteFrequency(schedule, plan) {
373
376
  if (hours.kind === "step" || hours.kind === "during") {
374
377
  const hourCad = unevenHourCadence(schedule);
375
378
  if (hourCad !== null) {
376
- return hourCad + (hourCad.indexOf("\u81F3") === -1 ? "" : "\uFF0C") + base;
379
+ const minuteBase = hours.kind === "step" ? withoutHourAnchor(base) : base;
380
+ return hourCad + (hourCad.indexOf("\u81F3") === -1 ? "" : "\uFF0C") + minuteBase;
377
381
  }
378
382
  }
379
383
  if (hours.kind === "window" && hours.from === hours.to) {
@@ -406,9 +410,9 @@ function renderMinuteSpanAcrossHourStep(schedule, plan) {
406
410
  const hourStep = stepSegment(schedule, "hour");
407
411
  const { form } = plan;
408
412
  if (form === "list") {
409
- return hourCadencePhrase(schedule) + "\uFF0C" + renderMinutePast(schedule);
413
+ return hourCadencePhrase(schedule) + "\uFF0C" + withoutHourAnchor(renderMinutePast(schedule));
410
414
  }
411
- const minuteTail = form === "wildcard" ? "\u6BCF\u5206\u949F" : minuteHourClause(schedule) + "\uFF0C\u6BCF\u5206\u949F";
415
+ const minuteTail = form === "wildcard" ? "\u6BCF\u5206\u949F" : withoutHourAnchor(minuteHourClause(schedule)) + "\uFF0C\u6BCF\u5206\u949F";
412
416
  if (hourStep.startToken !== "*") {
413
417
  return hourCadencePhrase(schedule) + "\uFF0C" + minuteTail;
414
418
  }
@@ -436,7 +440,7 @@ function renderCompactClockTimes(schedule, plan) {
436
440
  const tail = secs.length && schedule.pattern.second !== "0" ? "\uFF0C\u7B2C" + valueText(secs) + "\u79D2" : "";
437
441
  if (!compact.fold) {
438
442
  const hourCad = unevenHourCadence(schedule);
439
- return hourCad === null ? minuteHourClause(schedule) + "\uFF0C\u5728" + hourList(schedule) + tail : hourCad + "\uFF0C" + minuteHourClause(schedule) + tail;
443
+ return hourCad === null ? minuteHourClause(schedule) + "\uFF0C\u5728" + hourList(schedule) + tail : hourCad + "\uFF0C" + withoutHourAnchor(minuteHourClause(schedule)) + tail;
440
444
  }
441
445
  if (compact.minute > 0) {
442
446
  return minuteHourClause(schedule) + "\uFF0C\u5728" + hourList(schedule) + tail;
@@ -599,6 +603,10 @@ function composeSecondsOnHour(schedule, plan, opts) {
599
603
  if (composedClock && schedule.pattern.minute === "0") {
600
604
  return composeMinuteZeroClocks(schedule, sec);
601
605
  }
606
+ const fusedSingleMinute = composeSingleMinuteClocks(schedule, rest, sec, opts);
607
+ if (fusedSingleMinute !== null) {
608
+ return fusedSingleMinute;
609
+ }
602
610
  const restText = render(schedule, rest, opts);
603
611
  const secTail = clockRestCarriesSecond(rest) ? "" : sec;
604
612
  if (composedClock && isDaily(schedule)) {
@@ -609,6 +617,13 @@ function composeSecondsOnHour(schedule, plan, opts) {
609
617
  }
610
618
  return restText + secTail;
611
619
  }
620
+ function composeSingleMinuteClocks(schedule, rest, sec, opts) {
621
+ if (rest.kind !== "clockTimes" || schedule.shapes.minute !== "single" || clockRestCarriesSecond(rest)) {
622
+ return null;
623
+ }
624
+ const core = render(schedule, rest, opts) + minuteZeroSecondTail(schedule, sec);
625
+ return isDaily(schedule) ? "\u6BCF\u5929" + core : core;
626
+ }
612
627
  function composeMinuteZeroClocks(schedule, sec) {
613
628
  if (hasHourWindow(schedule)) {
614
629
  return isDaily(schedule) ? "\u6BCF\u5929" + hourRangeWindow(schedule, sec) : hourRangeWindow(schedule, sec);
@@ -616,11 +631,16 @@ function composeMinuteZeroClocks(schedule, sec) {
616
631
  const clocks = hourFires(schedule).map(function clock(hour) {
617
632
  return hour === 12 ? "\u6B63\u5348" : hourWord(hour) + "0\u5206";
618
633
  });
619
- const nested = strideFromSegments(segmentsOf(schedule, "second"), "\u79D2", "\u79D2", "");
620
- const tail = sec === "\u6BCF\u79D2" ? "\u7684\u6BCF\u4E00\u79D2" : "\u7684" + (nested ?? sec);
621
- const core = joinAnd(clocks) + tail;
634
+ const core = joinAnd(clocks) + minuteZeroSecondTail(schedule, sec);
622
635
  return isDaily(schedule) ? "\u6BCF\u5929" + core : core;
623
636
  }
637
+ function minuteZeroSecondTail(schedule, sec) {
638
+ if (sec === "\u6BCF\u79D2") {
639
+ return "\u7684\u6BCF\u4E00\u79D2";
640
+ }
641
+ const nested = strideFromSegments(segmentsOf(schedule, "second"), "\u79D2", "\u79D2", "");
642
+ return "\u7684" + (nested ?? sec);
643
+ }
624
644
  function hasHourWindow(schedule) {
625
645
  return segmentsOf(schedule, "hour").some(function range(segment) {
626
646
  return segment.kind === "range";
@@ -667,7 +687,7 @@ function composeSecondsListed(schedule) {
667
687
  }
668
688
  const hourCad = unevenHourCadence(schedule);
669
689
  if (hourCad !== null) {
670
- return hourCad + "\uFF0C" + minutes + "\uFF0C" + sec;
690
+ return hourCad + "\uFF0C" + withoutHourAnchor(minutes) + "\uFF0C" + sec;
671
691
  }
672
692
  return hourFrame(schedule) + minutes + "\uFF0C" + sec;
673
693
  }
package/dist/lang/zh.js CHANGED
@@ -320,6 +320,9 @@ function minuteHourClause(schedule) {
320
320
  function renderMinutePast(schedule) {
321
321
  return minuteHourClause(schedule);
322
322
  }
323
+ function withoutHourAnchor(clause) {
324
+ return clause.replace(/^每小时/, "");
325
+ }
323
326
  function hourSegmentWords(segment) {
324
327
  if (segment.kind === "range") {
325
328
  return [hourWord(+segment.bounds[0]) + "\u81F3" + hourWord(+segment.bounds[1])];
@@ -347,7 +350,8 @@ function renderMinuteFrequency(schedule, plan) {
347
350
  if (hours.kind === "step" || hours.kind === "during") {
348
351
  const hourCad = unevenHourCadence(schedule);
349
352
  if (hourCad !== null) {
350
- return hourCad + (hourCad.indexOf("\u81F3") === -1 ? "" : "\uFF0C") + base;
353
+ const minuteBase = hours.kind === "step" ? withoutHourAnchor(base) : base;
354
+ return hourCad + (hourCad.indexOf("\u81F3") === -1 ? "" : "\uFF0C") + minuteBase;
351
355
  }
352
356
  }
353
357
  if (hours.kind === "window" && hours.from === hours.to) {
@@ -380,9 +384,9 @@ function renderMinuteSpanAcrossHourStep(schedule, plan) {
380
384
  const hourStep = stepSegment(schedule, "hour");
381
385
  const { form } = plan;
382
386
  if (form === "list") {
383
- return hourCadencePhrase(schedule) + "\uFF0C" + renderMinutePast(schedule);
387
+ return hourCadencePhrase(schedule) + "\uFF0C" + withoutHourAnchor(renderMinutePast(schedule));
384
388
  }
385
- const minuteTail = form === "wildcard" ? "\u6BCF\u5206\u949F" : minuteHourClause(schedule) + "\uFF0C\u6BCF\u5206\u949F";
389
+ const minuteTail = form === "wildcard" ? "\u6BCF\u5206\u949F" : withoutHourAnchor(minuteHourClause(schedule)) + "\uFF0C\u6BCF\u5206\u949F";
386
390
  if (hourStep.startToken !== "*") {
387
391
  return hourCadencePhrase(schedule) + "\uFF0C" + minuteTail;
388
392
  }
@@ -410,7 +414,7 @@ function renderCompactClockTimes(schedule, plan) {
410
414
  const tail = secs.length && schedule.pattern.second !== "0" ? "\uFF0C\u7B2C" + valueText(secs) + "\u79D2" : "";
411
415
  if (!compact.fold) {
412
416
  const hourCad = unevenHourCadence(schedule);
413
- return hourCad === null ? minuteHourClause(schedule) + "\uFF0C\u5728" + hourList(schedule) + tail : hourCad + "\uFF0C" + minuteHourClause(schedule) + tail;
417
+ return hourCad === null ? minuteHourClause(schedule) + "\uFF0C\u5728" + hourList(schedule) + tail : hourCad + "\uFF0C" + withoutHourAnchor(minuteHourClause(schedule)) + tail;
414
418
  }
415
419
  if (compact.minute > 0) {
416
420
  return minuteHourClause(schedule) + "\uFF0C\u5728" + hourList(schedule) + tail;
@@ -573,6 +577,10 @@ function composeSecondsOnHour(schedule, plan, opts) {
573
577
  if (composedClock && schedule.pattern.minute === "0") {
574
578
  return composeMinuteZeroClocks(schedule, sec);
575
579
  }
580
+ const fusedSingleMinute = composeSingleMinuteClocks(schedule, rest, sec, opts);
581
+ if (fusedSingleMinute !== null) {
582
+ return fusedSingleMinute;
583
+ }
576
584
  const restText = render(schedule, rest, opts);
577
585
  const secTail = clockRestCarriesSecond(rest) ? "" : sec;
578
586
  if (composedClock && isDaily(schedule)) {
@@ -583,6 +591,13 @@ function composeSecondsOnHour(schedule, plan, opts) {
583
591
  }
584
592
  return restText + secTail;
585
593
  }
594
+ function composeSingleMinuteClocks(schedule, rest, sec, opts) {
595
+ if (rest.kind !== "clockTimes" || schedule.shapes.minute !== "single" || clockRestCarriesSecond(rest)) {
596
+ return null;
597
+ }
598
+ const core = render(schedule, rest, opts) + minuteZeroSecondTail(schedule, sec);
599
+ return isDaily(schedule) ? "\u6BCF\u5929" + core : core;
600
+ }
586
601
  function composeMinuteZeroClocks(schedule, sec) {
587
602
  if (hasHourWindow(schedule)) {
588
603
  return isDaily(schedule) ? "\u6BCF\u5929" + hourRangeWindow(schedule, sec) : hourRangeWindow(schedule, sec);
@@ -590,11 +605,16 @@ function composeMinuteZeroClocks(schedule, sec) {
590
605
  const clocks = hourFires(schedule).map(function clock(hour) {
591
606
  return hour === 12 ? "\u6B63\u5348" : hourWord(hour) + "0\u5206";
592
607
  });
593
- const nested = strideFromSegments(segmentsOf(schedule, "second"), "\u79D2", "\u79D2", "");
594
- const tail = sec === "\u6BCF\u79D2" ? "\u7684\u6BCF\u4E00\u79D2" : "\u7684" + (nested ?? sec);
595
- const core = joinAnd(clocks) + tail;
608
+ const core = joinAnd(clocks) + minuteZeroSecondTail(schedule, sec);
596
609
  return isDaily(schedule) ? "\u6BCF\u5929" + core : core;
597
610
  }
611
+ function minuteZeroSecondTail(schedule, sec) {
612
+ if (sec === "\u6BCF\u79D2") {
613
+ return "\u7684\u6BCF\u4E00\u79D2";
614
+ }
615
+ const nested = strideFromSegments(segmentsOf(schedule, "second"), "\u79D2", "\u79D2", "");
616
+ return "\u7684" + (nested ?? sec);
617
+ }
598
618
  function hasHourWindow(schedule) {
599
619
  return segmentsOf(schedule, "hour").some(function range(segment) {
600
620
  return segment.kind === "range";
@@ -641,7 +661,7 @@ function composeSecondsListed(schedule) {
641
661
  }
642
662
  const hourCad = unevenHourCadence(schedule);
643
663
  if (hourCad !== null) {
644
- return hourCad + "\uFF0C" + minutes + "\uFF0C" + sec;
664
+ return hourCad + "\uFF0C" + withoutHourAnchor(minutes) + "\uFF0C" + sec;
645
665
  }
646
666
  return hourFrame(schedule) + minutes + "\uFF0C" + sec;
647
667
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cronli5",
3
- "version": "0.8.0",
3
+ "version": "0.8.2",
4
4
  "description": "Cron Like I'm Five: A Cron to English Utility",
5
5
  "repository": {
6
6
  "type": "git",
@@ -738,12 +738,13 @@ function renderComposeSeconds(
738
738
  }
739
739
  }
740
740
 
741
- // A sub-minute second with the minute pinned to 0 and a specific hour: the
742
- // clock-time rest would read "um 9 Uhr", which hides the pinned :00 (and so
743
- // the one-minute confinement 60 fires in :00, not 3,600 across the hour).
744
- // Bind the seconds into the explicit clock minute in the genitive ("der
745
- // Minute 9:00"); the recurring "täglich"/day frame is added in `describe`.
746
- if (composeMinuteZero(schedule, plan)) {
741
+ // A second over a single fixed minute and a specific hour is a single fixed
742
+ // timestamp: the clock-time rest would float the seconds as a separate
743
+ // apposition ("jede Sekunde, um 9:02 Uhr"), hiding that they belong to that
744
+ // one minute. Bind the seconds into the explicit clock minute in the genitive
745
+ // ("der Minute 9:02"), the same fusion the minute-0 case ("der Minute 9:00")
746
+ // uses; the recurring "täglich"/day frame is added in `describe`.
747
+ if (composeSingleMinute(schedule, plan)) {
747
748
  return secondsLead(schedule) + ' ' +
748
749
  clockMinuteGenitive(plan.rest.times, opts.style.sep);
749
750
  }
@@ -765,21 +766,23 @@ function renderComposeSeconds(
765
766
  return lead + render(schedule, plan.rest, opts);
766
767
  }
767
768
 
768
- // True when a compose-seconds plan is a sub-minute second over a minute-0
769
- // clock-time rest — the case that reads as the bare hour and so must surface
770
- // the pinned clock minute.
771
- function composeMinuteZero(
769
+ // True when a compose-seconds plan is a sub-minute second over a single fixed
770
+ // minute's clock-time rest — the single fixed timestamp whose seconds must fuse
771
+ // to the explicit clock minute rather than float as a separate apposition.
772
+ // Minute 0 ("der Minute 0:00") is just this with the minute being 0; any single
773
+ // fixed minute fuses the same way.
774
+ function composeSingleMinute(
772
775
  schedule: Schedule,
773
776
  plan: Extract<PlanNode, {kind: 'composeSeconds'}>
774
777
  ): plan is Extract<PlanNode, {kind: 'composeSeconds'}> &
775
778
  {rest: Extract<PlanNode, {kind: 'clockTimes'}>} {
776
779
  return plan.rest.kind === 'clockTimes' &&
777
- plan.rest.times.every((time) => +time.minute === 0);
780
+ schedule.shapes.minute === 'single';
778
781
  }
779
782
 
780
- // The pinned clock minute in the genitive: "der Minute 9:00" for one hour,
781
- // "der Minuten 9:00, 10:00 und 17:00" for several — the explicit ":00" so the
782
- // minute-0 confinement stays visible.
783
+ // The pinned clock minute in the genitive: "der Minute 9:02" for one hour,
784
+ // "der Minuten 9:00, 10:00 und 17:00" for several — the explicit minute so the
785
+ // single-fixed-minute confinement stays visible.
783
786
  function clockMinuteGenitive(
784
787
  times: {hour: number; minute: number}[],
785
788
  sep: string
@@ -940,18 +943,22 @@ function renderMinuteFrequency(
940
943
  if (plan.hours.kind === 'during') {
941
944
  // A bounded or uneven hour stride confines the minute cadence to its own
942
945
  // endpoint-pinning hour cadence ("alle 15 Minuten, alle 5 Stunden von 0 bis
943
- // 20 Uhr").
946
+ // 20 Uhr"). That hour step is the sole hour authority, so an offset minute
947
+ // cadence drops its generic "jeder Stunde" (an every-hour scope conflicting
948
+ // with the step); a list of specific hours keeps it.
944
949
  const cadence = unevenHourCadence(schedule);
945
950
 
946
951
  return cadence ?
947
- base + ', ' + cadence :
952
+ stepClause(segment, UNITS.minute, '') + ', ' + cadence :
948
953
  base + ' ' + duringHours(schedule, plan.hours.times, sep);
949
954
  }
950
955
 
951
956
  if (plan.hours.kind === 'step') {
952
957
  // The plan carries a step only for a clean step (dividing the day):
953
- // confine the cadence to every Nth hour ("in jeder zweiten Stunde").
954
- return base + ' ' +
958
+ // confine the cadence to every Nth hour ("in jeder zweiten Stunde"). The
959
+ // hour step is the sole hour authority, so the minute cadence drops its
960
+ // generic "jeder Stunde".
961
+ return stepClause(segment, UNITS.minute, '') + ' ' +
955
962
  everyNthHour(stepSegment(schedule, 'hour'));
956
963
  }
957
964
 
@@ -1405,28 +1412,31 @@ function qualifier(schedule: Schedule, months: Months): string {
1405
1412
 
1406
1413
  // Plan kinds whose clause is a clock time: the qualifier leads them ("montags
1407
1414
  // um 9 Uhr"); a frequency clause trails it ("jede Minute montags"). The
1408
- // minute-0 compose-seconds clause is anchored on a clock minute too, so the
1409
- // qualifier leads it ("montags jede Sekunde der Minute 9:00").
1415
+ // single-fixed-minute compose-seconds clause is anchored on a clock minute too,
1416
+ // so the qualifier leads it ("montags jede Sekunde der Minute 9:00").
1410
1417
  const LEADING_PLANS = new Set(['clockTimes']);
1411
1418
 
1412
1419
  // True when the leading qualifier should precede the clause: a clock-time
1413
- // plan, or the minute-0 compose-seconds clause that surfaces a clock minute.
1420
+ // plan, or the single-fixed-minute compose-seconds clause that surfaces a clock
1421
+ // minute.
1414
1422
  function leadsQualifier(schedule: Schedule): boolean {
1415
- return LEADING_PLANS.has(schedule.plan.kind) || isComposeMinuteZero(schedule);
1423
+ return LEADING_PLANS.has(schedule.plan.kind) ||
1424
+ isComposeSingleMinute(schedule);
1416
1425
  }
1417
1426
 
1418
- // Whether the planned clause is the minute-0 compose-seconds confinement
1419
- // (a sub-minute second over a minute-0 clock-time rest).
1420
- function isComposeMinuteZero(schedule: Schedule): boolean {
1427
+ // Whether the planned clause is the single-fixed-minute compose-seconds
1428
+ // confinement (a sub-minute second over a single fixed minute's clock-time
1429
+ // rest).
1430
+ function isComposeSingleMinute(schedule: Schedule): boolean {
1421
1431
  return schedule.plan.kind === 'composeSeconds' &&
1422
- composeMinuteZero(schedule, schedule.plan);
1432
+ composeSingleMinute(schedule, schedule.plan);
1423
1433
  }
1424
1434
 
1425
1435
  // True when the clause is a bare daily clock-time list and so needs the
1426
1436
  // "täglich" frame to read as recurring, not a one-off: clockTimes always, the
1427
- // minute-0 compose-seconds clause (a recurring clock minute), and an uneven
1428
- // hour step (rendered as its fire list "um 0, 5, … Uhr", not the cadence "alle
1429
- // N Stunden"). A frequency clause already implies recurrence.
1437
+ // single-fixed-minute compose-seconds clause (a recurring clock minute), and an
1438
+ // uneven hour step (rendered as its fire list "um 0, 5, … Uhr", not the cadence
1439
+ // "alle N Stunden"). A frequency clause already implies recurrence.
1430
1440
  function needsDailyFrame(schedule: Schedule): boolean {
1431
1441
  // An hour cadence is a sub-daily frequency, not a daily clock-time list, so
1432
1442
  // it must not take the "täglich" frame ("alle 2 Stunden", not "täglich alle
@@ -1435,7 +1445,7 @@ function needsDailyFrame(schedule: Schedule): boolean {
1435
1445
  return false;
1436
1446
  }
1437
1447
 
1438
- if (schedule.plan.kind === 'clockTimes' || isComposeMinuteZero(schedule)) {
1448
+ if (schedule.plan.kind === 'clockTimes' || isComposeSingleMinute(schedule)) {
1439
1449
  return true;
1440
1450
  }
1441
1451