cronli5 0.1.4 → 0.1.5

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
@@ -50,12 +50,28 @@ var weekdayNumbers = {
50
50
  FRI: 5,
51
51
  SAT: 6
52
52
  };
53
+ var maxClockTimes = 6;
53
54
 
54
55
  // src/core/util.ts
55
56
  function isNonNegativeInteger(value) {
56
57
  const digits = /^\d+$/;
57
58
  return digits.test(value);
58
59
  }
60
+ function arithmeticStep(values) {
61
+ if (values.length < 5) {
62
+ return null;
63
+ }
64
+ const interval = values[1] - values[0];
65
+ if (interval < 2) {
66
+ return null;
67
+ }
68
+ for (let i = 2; i < values.length; i += 1) {
69
+ if (values[i] - values[i - 1] !== interval) {
70
+ return null;
71
+ }
72
+ }
73
+ return { start: values[0], interval, last: values[values.length - 1] };
74
+ }
59
75
  function toFieldNumber(token, numberMap) {
60
76
  return isNonNegativeInteger(token) ? +token : numberMap[token.toUpperCase()];
61
77
  }
@@ -191,12 +207,14 @@ var units = {
191
207
  mark: "joka tunti",
192
208
  anchor: "jokaisen tunnin",
193
209
  ela: "minuutista",
210
+ ill: "minuuttiin",
194
211
  gen: "minuutin"
195
212
  },
196
213
  second: {
197
214
  mark: "joka minuutti",
198
215
  anchor: "jokaisen minuutin",
199
216
  ela: "sekunnista",
217
+ ill: "sekuntiin",
200
218
  gen: "sekunnin"
201
219
  }
202
220
  };
@@ -252,29 +270,50 @@ function renderSecondsWithinMinute(ir, plan, opts) {
252
270
  }
253
271
  return secondsLeadClause(ir, opts) + ", " + atMarks(minuteField, units.minute, true) + trailingQualifier(ir, opts);
254
272
  }
273
+ function composeSecondsOverMinuteStep(ir, freq, opts) {
274
+ const seg = stepSegment(ir.analyses.segments.minute);
275
+ const stepPhrase = stepCycle60(seg, units.minute, opts);
276
+ if (freq.hours.kind === "during" && minuteStepIsAnchored(seg)) {
277
+ const bareHours = kloFromTimes(ir, freq.hours.times, opts);
278
+ return hoursFirstMinutes(bareHours, ir, opts) + ", " + secondsLeadClause(ir, opts) + trailingQualifier(ir, opts);
279
+ }
280
+ let hourClause = "";
281
+ if (freq.hours.kind === "during") {
282
+ hourClause = " " + hourWindowsFromTimes(ir, freq.hours.times, opts);
283
+ } else if (freq.hours.kind === "window") {
284
+ hourClause = " " + hourWindow(freq.hours, opts);
285
+ } else if (freq.hours.kind === "step") {
286
+ hourClause = " " + everyNthHour(stepSegment(ir.analyses.segments.hour), opts);
287
+ }
288
+ return stepPhrase + ", " + secondsLeadClause(ir, opts) + hourClause + trailingQualifier(ir, opts);
289
+ }
290
+ function composeHourCadence(ir, plan, opts) {
291
+ const clockRest = plan.rest.kind === "clockTimes" || plan.rest.kind === "compactClockTimes";
292
+ return clockRest && ir.shapes.minute === "single" ? hourCadence(ir, +ir.pattern.minute, opts) : null;
293
+ }
255
294
  function renderComposeSeconds(ir, plan, opts) {
295
+ const cadence = composeHourCadence(ir, plan, opts);
296
+ if (cadence !== null) {
297
+ return cadence;
298
+ }
256
299
  if (plan.rest.kind === "minuteFrequency" && ir.pattern.second !== "*") {
257
- const freq = plan.rest;
258
- const seg = stepSegment(ir.analyses.segments.minute);
259
- const stepPhrase = stepCycle60(seg, units.minute, opts);
260
- let hourClause = "";
261
- if (freq.hours.kind === "during" && minuteStepIsAnchored(seg)) {
262
- const bareHours = kloFromTimes(ir, freq.hours.times, opts);
263
- return hoursFirstMinutes(bareHours, ir) + ", " + secondsLeadClause(ir, opts) + trailingQualifier(ir, opts);
264
- } else if (freq.hours.kind === "during" && !minuteStepIsAnchored(seg)) {
265
- hourClause = " " + hourWindowsFromTimes(ir, freq.hours.times, opts);
266
- } else if (freq.hours.kind === "window") {
267
- hourClause = " " + hourWindow(freq.hours, opts);
268
- } else if (freq.hours.kind === "step") {
269
- hourClause = " " + everyNthHour(stepSegment(ir.analyses.segments.hour), opts);
270
- }
271
- return stepPhrase + ", " + secondsLeadClause(ir, opts) + hourClause + trailingQualifier(ir, opts);
300
+ return composeSecondsOverMinuteStep(ir, plan.rest, opts);
272
301
  }
273
302
  if (plan.rest.kind === "clockTimes" && plan.rest.times.every((time) => +time.minute === 0)) {
274
303
  return composeMinuteZero(ir, plan.rest, opts);
275
304
  }
305
+ if (isEveryOtherMinuteSeconds(ir, plan)) {
306
+ return secondsLeadClause(ir, opts) + " joka toisena minuuttina";
307
+ }
276
308
  return secondsLeadClause(ir, opts) + ", " + render(ir, plan.rest, opts);
277
309
  }
310
+ function isEveryOtherMinuteSeconds(ir, plan) {
311
+ if (plan.rest.kind !== "minuteFrequency" || ir.pattern.second !== "*" || ir.shapes.hour !== "wildcard") {
312
+ return false;
313
+ }
314
+ const seg = stepSegment(ir.analyses.segments.minute);
315
+ return seg.startToken === "*" && seg.interval === 2;
316
+ }
278
317
  function composeMinuteZero(ir, rest, opts) {
279
318
  const clocks = rest.times.map(function clock(time) {
280
319
  return clockDigits(
@@ -303,7 +342,7 @@ function secondsLeadClause(ir, opts) {
303
342
  if (shape === "single") {
304
343
  return atMarks(secondField, units.second, marked);
305
344
  }
306
- return atMarks(
345
+ return strideFromSegments(ir.analyses.segments.second, units.second, opts) ?? atMarks(
307
346
  joinList(segmentWords(ir.analyses.segments.second)),
308
347
  units.second,
309
348
  marked
@@ -316,20 +355,20 @@ function renderSingleMinute(ir, plan, opts) {
316
355
  return atMarks(ir.pattern.minute, units.minute, true) + trailingQualifier(ir, opts);
317
356
  }
318
357
  function renderRangeOfMinutes(ir, plan, opts) {
319
- return minutesList(ir) + trailingQualifier(ir, opts);
358
+ return minutesList(ir, opts) + trailingQualifier(ir, opts);
320
359
  }
321
360
  function renderMultipleMinutes(ir, plan, opts) {
322
- return minutesList(ir) + trailingQualifier(ir, opts);
361
+ return minutesList(ir, opts) + trailingQualifier(ir, opts);
323
362
  }
324
- function minutesList(ir) {
325
- return atMarks(
363
+ function minutesList(ir, opts) {
364
+ return strideFromSegments(ir.analyses.segments.minute, units.minute, opts) ?? atMarks(
326
365
  joinList(segmentWords(ir.analyses.segments.minute)),
327
366
  units.minute,
328
367
  true
329
368
  );
330
369
  }
331
- function bareMinutes(ir) {
332
- return atMarks(
370
+ function bareMinutes(ir, opts) {
371
+ return strideFromSegments(ir.analyses.segments.minute, units.minute, opts) ?? atMarks(
333
372
  joinList(segmentWords(ir.analyses.segments.minute)),
334
373
  units.minute,
335
374
  false
@@ -360,7 +399,11 @@ function hoursAreRangeIsolated(segments) {
360
399
  }
361
400
  return hasRange && hasSingle;
362
401
  }
363
- function hoursFirstMinutes(hoursStr, ir) {
402
+ function hoursFirstMinutes(hoursStr, ir, opts) {
403
+ const stride = strideFromSegments(ir.analyses.segments.minute, units.minute, opts);
404
+ if (stride) {
405
+ return hoursStr + " aina " + stride;
406
+ }
364
407
  return hoursStr + " aina minuuttien " + joinList(segmentWords(ir.analyses.segments.minute)) + " kohdalla";
365
408
  }
366
409
  function hourSegmentTimesWithSeka(ir, minute, second, opts) {
@@ -383,7 +426,7 @@ function renderMinuteFrequency(ir, plan, opts) {
383
426
  if (plan.hours.kind === "during") {
384
427
  if (minuteStepIsAnchored(seg)) {
385
428
  const bareHours = kloFromTimes(ir, plan.hours.times, opts);
386
- return hoursFirstMinutes(bareHours, ir) + trailingQualifier(ir, opts);
429
+ return hoursFirstMinutes(bareHours, ir, opts) + trailingQualifier(ir, opts);
387
430
  }
388
431
  return stepCycle60(seg, units.minute, opts) + " " + hourWindowsFromTimes(ir, plan.hours.times, opts) + trailingQualifier(ir, opts);
389
432
  }
@@ -410,10 +453,10 @@ function renderMinutesAcrossHours(ir, plan, opts) {
410
453
  return "joka minuutti " + hourWindowsFromTimes(ir, plan.times, opts) + trailingQualifier(ir, opts);
411
454
  }
412
455
  if (hoursAreRangeIsolated(ir.analyses.segments.hour)) {
413
- return bareMinutes(ir) + " " + hourSegmentTimesWithSeka(ir, 0, null, opts) + trailingQualifier(ir, opts);
456
+ return bareMinutes(ir, opts) + " " + hourSegmentTimesWithSeka(ir, 0, null, opts) + trailingQualifier(ir, opts);
414
457
  }
415
458
  const hoursStr = kloFromTimes(ir, plan.times, opts);
416
- return hoursFirstMinutes(hoursStr, ir) + trailingQualifier(ir, opts);
459
+ return hoursFirstMinutes(hoursStr, ir, opts) + trailingQualifier(ir, opts);
417
460
  }
418
461
  function renderMinuteSpanAcrossHourStep(ir, plan, opts) {
419
462
  const segment = stepSegment(ir.analyses.segments.hour);
@@ -422,9 +465,9 @@ function renderMinuteSpanAcrossHourStep(ir, plan, opts) {
422
465
  }
423
466
  if (segment.startToken.indexOf("-") !== -1) {
424
467
  const hoursStr = kloList(segment.fires, opts);
425
- return hoursFirstMinutes(hoursStr, ir) + trailingQualifier(ir, opts);
468
+ return hoursFirstMinutes(hoursStr, ir, opts) + trailingQualifier(ir, opts);
426
469
  }
427
- return bareMinutes(ir) + hourStepTail(segment, opts) + trailingQualifier(ir, opts);
470
+ return bareMinutes(ir, opts) + hourStepTail(segment, opts) + trailingQualifier(ir, opts);
428
471
  }
429
472
  function plainHourStep(segment) {
430
473
  return segment.startToken === "*" && 24 % segment.interval === 0;
@@ -482,7 +525,7 @@ function renderHourRange(ir, plan, opts) {
482
525
  return "joka minuutti " + window + trailingQualifier(ir, opts);
483
526
  }
484
527
  if (plan.minuteForm === "range") {
485
- return hoursFirstMinutes(window, ir) + trailingQualifier(ir, opts);
528
+ return hoursFirstMinutes(window, ir, opts) + trailingQualifier(ir, opts);
486
529
  }
487
530
  if (ir.pattern.minute === "0") {
488
531
  return "joka tunti " + window + trailingQualifier(ir, opts);
@@ -494,7 +537,7 @@ function renderHourRange(ir, plan, opts) {
494
537
  opts
495
538
  ) + trailingQualifier(ir, opts);
496
539
  }
497
- return hoursFirstMinutes(window, ir) + trailingQualifier(ir, opts);
540
+ return hoursFirstMinutes(window, ir, opts) + trailingQualifier(ir, opts);
498
541
  }
499
542
  function renderHourStep(ir, plan, opts) {
500
543
  return stepHours(stepSegment(ir.analyses.segments.hour), opts) + trailingQualifier(ir, opts);
@@ -510,6 +553,12 @@ function hourWindow(window, opts) {
510
553
  );
511
554
  }
512
555
  function renderClockTimes(ir, plan, opts) {
556
+ if (ir.shapes.minute === "single") {
557
+ const cadence = hourCadence(ir, +ir.pattern.minute, opts);
558
+ if (cadence !== null) {
559
+ return cadence;
560
+ }
561
+ }
513
562
  if (plan.times.length === 1) {
514
563
  const time = plan.times[0];
515
564
  return leadingQualifier(ir, opts) + timeWord(time.hour, time.minute, time.second, opts);
@@ -520,6 +569,12 @@ function renderClockTimes(ir, plan, opts) {
520
569
  return leadingQualifier(ir, opts) + "klo " + joinList(digits);
521
570
  }
522
571
  function renderCompactClockTimes(ir, plan, opts) {
572
+ if (plan.fold) {
573
+ const cadence = hourCadence(ir, plan.minute, opts);
574
+ if (cadence !== null) {
575
+ return cadence;
576
+ }
577
+ }
523
578
  const hourSegs = ir.analyses.segments.hour;
524
579
  if (hoursAreRangeIsolated(hourSegs)) {
525
580
  if (plan.fold) {
@@ -530,14 +585,14 @@ function renderCompactClockTimes(ir, plan, opts) {
530
585
  opts
531
586
  );
532
587
  }
533
- const phrase2 = bareMinutes(ir) + " " + hourSegmentTimesWithSeka(ir, 0, null, opts) + trailingQualifier(ir, opts);
588
+ const phrase2 = bareMinutes(ir, opts) + " " + hourSegmentTimesWithSeka(ir, 0, null, opts) + trailingQualifier(ir, opts);
534
589
  return ir.analyses.clockSecond ? secondsLeadClause(ir, opts) + ", " + phrase2 : phrase2;
535
590
  }
536
591
  if (plan.fold) {
537
592
  return leadingQualifier(ir, opts) + hourSegmentTimes(ir, plan.minute, ir.analyses.clockSecond, opts);
538
593
  }
539
594
  const hoursStr = hourSegmentTimes(ir, 0, null, opts);
540
- const phrase = hoursFirstMinutes(hoursStr, ir) + trailingQualifier(ir, opts);
595
+ const phrase = hoursFirstMinutes(hoursStr, ir, opts) + trailingQualifier(ir, opts);
541
596
  return ir.analyses.clockSecond ? secondsLeadClause(ir, opts) + ", " + phrase : phrase;
542
597
  }
543
598
  var renderers = {
@@ -560,20 +615,48 @@ var renderers = {
560
615
  singleMinute: renderSingleMinute,
561
616
  standaloneSeconds: renderStandaloneSeconds
562
617
  };
618
+ function renderStride(stride, opts) {
619
+ const { interval, start, last, cycle, unit } = stride;
620
+ const cadence = genitive(interval, opts) + " " + unit.gen + " v\xE4lein";
621
+ const tiles = cycle % interval === 0;
622
+ if (start === 0 && tiles) {
623
+ return cadence;
624
+ }
625
+ if (start < interval && tiles) {
626
+ return cadence + " " + unit.anchor + " " + unit.ela + " " + start + " alkaen";
627
+ }
628
+ return cadence + " " + unit.ela + " " + start + " " + unit.ill + " " + last;
629
+ }
630
+ function strideFromSegments(segments, unit, opts) {
631
+ const values = singleValues(segments);
632
+ const step = values && arithmeticStep(values);
633
+ return step ? renderStride({ ...step, cycle: 60, unit }, opts) : null;
634
+ }
635
+ function singleValues(segments) {
636
+ const values = [];
637
+ for (const segment of segments) {
638
+ if (segment.kind !== "single") {
639
+ return null;
640
+ }
641
+ values.push(+segment.value);
642
+ }
643
+ return values;
644
+ }
563
645
  function stepCycle60(segment, unit, opts) {
564
646
  if (segment.startToken.indexOf("-") !== -1) {
565
647
  return atMarks(joinList(wordList(segment.fires)), unit, true);
566
648
  }
567
649
  const start = segment.startToken === "*" ? 0 : +segment.startToken;
568
- const interval = segment.interval;
569
- const cadence = genitive(interval, opts) + " " + unit.gen + " v\xE4lein";
570
- if (start !== 0) {
571
- if (segment.fires.length <= 3) {
572
- return atMarks(joinList(wordList(segment.fires)), unit, true);
573
- }
574
- return cadence + " " + unit.anchor + " " + unit.ela + " " + start + " alkaen";
650
+ if (start !== 0 && segment.fires.length <= 3) {
651
+ return atMarks(joinList(wordList(segment.fires)), unit, true);
575
652
  }
576
- return cadence;
653
+ return renderStride({
654
+ interval: segment.interval,
655
+ start,
656
+ last: segment.fires[segment.fires.length - 1],
657
+ cycle: 60,
658
+ unit
659
+ }, opts);
577
660
  }
578
661
  function stepHours(segment, opts) {
579
662
  if (segment.startToken.indexOf("-") !== -1) {
@@ -590,6 +673,71 @@ function stepHours(segment, opts) {
590
673
  }
591
674
  return cadence + " klo " + hourElatives[start] + " alkaen";
592
675
  }
676
+ function hourStrideCadence(stride, opts) {
677
+ const { start, interval, last } = stride;
678
+ const cadence = genitive(interval, opts) + " tunnin v\xE4lein";
679
+ const tiles = 24 % interval === 0;
680
+ if (start === 0 && tiles) {
681
+ return cadence;
682
+ }
683
+ if (start < interval && tiles) {
684
+ return cadence + " klo " + hourElatives[start] + " alkaen";
685
+ }
686
+ return cadence + " " + kloRange({ hour: start, minute: 0 }, { hour: last, minute: 0 }, opts);
687
+ }
688
+ function hourStride(ir) {
689
+ const segments = ir.analyses.segments.hour;
690
+ if (!segments) {
691
+ return null;
692
+ }
693
+ if (segments.length === 1 && segments[0].kind === "step") {
694
+ const segment = segments[0];
695
+ const start = segment.startToken === "*" ? 0 : +segment.startToken.split("-")[0];
696
+ return { interval: segment.interval, last: segment.fires[segment.fires.length - 1], start };
697
+ }
698
+ const values = singleValues(segments);
699
+ const step = values && arithmeticStep(values);
700
+ return step || null;
701
+ }
702
+ function subMinuteSecond(ir) {
703
+ return ir.pattern.second === "*" || ir.shapes.second === "step";
704
+ }
705
+ function hourCadenceLead(ir, minute, opts) {
706
+ if (minute === 0) {
707
+ if (subMinuteSecond(ir)) {
708
+ return secondsLeadClause(ir, opts) + " minuutin ajan";
709
+ }
710
+ return secondsLeadClause(ir, opts);
711
+ }
712
+ const minutePhrase = atMarks(String(minute), units.minute, false);
713
+ if (ir.pattern.second === "0") {
714
+ return minutePhrase;
715
+ }
716
+ return secondsLeadClause(ir, opts) + ", " + minutePhrase;
717
+ }
718
+ function hourCadence(ir, minute, opts) {
719
+ const stride = hourStride(ir);
720
+ if (!stride) {
721
+ return null;
722
+ }
723
+ const fires = (stride.last - stride.start) / stride.interval + 1;
724
+ if (ir.pattern.second === "0" && fires <= maxClockTimes) {
725
+ return null;
726
+ }
727
+ const segment = ir.analyses.segments.hour[0];
728
+ const confined = minute === 0 && subMinuteSecond(ir) && ir.analyses.segments.hour.length === 1 && segment.kind === "step" && cleanHourStride(segment);
729
+ if (confined) {
730
+ return secondsLeadClause(ir, opts) + " minuutin ajan " + everyNthHour(segment, opts) + trailingQualifier(ir, opts);
731
+ }
732
+ return hourCadenceLead(ir, minute, opts) + ", " + hourStrideCadence(stride, opts) + trailingQualifier(ir, opts);
733
+ }
734
+ function cleanHourStride(segment) {
735
+ if (segment.startToken.indexOf("-") !== -1) {
736
+ return false;
737
+ }
738
+ const start = segment.startToken === "*" ? 0 : +segment.startToken;
739
+ return 24 % segment.interval === 0 && start < segment.interval;
740
+ }
593
741
  function kloList(hours, opts) {
594
742
  if (hours.length === 1) {
595
743
  return timeWord(hours[0], 0, null, opts);