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/fi.cjs CHANGED
@@ -224,6 +224,20 @@ var nthWeekdayNames = [
224
224
  "nelj\xE4nten\xE4",
225
225
  "viidenten\xE4"
226
226
  ];
227
+ var minuteStepOrdinals = {
228
+ 3: "kolmantena",
229
+ 4: "nelj\xE4nten\xE4",
230
+ 5: "viidenten\xE4",
231
+ 6: "kuudentena",
232
+ 7: "seitsem\xE4nten\xE4",
233
+ 8: "kahdeksantena",
234
+ 9: "yhdeks\xE4nten\xE4",
235
+ 10: "kymmenenten\xE4",
236
+ 12: "kahdentenatoista",
237
+ 15: "viidenten\xE4toista",
238
+ 20: "kahdentenakymmenenten\xE4",
239
+ 30: "kolmantenakymmenenten\xE4"
240
+ };
227
241
  var weekdays = [
228
242
  {
229
243
  ela: "sunnuntaista",
@@ -391,16 +405,42 @@ function composeHourCadence(schedule, plan, opts) {
391
405
  const minute = +schedule.pattern.minute;
392
406
  return hourCadence(schedule, minute, opts) ?? hourRangeCadence(schedule, minute, opts);
393
407
  }
408
+ function minuteStride(schedule) {
409
+ if (schedule.shapes.minute === "step") {
410
+ const segment = stepSegment(schedule, "minute");
411
+ const start = segment.startToken === "*" ? 0 : +segment.startToken;
412
+ return { interval: segment.interval, last: segment.fires[segment.fires.length - 1], start };
413
+ }
414
+ const values = singleValues(segmentsOf(schedule, "minute"));
415
+ return values && arithmeticStep(values);
416
+ }
417
+ function minuteStepConfinement(schedule, stride, opts) {
418
+ const ordinalForm = minuteStepOrdinals[stride.interval];
419
+ const minute = units.minute;
420
+ const head = ordinalForm ? " joka " + ordinalForm + " minuuttina" : " " + genitive(stride.interval, opts) + " " + minute.gen + " v\xE4lein";
421
+ const tail = renderStride({ ...stride, cycle: 60 }, {
422
+ bare: () => "",
423
+ offset: () => " " + minute.anchor + " " + minute.ela + " " + stride.start + " alkaen",
424
+ bounded: () => " " + minute.ela + " " + stride.start + " " + minute.ill + " " + stride.last
425
+ });
426
+ return secondsLeadClause(schedule, opts) + head + tail + trailingQualifier(schedule, opts);
427
+ }
428
+ function isSteppedMinuteSeconds(schedule, plan) {
429
+ return (plan.rest.kind === "minuteFrequency" || plan.rest.kind === "multipleMinutes") && (schedule.pattern.second === "*" || schedule.shapes.second === "step") && schedule.shapes.hour === "wildcard" && schedule.pattern.minute !== "*/2" && minuteStride(schedule) !== null;
430
+ }
394
431
  function renderComposeSeconds(schedule, plan, opts) {
395
432
  const cadence = composeHourCadence(schedule, plan, opts);
396
433
  if (cadence !== null) {
397
434
  return cadence;
398
435
  }
436
+ if (isSteppedMinuteSeconds(schedule, plan)) {
437
+ return minuteStepConfinement(schedule, minuteStride(schedule), opts);
438
+ }
399
439
  if (plan.rest.kind === "minuteFrequency" && schedule.pattern.second !== "*") {
400
440
  return composeSecondsOverMinuteStep(schedule, plan.rest, opts);
401
441
  }
402
- if (plan.rest.kind === "clockTimes" && plan.rest.times.every((time) => +time.minute === 0)) {
403
- return composeMinuteZero(schedule, plan.rest, opts);
442
+ if (plan.rest.kind === "clockTimes" && schedule.shapes.minute === "single") {
443
+ return composeSingleMinute(schedule, plan.rest, opts);
404
444
  }
405
445
  if (isEveryOtherMinuteSeconds(schedule, plan)) {
406
446
  return secondsLeadClause(schedule, opts) + " joka toisena minuuttina";
@@ -416,7 +456,7 @@ function isEveryOtherMinuteSeconds(schedule, plan) {
416
456
  const seg = stepSegment(schedule, "minute");
417
457
  return seg.startToken === "*" && seg.interval === 2;
418
458
  }
419
- function composeMinuteZero(schedule, rest, opts) {
459
+ function composeSingleMinute(schedule, rest, opts) {
420
460
  const clocks = rest.times.map(function clock(time) {
421
461
  return clockDigits(
422
462
  { hour: time.hour, minute: time.minute },
@@ -540,7 +580,7 @@ function renderMinuteFrequency(schedule, plan, opts) {
540
580
  if (plan.hours.kind === "during") {
541
581
  const cadence = unevenHourCadence(schedule, opts);
542
582
  if (cadence !== null) {
543
- return stepCycle60(seg, units.minute, opts) + ", " + cadence + trailingQualifier(schedule, opts);
583
+ return withoutHourAnchor(stepCycle60(seg, units.minute, opts)) + ", " + cadence + trailingQualifier(schedule, opts);
544
584
  }
545
585
  if (minuteStepIsAnchored(seg)) {
546
586
  const bareHours = kloFromTimes(schedule, plan.hours.times, opts);
@@ -548,11 +588,12 @@ function renderMinuteFrequency(schedule, plan, opts) {
548
588
  }
549
589
  return stepCycle60(seg, units.minute, opts) + " " + hourWindowsFromTimes(schedule, plan.hours.times, opts) + trailingQualifier(schedule, opts);
550
590
  }
551
- let phrase = stepCycle60(seg, units.minute, opts);
591
+ const phraseBase = stepCycle60(seg, units.minute, opts);
592
+ let phrase = phraseBase;
552
593
  if (plan.hours.kind === "window") {
553
594
  phrase += " " + hourWindow(plan.hours, opts);
554
595
  } else if (plan.hours.kind === "step") {
555
- phrase += " " + everyNthHour(stepSegment(schedule, "hour"), opts);
596
+ phrase = withoutHourAnchor(phraseBase) + " " + everyNthHour(stepSegment(schedule, "hour"), opts);
556
597
  }
557
598
  return phrase + trailingQualifier(schedule, opts);
558
599
  }
@@ -785,6 +826,9 @@ function stepCycle60(segment, unit, opts) {
785
826
  unit
786
827
  }, opts);
787
828
  }
829
+ function withoutHourAnchor(lead) {
830
+ return lead.replace(" " + units.minute.anchor + " ", " ");
831
+ }
788
832
  function stepHours(segment, opts) {
789
833
  if (segment.startToken.indexOf("-") !== -1) {
790
834
  return kloList(segment.fires, opts);
package/dist/lang/fi.js CHANGED
@@ -198,6 +198,20 @@ var nthWeekdayNames = [
198
198
  "nelj\xE4nten\xE4",
199
199
  "viidenten\xE4"
200
200
  ];
201
+ var minuteStepOrdinals = {
202
+ 3: "kolmantena",
203
+ 4: "nelj\xE4nten\xE4",
204
+ 5: "viidenten\xE4",
205
+ 6: "kuudentena",
206
+ 7: "seitsem\xE4nten\xE4",
207
+ 8: "kahdeksantena",
208
+ 9: "yhdeks\xE4nten\xE4",
209
+ 10: "kymmenenten\xE4",
210
+ 12: "kahdentenatoista",
211
+ 15: "viidenten\xE4toista",
212
+ 20: "kahdentenakymmenenten\xE4",
213
+ 30: "kolmantenakymmenenten\xE4"
214
+ };
201
215
  var weekdays = [
202
216
  {
203
217
  ela: "sunnuntaista",
@@ -365,16 +379,42 @@ function composeHourCadence(schedule, plan, opts) {
365
379
  const minute = +schedule.pattern.minute;
366
380
  return hourCadence(schedule, minute, opts) ?? hourRangeCadence(schedule, minute, opts);
367
381
  }
382
+ function minuteStride(schedule) {
383
+ if (schedule.shapes.minute === "step") {
384
+ const segment = stepSegment(schedule, "minute");
385
+ const start = segment.startToken === "*" ? 0 : +segment.startToken;
386
+ return { interval: segment.interval, last: segment.fires[segment.fires.length - 1], start };
387
+ }
388
+ const values = singleValues(segmentsOf(schedule, "minute"));
389
+ return values && arithmeticStep(values);
390
+ }
391
+ function minuteStepConfinement(schedule, stride, opts) {
392
+ const ordinalForm = minuteStepOrdinals[stride.interval];
393
+ const minute = units.minute;
394
+ const head = ordinalForm ? " joka " + ordinalForm + " minuuttina" : " " + genitive(stride.interval, opts) + " " + minute.gen + " v\xE4lein";
395
+ const tail = renderStride({ ...stride, cycle: 60 }, {
396
+ bare: () => "",
397
+ offset: () => " " + minute.anchor + " " + minute.ela + " " + stride.start + " alkaen",
398
+ bounded: () => " " + minute.ela + " " + stride.start + " " + minute.ill + " " + stride.last
399
+ });
400
+ return secondsLeadClause(schedule, opts) + head + tail + trailingQualifier(schedule, opts);
401
+ }
402
+ function isSteppedMinuteSeconds(schedule, plan) {
403
+ return (plan.rest.kind === "minuteFrequency" || plan.rest.kind === "multipleMinutes") && (schedule.pattern.second === "*" || schedule.shapes.second === "step") && schedule.shapes.hour === "wildcard" && schedule.pattern.minute !== "*/2" && minuteStride(schedule) !== null;
404
+ }
368
405
  function renderComposeSeconds(schedule, plan, opts) {
369
406
  const cadence = composeHourCadence(schedule, plan, opts);
370
407
  if (cadence !== null) {
371
408
  return cadence;
372
409
  }
410
+ if (isSteppedMinuteSeconds(schedule, plan)) {
411
+ return minuteStepConfinement(schedule, minuteStride(schedule), opts);
412
+ }
373
413
  if (plan.rest.kind === "minuteFrequency" && schedule.pattern.second !== "*") {
374
414
  return composeSecondsOverMinuteStep(schedule, plan.rest, opts);
375
415
  }
376
- if (plan.rest.kind === "clockTimes" && plan.rest.times.every((time) => +time.minute === 0)) {
377
- return composeMinuteZero(schedule, plan.rest, opts);
416
+ if (plan.rest.kind === "clockTimes" && schedule.shapes.minute === "single") {
417
+ return composeSingleMinute(schedule, plan.rest, opts);
378
418
  }
379
419
  if (isEveryOtherMinuteSeconds(schedule, plan)) {
380
420
  return secondsLeadClause(schedule, opts) + " joka toisena minuuttina";
@@ -390,7 +430,7 @@ function isEveryOtherMinuteSeconds(schedule, plan) {
390
430
  const seg = stepSegment(schedule, "minute");
391
431
  return seg.startToken === "*" && seg.interval === 2;
392
432
  }
393
- function composeMinuteZero(schedule, rest, opts) {
433
+ function composeSingleMinute(schedule, rest, opts) {
394
434
  const clocks = rest.times.map(function clock(time) {
395
435
  return clockDigits(
396
436
  { hour: time.hour, minute: time.minute },
@@ -514,7 +554,7 @@ function renderMinuteFrequency(schedule, plan, opts) {
514
554
  if (plan.hours.kind === "during") {
515
555
  const cadence = unevenHourCadence(schedule, opts);
516
556
  if (cadence !== null) {
517
- return stepCycle60(seg, units.minute, opts) + ", " + cadence + trailingQualifier(schedule, opts);
557
+ return withoutHourAnchor(stepCycle60(seg, units.minute, opts)) + ", " + cadence + trailingQualifier(schedule, opts);
518
558
  }
519
559
  if (minuteStepIsAnchored(seg)) {
520
560
  const bareHours = kloFromTimes(schedule, plan.hours.times, opts);
@@ -522,11 +562,12 @@ function renderMinuteFrequency(schedule, plan, opts) {
522
562
  }
523
563
  return stepCycle60(seg, units.minute, opts) + " " + hourWindowsFromTimes(schedule, plan.hours.times, opts) + trailingQualifier(schedule, opts);
524
564
  }
525
- let phrase = stepCycle60(seg, units.minute, opts);
565
+ const phraseBase = stepCycle60(seg, units.minute, opts);
566
+ let phrase = phraseBase;
526
567
  if (plan.hours.kind === "window") {
527
568
  phrase += " " + hourWindow(plan.hours, opts);
528
569
  } else if (plan.hours.kind === "step") {
529
- phrase += " " + everyNthHour(stepSegment(schedule, "hour"), opts);
570
+ phrase = withoutHourAnchor(phraseBase) + " " + everyNthHour(stepSegment(schedule, "hour"), opts);
530
571
  }
531
572
  return phrase + trailingQualifier(schedule, opts);
532
573
  }
@@ -759,6 +800,9 @@ function stepCycle60(segment, unit, opts) {
759
800
  unit
760
801
  }, opts);
761
802
  }
803
+ function withoutHourAnchor(lead) {
804
+ return lead.replace(" " + units.minute.anchor + " ", " ");
805
+ }
762
806
  function stepHours(segment, opts) {
763
807
  if (segment.startToken.indexOf("-") !== -1) {
764
808
  return kloList(segment.fires, opts);
package/dist/lang/fr.cjs CHANGED
@@ -210,6 +210,20 @@ var weekdayNames = [
210
210
  "samedi"
211
211
  ];
212
212
  var nthWeekdayMasculine = [null, "premier", "deuxi\xE8me", "troisi\xE8me", "quatri\xE8me", "cinqui\xE8me"];
213
+ var stepOrdinals = {
214
+ 3: "troisi\xE8me",
215
+ 4: "quatri\xE8me",
216
+ 5: "cinqui\xE8me",
217
+ 6: "sixi\xE8me",
218
+ 7: "septi\xE8me",
219
+ 8: "huiti\xE8me",
220
+ 9: "neuvi\xE8me",
221
+ 10: "dixi\xE8me",
222
+ 12: "douzi\xE8me",
223
+ 15: "quinzi\xE8me",
224
+ 20: "vingti\xE8me",
225
+ 30: "trenti\xE8me"
226
+ };
213
227
  function normalizeOptions(options) {
214
228
  options = options || {};
215
229
  const style = resolveDialect(options.dialect);
@@ -274,6 +288,28 @@ function composeHourCadence(schedule, plan, opts) {
274
288
  function isPinnedMinuteSeconds(schedule, plan) {
275
289
  return plan.rest.kind === "clockTimes" && (schedule.shapes.second === "wildcard" || schedule.shapes.second === "step");
276
290
  }
291
+ function minuteStride(schedule) {
292
+ if (schedule.shapes.minute === "step") {
293
+ const segment = stepSegment(schedule, "minute");
294
+ const start = segment.startToken === "*" ? 0 : +segment.startToken;
295
+ return { interval: segment.interval, last: segment.fires[segment.fires.length - 1], start };
296
+ }
297
+ const values = singleValues(segmentsOf(schedule, "minute"));
298
+ return values && arithmeticStep(values);
299
+ }
300
+ function minuteStepConfinement(schedule, stride, opts) {
301
+ const ordinal = stepOrdinals[stride.interval];
302
+ const head = ordinal ? "\xE0 la " + ordinal + " minute" : "\xE0 la minute toutes les " + numero(stride.interval, opts);
303
+ const tail = renderStride({ ...stride, cycle: 60 }, {
304
+ bare: () => "",
305
+ offset: () => " \xE0 partir de la minute " + stride.start,
306
+ bounded: () => " de la minute " + stride.start + " \xE0 " + stride.last
307
+ });
308
+ return secondsLeadClause(schedule, opts) + " " + head + tail + " de chaque heure" + trailingQualifier(schedule, opts);
309
+ }
310
+ function isSteppedMinuteSeconds(schedule, plan) {
311
+ 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;
312
+ }
277
313
  function renderComposeSeconds(schedule, plan, opts) {
278
314
  const hourCad = composeHourCadence(schedule, plan, opts);
279
315
  if (hourCad !== null) {
@@ -292,6 +328,9 @@ function renderComposeSeconds(schedule, plan, opts) {
292
328
  const cadence = "toutes les " + numero(stepSegment(schedule, "second").interval, opts) + " secondes de la minute " + schedule.pattern.minute;
293
329
  return dayFrame + ", " + window + ", " + cadence;
294
330
  }
331
+ if (isSteppedMinuteSeconds(schedule, plan)) {
332
+ return minuteStepConfinement(schedule, minuteStride(schedule), opts);
333
+ }
295
334
  if (isEveryOtherMinuteSeconds(schedule, plan)) {
296
335
  return secondsLeadClause(schedule, opts) + " de " + render(schedule, plan.rest, opts).replace(/^toutes les /u, "chaque ");
297
336
  }
@@ -365,6 +404,9 @@ function minutesList(schedule, opts) {
365
404
  opts
366
405
  ) ?? "aux minutes " + joinList(segmentWords(segmentsOf(schedule, "minute"))) + " de chaque heure";
367
406
  }
407
+ function withoutHourAnchor(lead) {
408
+ return lead.replace(/ de chaque heure$/, "");
409
+ }
368
410
  function minuteRangeLead(minuteField) {
369
411
  const bounds = minuteField.split("-");
370
412
  return "chaque minute de " + bounds[0] + " \xE0 " + bounds[1];
@@ -402,7 +444,7 @@ function renderMinuteFrequency(schedule, plan, opts) {
402
444
  } else if (plan.hours.kind === "window") {
403
445
  phrase += " " + hourWindow(plan.hours, opts);
404
446
  } else if (plan.hours.kind === "step") {
405
- phrase += ", " + stepHourSpan(stepSegment(schedule, "hour"), opts);
447
+ phrase = withoutHourAnchor(phrase) + ", " + stepHourSpan(stepSegment(schedule, "hour"), opts);
406
448
  }
407
449
  return phrase + trailingQualifier(schedule, opts);
408
450
  }
@@ -439,7 +481,7 @@ function renderMinuteSpanAcrossHourStep(schedule, plan, opts) {
439
481
  if (plan.form === "wildcard") {
440
482
  return "chaque minute, " + stepHourSpan(segment, opts) + trailingQualifier(schedule, opts);
441
483
  }
442
- const lead = plan.form === "list" ? minutesList(schedule, opts) : minuteRangeLead(schedule.pattern.minute);
484
+ const lead = withoutHourAnchor(plan.form === "list" ? minutesList(schedule, opts) : minuteRangeLead(schedule.pattern.minute));
443
485
  return lead + ", " + (cadence ?? stepHours(segment, opts)) + trailingQualifier(schedule, opts);
444
486
  }
445
487
  function renderEveryHour(schedule, plan, opts) {
@@ -612,7 +654,7 @@ function renderCompactClockTimes(schedule, plan, opts) {
612
654
  );
613
655
  }
614
656
  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);
657
+ const phrase = cadence ? withoutHourAnchor(minutesList(schedule, opts)) + ", " + cadence + trailingQualifier(schedule, opts) : minutesList(schedule, opts) + ", " + hourContextTimes(schedule, opts) + trailingQualifier(schedule, opts);
616
658
  return schedule.analyses.clockSecond ? secondsLeadClause(schedule, opts) + ", " + phrase : phrase;
617
659
  }
618
660
  var renderers = {
package/dist/lang/fr.js CHANGED
@@ -184,6 +184,20 @@ var weekdayNames = [
184
184
  "samedi"
185
185
  ];
186
186
  var nthWeekdayMasculine = [null, "premier", "deuxi\xE8me", "troisi\xE8me", "quatri\xE8me", "cinqui\xE8me"];
187
+ var stepOrdinals = {
188
+ 3: "troisi\xE8me",
189
+ 4: "quatri\xE8me",
190
+ 5: "cinqui\xE8me",
191
+ 6: "sixi\xE8me",
192
+ 7: "septi\xE8me",
193
+ 8: "huiti\xE8me",
194
+ 9: "neuvi\xE8me",
195
+ 10: "dixi\xE8me",
196
+ 12: "douzi\xE8me",
197
+ 15: "quinzi\xE8me",
198
+ 20: "vingti\xE8me",
199
+ 30: "trenti\xE8me"
200
+ };
187
201
  function normalizeOptions(options) {
188
202
  options = options || {};
189
203
  const style = resolveDialect(options.dialect);
@@ -248,6 +262,28 @@ function composeHourCadence(schedule, plan, opts) {
248
262
  function isPinnedMinuteSeconds(schedule, plan) {
249
263
  return plan.rest.kind === "clockTimes" && (schedule.shapes.second === "wildcard" || schedule.shapes.second === "step");
250
264
  }
265
+ function minuteStride(schedule) {
266
+ if (schedule.shapes.minute === "step") {
267
+ const segment = stepSegment(schedule, "minute");
268
+ const start = segment.startToken === "*" ? 0 : +segment.startToken;
269
+ return { interval: segment.interval, last: segment.fires[segment.fires.length - 1], start };
270
+ }
271
+ const values = singleValues(segmentsOf(schedule, "minute"));
272
+ return values && arithmeticStep(values);
273
+ }
274
+ function minuteStepConfinement(schedule, stride, opts) {
275
+ const ordinal = stepOrdinals[stride.interval];
276
+ const head = ordinal ? "\xE0 la " + ordinal + " minute" : "\xE0 la minute toutes les " + numero(stride.interval, opts);
277
+ const tail = renderStride({ ...stride, cycle: 60 }, {
278
+ bare: () => "",
279
+ offset: () => " \xE0 partir de la minute " + stride.start,
280
+ bounded: () => " de la minute " + stride.start + " \xE0 " + stride.last
281
+ });
282
+ return secondsLeadClause(schedule, opts) + " " + head + tail + " de chaque heure" + trailingQualifier(schedule, opts);
283
+ }
284
+ function isSteppedMinuteSeconds(schedule, plan) {
285
+ 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;
286
+ }
251
287
  function renderComposeSeconds(schedule, plan, opts) {
252
288
  const hourCad = composeHourCadence(schedule, plan, opts);
253
289
  if (hourCad !== null) {
@@ -266,6 +302,9 @@ function renderComposeSeconds(schedule, plan, opts) {
266
302
  const cadence = "toutes les " + numero(stepSegment(schedule, "second").interval, opts) + " secondes de la minute " + schedule.pattern.minute;
267
303
  return dayFrame + ", " + window + ", " + cadence;
268
304
  }
305
+ if (isSteppedMinuteSeconds(schedule, plan)) {
306
+ return minuteStepConfinement(schedule, minuteStride(schedule), opts);
307
+ }
269
308
  if (isEveryOtherMinuteSeconds(schedule, plan)) {
270
309
  return secondsLeadClause(schedule, opts) + " de " + render(schedule, plan.rest, opts).replace(/^toutes les /u, "chaque ");
271
310
  }
@@ -339,6 +378,9 @@ function minutesList(schedule, opts) {
339
378
  opts
340
379
  ) ?? "aux minutes " + joinList(segmentWords(segmentsOf(schedule, "minute"))) + " de chaque heure";
341
380
  }
381
+ function withoutHourAnchor(lead) {
382
+ return lead.replace(/ de chaque heure$/, "");
383
+ }
342
384
  function minuteRangeLead(minuteField) {
343
385
  const bounds = minuteField.split("-");
344
386
  return "chaque minute de " + bounds[0] + " \xE0 " + bounds[1];
@@ -376,7 +418,7 @@ function renderMinuteFrequency(schedule, plan, opts) {
376
418
  } else if (plan.hours.kind === "window") {
377
419
  phrase += " " + hourWindow(plan.hours, opts);
378
420
  } else if (plan.hours.kind === "step") {
379
- phrase += ", " + stepHourSpan(stepSegment(schedule, "hour"), opts);
421
+ phrase = withoutHourAnchor(phrase) + ", " + stepHourSpan(stepSegment(schedule, "hour"), opts);
380
422
  }
381
423
  return phrase + trailingQualifier(schedule, opts);
382
424
  }
@@ -413,7 +455,7 @@ function renderMinuteSpanAcrossHourStep(schedule, plan, opts) {
413
455
  if (plan.form === "wildcard") {
414
456
  return "chaque minute, " + stepHourSpan(segment, opts) + trailingQualifier(schedule, opts);
415
457
  }
416
- const lead = plan.form === "list" ? minutesList(schedule, opts) : minuteRangeLead(schedule.pattern.minute);
458
+ const lead = withoutHourAnchor(plan.form === "list" ? minutesList(schedule, opts) : minuteRangeLead(schedule.pattern.minute));
417
459
  return lead + ", " + (cadence ?? stepHours(segment, opts)) + trailingQualifier(schedule, opts);
418
460
  }
419
461
  function renderEveryHour(schedule, plan, opts) {
@@ -586,7 +628,7 @@ function renderCompactClockTimes(schedule, plan, opts) {
586
628
  );
587
629
  }
588
630
  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);
631
+ const phrase = cadence ? withoutHourAnchor(minutesList(schedule, opts)) + ", " + cadence + trailingQualifier(schedule, opts) : minutesList(schedule, opts) + ", " + hourContextTimes(schedule, opts) + trailingQualifier(schedule, opts);
590
632
  return schedule.analyses.clockSecond ? secondsLeadClause(schedule, opts) + ", " + phrase : phrase;
591
633
  }
592
634
  var renderers = {
package/dist/lang/pt.cjs CHANGED
@@ -232,6 +232,20 @@ function weekdayFeminine(number) {
232
232
  }
233
233
  var nthWeekdayMasculine = [null, "primeiro", "segundo", "terceiro", "quarto", "quinto"];
234
234
  var nthWeekdayFeminine = [null, "primeira", "segunda", "terceira", "quarta", "quinta"];
235
+ var stepOrdinals = {
236
+ 3: "terceiro",
237
+ 4: "quarto",
238
+ 5: "quinto",
239
+ 6: "sexto",
240
+ 7: "s\xE9timo",
241
+ 8: "oitavo",
242
+ 9: "nono",
243
+ 10: "d\xE9cimo",
244
+ 12: "d\xE9cimo segundo",
245
+ 15: "d\xE9cimo quinto",
246
+ 20: "vig\xE9simo",
247
+ 30: "trig\xE9simo"
248
+ };
235
249
  function noonMidnightArticle(phrase) {
236
250
  if (phrase === "meio-dia") {
237
251
  return "o";
@@ -361,6 +375,28 @@ function composeHourCadence(schedule, plan, opts) {
361
375
  function isPinnedMinuteSeconds(schedule, plan) {
362
376
  return plan.rest.kind === "clockTimes" && (schedule.shapes.second === "wildcard" || schedule.shapes.second === "step");
363
377
  }
378
+ function minuteStride(schedule) {
379
+ if (schedule.shapes.minute === "step") {
380
+ const segment = stepSegment(schedule, "minute");
381
+ const start = segment.startToken === "*" ? 0 : +segment.startToken;
382
+ return { interval: segment.interval, last: segment.fires[segment.fires.length - 1], start };
383
+ }
384
+ const values = singleValues(segmentsOf(schedule, "minute"));
385
+ return values && arithmeticStep(values);
386
+ }
387
+ function minuteStepConfinement(schedule, stride, opts) {
388
+ const ordinal = stepOrdinals[stride.interval];
389
+ const head = ordinal ? "no " + ordinal + " minuto" : "a cada " + numero(stride.interval, opts) + " minutos";
390
+ const tail = renderStride({ ...stride, cycle: 60 }, {
391
+ bare: () => "",
392
+ offset: () => " a partir do minuto " + stride.start,
393
+ bounded: () => " do minuto " + stride.start + " ao " + stride.last
394
+ });
395
+ return secondsLeadClause(schedule, opts) + " " + head + tail + " de cada hora" + trailingQualifier(schedule, opts);
396
+ }
397
+ function isSteppedMinuteSeconds(schedule, plan) {
398
+ 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;
399
+ }
364
400
  function renderComposeSeconds(schedule, plan, opts) {
365
401
  const hourCad = composeHourCadence(schedule, plan, opts);
366
402
  if (hourCad !== null) {
@@ -379,6 +415,9 @@ function renderComposeSeconds(schedule, plan, opts) {
379
415
  const cadence = "a cada " + numero(stepSegment(schedule, "second").interval, opts) + " segundos do minuto " + schedule.pattern.minute;
380
416
  return dayFrame + ", " + window + ", " + cadence;
381
417
  }
418
+ if (isSteppedMinuteSeconds(schedule, plan)) {
419
+ return minuteStepConfinement(schedule, minuteStride(schedule), opts);
420
+ }
382
421
  if (isEveryOtherMinuteSeconds(schedule, plan)) {
383
422
  const rest = render(schedule, plan.rest, opts).replace(/^a /u, "");
384
423
  return secondsLeadClause(schedule, opts) + " de " + rest;
@@ -453,6 +492,9 @@ function minutesList(schedule, opts) {
453
492
  opts
454
493
  ) ?? "nos minutos " + joinList(segmentWords(segmentsOf(schedule, "minute"))) + " de cada hora";
455
494
  }
495
+ function withoutHourAnchor(lead) {
496
+ return lead.replace(/ de cada hora$/, "");
497
+ }
456
498
  function minuteRangeLead(minuteField) {
457
499
  const bounds = minuteField.split("-");
458
500
  return "a cada minuto do " + bounds[0] + " ao " + bounds[1];
@@ -523,7 +565,7 @@ function renderMinuteFrequency(schedule, plan, opts) {
523
565
  } else if (plan.hours.kind === "window") {
524
566
  phrase += " " + hourWindow(plan.hours, opts);
525
567
  } else if (plan.hours.kind === "step") {
526
- phrase += ", " + stepHourSpan(stepSegment(schedule, "hour"), opts);
568
+ phrase = withoutHourAnchor(phrase) + ", " + stepHourSpan(stepSegment(schedule, "hour"), opts);
527
569
  }
528
570
  return phrase + trailingQualifier(schedule, opts);
529
571
  }
@@ -560,7 +602,7 @@ function renderMinuteSpanAcrossHourStep(schedule, plan, opts) {
560
602
  if (plan.form === "wildcard") {
561
603
  return "a cada minuto, " + stepHourSpan(segment, opts) + trailingQualifier(schedule, opts);
562
604
  }
563
- const lead = plan.form === "list" ? minutesList(schedule, opts) : minuteRangeLead(schedule.pattern.minute);
605
+ const lead = withoutHourAnchor(plan.form === "list" ? minutesList(schedule, opts) : minuteRangeLead(schedule.pattern.minute));
564
606
  return lead + ", " + (cadence ?? stepHours(segment, opts)) + trailingQualifier(schedule, opts);
565
607
  }
566
608
  function renderEveryHour(schedule, plan, opts) {
@@ -865,7 +907,7 @@ function renderCompactClockTimes(schedule, plan, opts) {
865
907
  );
866
908
  }
867
909
  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);
910
+ const phrase = cadence ? withoutHourAnchor(minutesList(schedule, opts)) + ", " + cadence + trailingQualifier(schedule, opts) : minutesList(schedule, opts) + ", " + hourContextTimes(schedule, opts) + trailingQualifier(schedule, opts);
869
911
  return schedule.analyses.clockSecond ? secondsLeadClause(schedule, opts) + ", " + phrase : phrase;
870
912
  }
871
913
  var renderers = {
package/dist/lang/pt.js CHANGED
@@ -206,6 +206,20 @@ function weekdayFeminine(number) {
206
206
  }
207
207
  var nthWeekdayMasculine = [null, "primeiro", "segundo", "terceiro", "quarto", "quinto"];
208
208
  var nthWeekdayFeminine = [null, "primeira", "segunda", "terceira", "quarta", "quinta"];
209
+ var stepOrdinals = {
210
+ 3: "terceiro",
211
+ 4: "quarto",
212
+ 5: "quinto",
213
+ 6: "sexto",
214
+ 7: "s\xE9timo",
215
+ 8: "oitavo",
216
+ 9: "nono",
217
+ 10: "d\xE9cimo",
218
+ 12: "d\xE9cimo segundo",
219
+ 15: "d\xE9cimo quinto",
220
+ 20: "vig\xE9simo",
221
+ 30: "trig\xE9simo"
222
+ };
209
223
  function noonMidnightArticle(phrase) {
210
224
  if (phrase === "meio-dia") {
211
225
  return "o";
@@ -335,6 +349,28 @@ function composeHourCadence(schedule, plan, opts) {
335
349
  function isPinnedMinuteSeconds(schedule, plan) {
336
350
  return plan.rest.kind === "clockTimes" && (schedule.shapes.second === "wildcard" || schedule.shapes.second === "step");
337
351
  }
352
+ function minuteStride(schedule) {
353
+ if (schedule.shapes.minute === "step") {
354
+ const segment = stepSegment(schedule, "minute");
355
+ const start = segment.startToken === "*" ? 0 : +segment.startToken;
356
+ return { interval: segment.interval, last: segment.fires[segment.fires.length - 1], start };
357
+ }
358
+ const values = singleValues(segmentsOf(schedule, "minute"));
359
+ return values && arithmeticStep(values);
360
+ }
361
+ function minuteStepConfinement(schedule, stride, opts) {
362
+ const ordinal = stepOrdinals[stride.interval];
363
+ const head = ordinal ? "no " + ordinal + " minuto" : "a cada " + numero(stride.interval, opts) + " minutos";
364
+ const tail = renderStride({ ...stride, cycle: 60 }, {
365
+ bare: () => "",
366
+ offset: () => " a partir do minuto " + stride.start,
367
+ bounded: () => " do minuto " + stride.start + " ao " + stride.last
368
+ });
369
+ return secondsLeadClause(schedule, opts) + " " + head + tail + " de cada hora" + trailingQualifier(schedule, opts);
370
+ }
371
+ function isSteppedMinuteSeconds(schedule, plan) {
372
+ 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;
373
+ }
338
374
  function renderComposeSeconds(schedule, plan, opts) {
339
375
  const hourCad = composeHourCadence(schedule, plan, opts);
340
376
  if (hourCad !== null) {
@@ -353,6 +389,9 @@ function renderComposeSeconds(schedule, plan, opts) {
353
389
  const cadence = "a cada " + numero(stepSegment(schedule, "second").interval, opts) + " segundos do minuto " + schedule.pattern.minute;
354
390
  return dayFrame + ", " + window + ", " + cadence;
355
391
  }
392
+ if (isSteppedMinuteSeconds(schedule, plan)) {
393
+ return minuteStepConfinement(schedule, minuteStride(schedule), opts);
394
+ }
356
395
  if (isEveryOtherMinuteSeconds(schedule, plan)) {
357
396
  const rest = render(schedule, plan.rest, opts).replace(/^a /u, "");
358
397
  return secondsLeadClause(schedule, opts) + " de " + rest;
@@ -427,6 +466,9 @@ function minutesList(schedule, opts) {
427
466
  opts
428
467
  ) ?? "nos minutos " + joinList(segmentWords(segmentsOf(schedule, "minute"))) + " de cada hora";
429
468
  }
469
+ function withoutHourAnchor(lead) {
470
+ return lead.replace(/ de cada hora$/, "");
471
+ }
430
472
  function minuteRangeLead(minuteField) {
431
473
  const bounds = minuteField.split("-");
432
474
  return "a cada minuto do " + bounds[0] + " ao " + bounds[1];
@@ -497,7 +539,7 @@ function renderMinuteFrequency(schedule, plan, opts) {
497
539
  } else if (plan.hours.kind === "window") {
498
540
  phrase += " " + hourWindow(plan.hours, opts);
499
541
  } else if (plan.hours.kind === "step") {
500
- phrase += ", " + stepHourSpan(stepSegment(schedule, "hour"), opts);
542
+ phrase = withoutHourAnchor(phrase) + ", " + stepHourSpan(stepSegment(schedule, "hour"), opts);
501
543
  }
502
544
  return phrase + trailingQualifier(schedule, opts);
503
545
  }
@@ -534,7 +576,7 @@ function renderMinuteSpanAcrossHourStep(schedule, plan, opts) {
534
576
  if (plan.form === "wildcard") {
535
577
  return "a cada minuto, " + stepHourSpan(segment, opts) + trailingQualifier(schedule, opts);
536
578
  }
537
- const lead = plan.form === "list" ? minutesList(schedule, opts) : minuteRangeLead(schedule.pattern.minute);
579
+ const lead = withoutHourAnchor(plan.form === "list" ? minutesList(schedule, opts) : minuteRangeLead(schedule.pattern.minute));
538
580
  return lead + ", " + (cadence ?? stepHours(segment, opts)) + trailingQualifier(schedule, opts);
539
581
  }
540
582
  function renderEveryHour(schedule, plan, opts) {
@@ -839,7 +881,7 @@ function renderCompactClockTimes(schedule, plan, opts) {
839
881
  );
840
882
  }
841
883
  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);
884
+ const phrase = cadence ? withoutHourAnchor(minutesList(schedule, opts)) + ", " + cadence + trailingQualifier(schedule, opts) : minutesList(schedule, opts) + ", " + hourContextTimes(schedule, opts) + trailingQualifier(schedule, opts);
843
885
  return schedule.analyses.clockSecond ? secondsLeadClause(schedule, opts) + ", " + phrase : phrase;
844
886
  }
845
887
  var renderers = {