cronli5 0.1.2 → 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.js CHANGED
@@ -14,6 +14,42 @@ function clockDigits(time, { sep, pad: padHour, lean }) {
14
14
  return head + sep + pad(time.minute) + (time.second ? sep + pad(time.second) : "");
15
15
  }
16
16
 
17
+ // src/core/specs.ts
18
+ var weekdayNumbers = {
19
+ SUN: 0,
20
+ MON: 1,
21
+ TUE: 2,
22
+ WED: 3,
23
+ THU: 4,
24
+ FRI: 5,
25
+ SAT: 6
26
+ };
27
+ var maxClockTimes = 6;
28
+
29
+ // src/core/util.ts
30
+ function isNonNegativeInteger(value) {
31
+ const digits = /^\d+$/;
32
+ return digits.test(value);
33
+ }
34
+ function arithmeticStep(values) {
35
+ if (values.length < 5) {
36
+ return null;
37
+ }
38
+ const interval = values[1] - values[0];
39
+ if (interval < 2) {
40
+ return null;
41
+ }
42
+ for (let i = 2; i < values.length; i += 1) {
43
+ if (values[i] - values[i - 1] !== interval) {
44
+ return null;
45
+ }
46
+ }
47
+ return { start: values[0], interval, last: values[values.length - 1] };
48
+ }
49
+ function toFieldNumber(token, numberMap) {
50
+ return isNonNegativeInteger(token) ? +token : numberMap[token.toUpperCase()];
51
+ }
52
+
17
53
  // src/lang/fi/dialects.ts
18
54
  var dialects = {
19
55
  fi: {
@@ -140,40 +176,19 @@ var monthStems = [
140
176
  "marras",
141
177
  "joulu"
142
178
  ];
143
- var monthTokens = {
144
- JAN: 1,
145
- FEB: 2,
146
- MAR: 3,
147
- APR: 4,
148
- MAY: 5,
149
- JUN: 6,
150
- JUL: 7,
151
- AUG: 8,
152
- SEP: 9,
153
- OCT: 10,
154
- NOV: 11,
155
- DEC: 12
156
- };
157
- var weekdayTokens = {
158
- SUN: 0,
159
- MON: 1,
160
- TUE: 2,
161
- WED: 3,
162
- THU: 4,
163
- FRI: 5,
164
- SAT: 6
165
- };
166
179
  var units = {
167
180
  minute: {
168
181
  mark: "joka tunti",
169
182
  anchor: "jokaisen tunnin",
170
183
  ela: "minuutista",
184
+ ill: "minuuttiin",
171
185
  gen: "minuutin"
172
186
  },
173
187
  second: {
174
188
  mark: "joka minuutti",
175
189
  anchor: "jokaisen minuutin",
176
190
  ela: "sekunnista",
191
+ ill: "sekuntiin",
177
192
  gen: "sekunnin"
178
193
  }
179
194
  };
@@ -229,26 +244,61 @@ function renderSecondsWithinMinute(ir, plan, opts) {
229
244
  }
230
245
  return secondsLeadClause(ir, opts) + ", " + atMarks(minuteField, units.minute, true) + trailingQualifier(ir, opts);
231
246
  }
247
+ function composeSecondsOverMinuteStep(ir, freq, opts) {
248
+ const seg = stepSegment(ir.analyses.segments.minute);
249
+ const stepPhrase = stepCycle60(seg, units.minute, opts);
250
+ if (freq.hours.kind === "during" && minuteStepIsAnchored(seg)) {
251
+ const bareHours = kloFromTimes(ir, freq.hours.times, opts);
252
+ return hoursFirstMinutes(bareHours, ir, opts) + ", " + secondsLeadClause(ir, opts) + trailingQualifier(ir, opts);
253
+ }
254
+ let hourClause = "";
255
+ if (freq.hours.kind === "during") {
256
+ hourClause = " " + hourWindowsFromTimes(ir, freq.hours.times, opts);
257
+ } else if (freq.hours.kind === "window") {
258
+ hourClause = " " + hourWindow(freq.hours, opts);
259
+ } else if (freq.hours.kind === "step") {
260
+ hourClause = " " + everyNthHour(stepSegment(ir.analyses.segments.hour), opts);
261
+ }
262
+ return stepPhrase + ", " + secondsLeadClause(ir, opts) + hourClause + trailingQualifier(ir, opts);
263
+ }
264
+ function composeHourCadence(ir, plan, opts) {
265
+ const clockRest = plan.rest.kind === "clockTimes" || plan.rest.kind === "compactClockTimes";
266
+ return clockRest && ir.shapes.minute === "single" ? hourCadence(ir, +ir.pattern.minute, opts) : null;
267
+ }
232
268
  function renderComposeSeconds(ir, plan, opts) {
269
+ const cadence = composeHourCadence(ir, plan, opts);
270
+ if (cadence !== null) {
271
+ return cadence;
272
+ }
233
273
  if (plan.rest.kind === "minuteFrequency" && ir.pattern.second !== "*") {
234
- const freq = plan.rest;
235
- const seg = stepSegment(ir.analyses.segments.minute);
236
- const stepPhrase = stepCycle60(seg, units.minute, opts);
237
- let hourClause = "";
238
- if (freq.hours.kind === "during" && minuteStepIsAnchored(seg)) {
239
- const bareHours = kloFromTimes(ir, freq.hours.times, opts);
240
- return hoursFirstMinutes(bareHours, ir) + ", " + secondsLeadClause(ir, opts) + trailingQualifier(ir, opts);
241
- } else if (freq.hours.kind === "during" && !minuteStepIsAnchored(seg)) {
242
- hourClause = " " + hourWindowsFromTimes(ir, freq.hours.times, opts);
243
- } else if (freq.hours.kind === "window") {
244
- hourClause = " " + hourWindow(freq.hours, opts);
245
- } else if (freq.hours.kind === "step") {
246
- hourClause = " " + everyNthHour(stepSegment(ir.analyses.segments.hour), opts);
247
- }
248
- return stepPhrase + ", " + secondsLeadClause(ir, opts) + hourClause + trailingQualifier(ir, opts);
274
+ return composeSecondsOverMinuteStep(ir, plan.rest, opts);
275
+ }
276
+ if (plan.rest.kind === "clockTimes" && plan.rest.times.every((time) => +time.minute === 0)) {
277
+ return composeMinuteZero(ir, plan.rest, opts);
278
+ }
279
+ if (isEveryOtherMinuteSeconds(ir, plan)) {
280
+ return secondsLeadClause(ir, opts) + " joka toisena minuuttina";
249
281
  }
250
282
  return secondsLeadClause(ir, opts) + ", " + render(ir, plan.rest, opts);
251
283
  }
284
+ function isEveryOtherMinuteSeconds(ir, plan) {
285
+ if (plan.rest.kind !== "minuteFrequency" || ir.pattern.second !== "*" || ir.shapes.hour !== "wildcard") {
286
+ return false;
287
+ }
288
+ const seg = stepSegment(ir.analyses.segments.minute);
289
+ return seg.startToken === "*" && seg.interval === 2;
290
+ }
291
+ function composeMinuteZero(ir, rest, opts) {
292
+ const clocks = rest.times.map(function clock(time) {
293
+ return clockDigits(
294
+ { hour: time.hour, minute: time.minute },
295
+ { sep: opts.style.sep }
296
+ );
297
+ });
298
+ const frame = clocks.length === 1 ? "minuutin " + clocks[0] : "minuuttien " + joinList(clocks);
299
+ const dayTrail = leadingQualifier(ir, opts).trimEnd();
300
+ return secondsLeadClause(ir, opts) + " " + frame + " aikana" + (dayTrail ? ", " + dayTrail : "");
301
+ }
252
302
  function secondsLeadClause(ir, opts) {
253
303
  const secondField = ir.pattern.second;
254
304
  const shape = ir.shapes.second;
@@ -266,7 +316,7 @@ function secondsLeadClause(ir, opts) {
266
316
  if (shape === "single") {
267
317
  return atMarks(secondField, units.second, marked);
268
318
  }
269
- return atMarks(
319
+ return strideFromSegments(ir.analyses.segments.second, units.second, opts) ?? atMarks(
270
320
  joinList(segmentWords(ir.analyses.segments.second)),
271
321
  units.second,
272
322
  marked
@@ -279,20 +329,20 @@ function renderSingleMinute(ir, plan, opts) {
279
329
  return atMarks(ir.pattern.minute, units.minute, true) + trailingQualifier(ir, opts);
280
330
  }
281
331
  function renderRangeOfMinutes(ir, plan, opts) {
282
- return minutesList(ir) + trailingQualifier(ir, opts);
332
+ return minutesList(ir, opts) + trailingQualifier(ir, opts);
283
333
  }
284
334
  function renderMultipleMinutes(ir, plan, opts) {
285
- return minutesList(ir) + trailingQualifier(ir, opts);
335
+ return minutesList(ir, opts) + trailingQualifier(ir, opts);
286
336
  }
287
- function minutesList(ir) {
288
- return atMarks(
337
+ function minutesList(ir, opts) {
338
+ return strideFromSegments(ir.analyses.segments.minute, units.minute, opts) ?? atMarks(
289
339
  joinList(segmentWords(ir.analyses.segments.minute)),
290
340
  units.minute,
291
341
  true
292
342
  );
293
343
  }
294
- function bareMinutes(ir) {
295
- return atMarks(
344
+ function bareMinutes(ir, opts) {
345
+ return strideFromSegments(ir.analyses.segments.minute, units.minute, opts) ?? atMarks(
296
346
  joinList(segmentWords(ir.analyses.segments.minute)),
297
347
  units.minute,
298
348
  false
@@ -323,7 +373,11 @@ function hoursAreRangeIsolated(segments) {
323
373
  }
324
374
  return hasRange && hasSingle;
325
375
  }
326
- function hoursFirstMinutes(hoursStr, ir) {
376
+ function hoursFirstMinutes(hoursStr, ir, opts) {
377
+ const stride = strideFromSegments(ir.analyses.segments.minute, units.minute, opts);
378
+ if (stride) {
379
+ return hoursStr + " aina " + stride;
380
+ }
327
381
  return hoursStr + " aina minuuttien " + joinList(segmentWords(ir.analyses.segments.minute)) + " kohdalla";
328
382
  }
329
383
  function hourSegmentTimesWithSeka(ir, minute, second, opts) {
@@ -346,7 +400,7 @@ function renderMinuteFrequency(ir, plan, opts) {
346
400
  if (plan.hours.kind === "during") {
347
401
  if (minuteStepIsAnchored(seg)) {
348
402
  const bareHours = kloFromTimes(ir, plan.hours.times, opts);
349
- return hoursFirstMinutes(bareHours, ir) + trailingQualifier(ir, opts);
403
+ return hoursFirstMinutes(bareHours, ir, opts) + trailingQualifier(ir, opts);
350
404
  }
351
405
  return stepCycle60(seg, units.minute, opts) + " " + hourWindowsFromTimes(ir, plan.hours.times, opts) + trailingQualifier(ir, opts);
352
406
  }
@@ -359,6 +413,9 @@ function renderMinuteFrequency(ir, plan, opts) {
359
413
  return phrase + trailingQualifier(ir, opts);
360
414
  }
361
415
  function renderMinuteSpanInHour(ir, plan, opts) {
416
+ if (ir.pattern.minute === "*") {
417
+ return "joka minuutti kello " + plan.hour + " aikana" + trailingQualifier(ir, opts);
418
+ }
362
419
  return "joka minuutti " + kloRange(
363
420
  { hour: plan.hour, minute: plan.span[0] },
364
421
  { hour: plan.hour, minute: plan.span[1] },
@@ -370,10 +427,10 @@ function renderMinutesAcrossHours(ir, plan, opts) {
370
427
  return "joka minuutti " + hourWindowsFromTimes(ir, plan.times, opts) + trailingQualifier(ir, opts);
371
428
  }
372
429
  if (hoursAreRangeIsolated(ir.analyses.segments.hour)) {
373
- return bareMinutes(ir) + " " + hourSegmentTimesWithSeka(ir, 0, null, opts) + trailingQualifier(ir, opts);
430
+ return bareMinutes(ir, opts) + " " + hourSegmentTimesWithSeka(ir, 0, null, opts) + trailingQualifier(ir, opts);
374
431
  }
375
432
  const hoursStr = kloFromTimes(ir, plan.times, opts);
376
- return hoursFirstMinutes(hoursStr, ir) + trailingQualifier(ir, opts);
433
+ return hoursFirstMinutes(hoursStr, ir, opts) + trailingQualifier(ir, opts);
377
434
  }
378
435
  function renderMinuteSpanAcrossHourStep(ir, plan, opts) {
379
436
  const segment = stepSegment(ir.analyses.segments.hour);
@@ -382,9 +439,9 @@ function renderMinuteSpanAcrossHourStep(ir, plan, opts) {
382
439
  }
383
440
  if (segment.startToken.indexOf("-") !== -1) {
384
441
  const hoursStr = kloList(segment.fires, opts);
385
- return hoursFirstMinutes(hoursStr, ir) + trailingQualifier(ir, opts);
442
+ return hoursFirstMinutes(hoursStr, ir, opts) + trailingQualifier(ir, opts);
386
443
  }
387
- return bareMinutes(ir) + hourStepTail(segment, opts) + trailingQualifier(ir, opts);
444
+ return bareMinutes(ir, opts) + hourStepTail(segment, opts) + trailingQualifier(ir, opts);
388
445
  }
389
446
  function plainHourStep(segment) {
390
447
  return segment.startToken === "*" && 24 % segment.interval === 0;
@@ -442,7 +499,7 @@ function renderHourRange(ir, plan, opts) {
442
499
  return "joka minuutti " + window + trailingQualifier(ir, opts);
443
500
  }
444
501
  if (plan.minuteForm === "range") {
445
- return hoursFirstMinutes(window, ir) + trailingQualifier(ir, opts);
502
+ return hoursFirstMinutes(window, ir, opts) + trailingQualifier(ir, opts);
446
503
  }
447
504
  if (ir.pattern.minute === "0") {
448
505
  return "joka tunti " + window + trailingQualifier(ir, opts);
@@ -454,7 +511,7 @@ function renderHourRange(ir, plan, opts) {
454
511
  opts
455
512
  ) + trailingQualifier(ir, opts);
456
513
  }
457
- return hoursFirstMinutes(window, ir) + trailingQualifier(ir, opts);
514
+ return hoursFirstMinutes(window, ir, opts) + trailingQualifier(ir, opts);
458
515
  }
459
516
  function renderHourStep(ir, plan, opts) {
460
517
  return stepHours(stepSegment(ir.analyses.segments.hour), opts) + trailingQualifier(ir, opts);
@@ -470,6 +527,12 @@ function hourWindow(window, opts) {
470
527
  );
471
528
  }
472
529
  function renderClockTimes(ir, plan, opts) {
530
+ if (ir.shapes.minute === "single") {
531
+ const cadence = hourCadence(ir, +ir.pattern.minute, opts);
532
+ if (cadence !== null) {
533
+ return cadence;
534
+ }
535
+ }
473
536
  if (plan.times.length === 1) {
474
537
  const time = plan.times[0];
475
538
  return leadingQualifier(ir, opts) + timeWord(time.hour, time.minute, time.second, opts);
@@ -480,6 +543,12 @@ function renderClockTimes(ir, plan, opts) {
480
543
  return leadingQualifier(ir, opts) + "klo " + joinList(digits);
481
544
  }
482
545
  function renderCompactClockTimes(ir, plan, opts) {
546
+ if (plan.fold) {
547
+ const cadence = hourCadence(ir, plan.minute, opts);
548
+ if (cadence !== null) {
549
+ return cadence;
550
+ }
551
+ }
483
552
  const hourSegs = ir.analyses.segments.hour;
484
553
  if (hoursAreRangeIsolated(hourSegs)) {
485
554
  if (plan.fold) {
@@ -490,14 +559,14 @@ function renderCompactClockTimes(ir, plan, opts) {
490
559
  opts
491
560
  );
492
561
  }
493
- const phrase2 = bareMinutes(ir) + " " + hourSegmentTimesWithSeka(ir, 0, null, opts) + trailingQualifier(ir, opts);
562
+ const phrase2 = bareMinutes(ir, opts) + " " + hourSegmentTimesWithSeka(ir, 0, null, opts) + trailingQualifier(ir, opts);
494
563
  return ir.analyses.clockSecond ? secondsLeadClause(ir, opts) + ", " + phrase2 : phrase2;
495
564
  }
496
565
  if (plan.fold) {
497
566
  return leadingQualifier(ir, opts) + hourSegmentTimes(ir, plan.minute, ir.analyses.clockSecond, opts);
498
567
  }
499
568
  const hoursStr = hourSegmentTimes(ir, 0, null, opts);
500
- const phrase = hoursFirstMinutes(hoursStr, ir) + trailingQualifier(ir, opts);
569
+ const phrase = hoursFirstMinutes(hoursStr, ir, opts) + trailingQualifier(ir, opts);
501
570
  return ir.analyses.clockSecond ? secondsLeadClause(ir, opts) + ", " + phrase : phrase;
502
571
  }
503
572
  var renderers = {
@@ -520,20 +589,48 @@ var renderers = {
520
589
  singleMinute: renderSingleMinute,
521
590
  standaloneSeconds: renderStandaloneSeconds
522
591
  };
592
+ function renderStride(stride, opts) {
593
+ const { interval, start, last, cycle, unit } = stride;
594
+ const cadence = genitive(interval, opts) + " " + unit.gen + " v\xE4lein";
595
+ const tiles = cycle % interval === 0;
596
+ if (start === 0 && tiles) {
597
+ return cadence;
598
+ }
599
+ if (start < interval && tiles) {
600
+ return cadence + " " + unit.anchor + " " + unit.ela + " " + start + " alkaen";
601
+ }
602
+ return cadence + " " + unit.ela + " " + start + " " + unit.ill + " " + last;
603
+ }
604
+ function strideFromSegments(segments, unit, opts) {
605
+ const values = singleValues(segments);
606
+ const step = values && arithmeticStep(values);
607
+ return step ? renderStride({ ...step, cycle: 60, unit }, opts) : null;
608
+ }
609
+ function singleValues(segments) {
610
+ const values = [];
611
+ for (const segment of segments) {
612
+ if (segment.kind !== "single") {
613
+ return null;
614
+ }
615
+ values.push(+segment.value);
616
+ }
617
+ return values;
618
+ }
523
619
  function stepCycle60(segment, unit, opts) {
524
620
  if (segment.startToken.indexOf("-") !== -1) {
525
621
  return atMarks(joinList(wordList(segment.fires)), unit, true);
526
622
  }
527
623
  const start = segment.startToken === "*" ? 0 : +segment.startToken;
528
- const interval = segment.interval;
529
- const cadence = genitive(interval, opts) + " " + unit.gen + " v\xE4lein";
530
- if (start !== 0) {
531
- if (segment.fires.length <= 3) {
532
- return atMarks(joinList(wordList(segment.fires)), unit, true);
533
- }
534
- return cadence + " " + unit.anchor + " " + unit.ela + " " + start + " alkaen";
624
+ if (start !== 0 && segment.fires.length <= 3) {
625
+ return atMarks(joinList(wordList(segment.fires)), unit, true);
535
626
  }
536
- return cadence;
627
+ return renderStride({
628
+ interval: segment.interval,
629
+ start,
630
+ last: segment.fires[segment.fires.length - 1],
631
+ cycle: 60,
632
+ unit
633
+ }, opts);
537
634
  }
538
635
  function stepHours(segment, opts) {
539
636
  if (segment.startToken.indexOf("-") !== -1) {
@@ -550,6 +647,71 @@ function stepHours(segment, opts) {
550
647
  }
551
648
  return cadence + " klo " + hourElatives[start] + " alkaen";
552
649
  }
650
+ function hourStrideCadence(stride, opts) {
651
+ const { start, interval, last } = stride;
652
+ const cadence = genitive(interval, opts) + " tunnin v\xE4lein";
653
+ const tiles = 24 % interval === 0;
654
+ if (start === 0 && tiles) {
655
+ return cadence;
656
+ }
657
+ if (start < interval && tiles) {
658
+ return cadence + " klo " + hourElatives[start] + " alkaen";
659
+ }
660
+ return cadence + " " + kloRange({ hour: start, minute: 0 }, { hour: last, minute: 0 }, opts);
661
+ }
662
+ function hourStride(ir) {
663
+ const segments = ir.analyses.segments.hour;
664
+ if (!segments) {
665
+ return null;
666
+ }
667
+ if (segments.length === 1 && segments[0].kind === "step") {
668
+ const segment = segments[0];
669
+ const start = segment.startToken === "*" ? 0 : +segment.startToken.split("-")[0];
670
+ return { interval: segment.interval, last: segment.fires[segment.fires.length - 1], start };
671
+ }
672
+ const values = singleValues(segments);
673
+ const step = values && arithmeticStep(values);
674
+ return step || null;
675
+ }
676
+ function subMinuteSecond(ir) {
677
+ return ir.pattern.second === "*" || ir.shapes.second === "step";
678
+ }
679
+ function hourCadenceLead(ir, minute, opts) {
680
+ if (minute === 0) {
681
+ if (subMinuteSecond(ir)) {
682
+ return secondsLeadClause(ir, opts) + " minuutin ajan";
683
+ }
684
+ return secondsLeadClause(ir, opts);
685
+ }
686
+ const minutePhrase = atMarks(String(minute), units.minute, false);
687
+ if (ir.pattern.second === "0") {
688
+ return minutePhrase;
689
+ }
690
+ return secondsLeadClause(ir, opts) + ", " + minutePhrase;
691
+ }
692
+ function hourCadence(ir, minute, opts) {
693
+ const stride = hourStride(ir);
694
+ if (!stride) {
695
+ return null;
696
+ }
697
+ const fires = (stride.last - stride.start) / stride.interval + 1;
698
+ if (ir.pattern.second === "0" && fires <= maxClockTimes) {
699
+ return null;
700
+ }
701
+ const segment = ir.analyses.segments.hour[0];
702
+ const confined = minute === 0 && subMinuteSecond(ir) && ir.analyses.segments.hour.length === 1 && segment.kind === "step" && cleanHourStride(segment);
703
+ if (confined) {
704
+ return secondsLeadClause(ir, opts) + " minuutin ajan " + everyNthHour(segment, opts) + trailingQualifier(ir, opts);
705
+ }
706
+ return hourCadenceLead(ir, minute, opts) + ", " + hourStrideCadence(stride, opts) + trailingQualifier(ir, opts);
707
+ }
708
+ function cleanHourStride(segment) {
709
+ if (segment.startToken.indexOf("-") !== -1) {
710
+ return false;
711
+ }
712
+ const start = segment.startToken === "*" ? 0 : +segment.startToken;
713
+ return 24 % segment.interval === 0 && start < segment.interval;
714
+ }
553
715
  function kloList(hours, opts) {
554
716
  if (hours.length === 1) {
555
717
  return timeWord(hours[0], 0, null, opts);
@@ -814,13 +976,10 @@ function quartzWeekdayPhrase(weekdayField) {
814
976
  }
815
977
  }
816
978
  function weekdayNumber(token) {
817
- if (token in weekdayTokens) {
818
- return weekdayTokens[token];
819
- }
820
- return +token % 7;
979
+ return toFieldNumber("" + token, weekdayNumbers) % 7;
821
980
  }
822
981
  function monthNumber(token) {
823
- return monthTokens[token] || +token;
982
+ return +token;
824
983
  }
825
984
  function applyYear(description, ir, opts) {
826
985
  const yearField = ir.pattern.year;
@@ -902,7 +1061,9 @@ var fi = {
902
1061
  fallback: "tunnistamaton cron-lauseke",
903
1062
  options: normalizeOptions,
904
1063
  reboot: "j\xE4rjestelm\xE4n k\xE4ynnistyess\xE4",
905
- sentence: (description) => "Suoritetaan " + description + "."
1064
+ // A description ending in a period already carries it, so closing the
1065
+ // sentence must not double it.
1066
+ sentence: (description) => "Suoritetaan " + description + (description.endsWith(".") ? "" : ".")
906
1067
  };
907
1068
  var index_default = fi;
908
1069
  export {