cronli5 0.2.0 → 0.2.1

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/en.cjs CHANGED
@@ -60,6 +60,48 @@ function orderWeekdaysForDisplay(segments) {
60
60
  return pair[0];
61
61
  });
62
62
  }
63
+ function segmentsOf(ir, field) {
64
+ return ir.analyses.segments[field] ?? [];
65
+ }
66
+ function stepSegment(ir, field) {
67
+ return segmentsOf(ir, field)[0];
68
+ }
69
+ function singleValues(segments) {
70
+ const values = [];
71
+ for (const segment of segments) {
72
+ if (segment.kind !== "single") {
73
+ return null;
74
+ }
75
+ values.push(+segment.value);
76
+ }
77
+ return values;
78
+ }
79
+ function offsetCleanStride(stride) {
80
+ return stride.start < stride.interval && 24 % stride.interval === 0;
81
+ }
82
+ function hourListStride(values) {
83
+ if (values.length < 2) {
84
+ return null;
85
+ }
86
+ const interval = values[1] - values[0];
87
+ if (interval < 2) {
88
+ return null;
89
+ }
90
+ for (let i = 2; i < values.length; i += 1) {
91
+ if (values[i] - values[i - 1] !== interval) {
92
+ return null;
93
+ }
94
+ }
95
+ if (values[0] !== 0 && values.length < 5) {
96
+ return null;
97
+ }
98
+ return { interval, last: values[values.length - 1], start: values[0] };
99
+ }
100
+
101
+ // src/core/shapes.ts
102
+ function isOpenStep(field) {
103
+ return field.indexOf("/") !== -1 && field.indexOf("-") === -1 && field.indexOf(",") === -1;
104
+ }
63
105
 
64
106
  // src/core/specs.ts
65
107
  var maxClockTimes = 6;
@@ -281,7 +323,7 @@ function secondsClause(ir, anchor, opts) {
281
323
  }
282
324
  if (shape === "step") {
283
325
  return stepCycle60(
284
- ir.analyses.segments.second[0],
326
+ stepSegment(ir, "second"),
285
327
  "second",
286
328
  anchor,
287
329
  opts
@@ -296,12 +338,12 @@ function secondsClause(ir, anchor, opts) {
296
338
  return "at " + getNumber(secondField, opts) + " " + pluralize(secondField, "second") + " past the " + anchor;
297
339
  }
298
340
  return strideFromSegments(
299
- ir.analyses.segments.second,
341
+ segmentsOf(ir, "second"),
300
342
  "second",
301
343
  anchor,
302
344
  opts
303
345
  ) ?? listPastThe(
304
- segmentWords(ir.analyses.segments.second, opts),
346
+ segmentWords(segmentsOf(ir, "second"), opts),
305
347
  "second",
306
348
  anchor,
307
349
  opts
@@ -318,15 +360,15 @@ function renderRangeOfMinutes(ir, plan, opts) {
318
360
  return minuteRangeLead(ir.pattern.minute, opts) + trailingQualifier(ir, opts);
319
361
  }
320
362
  function renderMultipleMinutes(ir, plan, opts) {
321
- const stride = strideFromSegments(ir.analyses.segments.minute, "minute", "hour", opts);
363
+ const stride = strideFromSegments(segmentsOf(ir, "minute"), "minute", "hour", opts);
322
364
  return (stride ?? listPastThe(segmentWords(
323
- ir.analyses.segments.minute,
365
+ segmentsOf(ir, "minute"),
324
366
  opts
325
367
  ), "minute", "hour", opts)) + trailingQualifier(ir, opts);
326
368
  }
327
369
  function renderMinuteFrequency(ir, plan, opts) {
328
370
  let phrase = stepCycle60(
329
- ir.analyses.segments.minute[0],
371
+ stepSegment(ir, "minute"),
330
372
  "minute",
331
373
  "hour",
332
374
  opts
@@ -335,9 +377,14 @@ function renderMinuteFrequency(ir, plan, opts) {
335
377
  const cadence = unevenHourCadence(ir, opts);
336
378
  phrase += cadence ? ", " + cadence : " during the " + hourTimesFromPlan(ir, plan.hours.times, false, opts) + " hours";
337
379
  } else if (plan.hours.kind === "window") {
338
- phrase += " " + hourWindow(plan.hours, opts);
380
+ phrase += " " + rangeWindow({
381
+ continuous: false,
382
+ from: plan.hours.from,
383
+ throughMinute: plan.hours.last,
384
+ to: plan.hours.to
385
+ }, opts);
339
386
  } else if (plan.hours.kind === "step") {
340
- phrase += " " + everyNthHour(ir.analyses.segments.hour[0], opts);
387
+ phrase += " " + everyNthHour(stepSegment(ir, "hour"), opts);
341
388
  }
342
389
  return phrase + trailingQualifier(ir, opts);
343
390
  }
@@ -365,8 +412,8 @@ function renderMinutesAcrossHours(ir, plan, opts) {
365
412
  }
366
413
  return lead2 + " during the " + hourTimesFromPlan(ir, plan.times, false, opts) + " hours" + trailingQualifier(ir, opts);
367
414
  }
368
- const lead = strideFromSegments(ir.analyses.segments.minute, "minute", "hour", opts) ?? listPastThe(
369
- segmentWords(ir.analyses.segments.minute, opts),
415
+ const lead = strideFromSegments(segmentsOf(ir, "minute"), "minute", "hour", opts) ?? listPastThe(
416
+ segmentWords(segmentsOf(ir, "minute"), opts),
370
417
  "minute",
371
418
  "hour",
372
419
  opts
@@ -391,12 +438,12 @@ function everyNthHour(segment, opts) {
391
438
  return start === 0 ? base : base + " starting at " + getTime({ hour: start, minute: 0 }, opts);
392
439
  }
393
440
  function renderMinuteSpanAcrossHourStep(ir, plan, opts) {
394
- const segment = ir.analyses.segments.hour[0];
441
+ const segment = stepSegment(ir, "hour");
395
442
  if (plan.form === "wildcard") {
396
443
  return "every minute " + everyNthHour(segment, opts) + trailingQualifier(ir, opts);
397
444
  }
398
- const lead = plan.form === "list" ? strideFromSegments(ir.analyses.segments.minute, "minute", "hour", opts) ?? listPastThe(
399
- segmentWords(ir.analyses.segments.minute, opts),
445
+ const lead = plan.form === "list" ? strideFromSegments(segmentsOf(ir, "minute"), "minute", "hour", opts) ?? listPastThe(
446
+ segmentWords(segmentsOf(ir, "minute"), opts),
400
447
  "minute",
401
448
  "hour",
402
449
  opts
@@ -427,12 +474,12 @@ function rangeMinuteLead(ir, opts) {
427
474
  return "every hour";
428
475
  }
429
476
  return strideFromSegments(
430
- ir.analyses.segments.minute,
477
+ segmentsOf(ir, "minute"),
431
478
  "minute",
432
479
  "hour",
433
480
  opts
434
481
  ) ?? listPastThe(
435
- segmentWords(ir.analyses.segments.minute, opts),
482
+ segmentWords(segmentsOf(ir, "minute"), opts),
436
483
  "minute",
437
484
  "hour",
438
485
  opts
@@ -443,21 +490,28 @@ function renderHourStep(ir, plan, opts) {
443
490
  if (cadence !== null) {
444
491
  return cadence + trailingQualifier(ir, opts);
445
492
  }
446
- return stepHours(ir.analyses.segments.hour[0], opts) + trailingQualifier(ir, opts);
493
+ return stepHours(stepSegment(ir, "hour"), opts) + trailingQualifier(ir, opts);
447
494
  }
448
495
  function boundedWindow(plan) {
449
- const last = plan.minuteForm === "wildcard" ? plan.boundMinute ?? 0 : 0;
450
- return { from: plan.from, last, to: plan.to };
496
+ const continuous = plan.minuteForm === "wildcard";
497
+ const closeMinute = continuous ? plan.boundMinute ?? 0 : 0;
498
+ return { from: plan.from, closeMinute, to: plan.to, continuous };
451
499
  }
452
- function rangeWindow(from, to, throughMinute, opts) {
500
+ function rangeWindow(window, opts) {
501
+ const { from, to, throughMinute, continuous } = window;
453
502
  const open = "from " + getTime({ hour: from, minute: 0 }, opts);
454
503
  if (opts.style.untilWindow && !opts.short && from !== to) {
455
- return open + " until " + getTime({ hour: (to + 1) % 24, minute: 0 }, opts);
504
+ return continuous ? open + " until " + getTime({ hour: (to + 1) % 24, minute: 0 }, opts) : open + through(opts) + getTime({ hour: to, minute: 0 }, opts);
456
505
  }
457
506
  return open + through(opts) + getTime({ hour: to, minute: throughMinute }, opts);
458
507
  }
459
508
  function hourWindow(window, opts) {
460
- return rangeWindow(window.from, window.to, window.last, opts);
509
+ return rangeWindow({
510
+ continuous: window.continuous,
511
+ from: window.from,
512
+ throughMinute: window.closeMinute,
513
+ to: window.to
514
+ }, opts);
461
515
  }
462
516
  function renderClockTimes(ir, plan, opts) {
463
517
  if (ir.shapes.minute === "single") {
@@ -487,7 +541,7 @@ function renderCompactClockTimes(ir, plan, opts) {
487
541
  if (cadence2 !== null) {
488
542
  return cadence2;
489
543
  }
490
- const hasRange = ir.analyses.segments.hour.some(function range(segment) {
544
+ const hasRange = segmentsOf(ir, "hour").some(function range(segment) {
491
545
  return segment.kind === "range";
492
546
  });
493
547
  if (hasRange && !ir.analyses.clockSecond) {
@@ -499,8 +553,8 @@ function renderCompactClockTimes(ir, plan, opts) {
499
553
  const minuteLead = (
500
554
  // The non-fold branch is a minute list, which has segments. An
501
555
  // offset/uneven step enumerated to that list reads as a stride.
502
- strideFromSegments(ir.analyses.segments.minute, "minute", "hour", opts) ?? listPastThe(
503
- segmentWords(ir.analyses.segments.minute, opts),
556
+ strideFromSegments(segmentsOf(ir, "minute"), "minute", "hour", opts) ?? listPastThe(
557
+ segmentWords(segmentsOf(ir, "minute"), opts),
504
558
  "minute",
505
559
  "hour",
506
560
  opts
@@ -513,42 +567,38 @@ function renderCompactClockTimes(ir, plan, opts) {
513
567
  function foldedHourWindows(ir, plan, opts) {
514
568
  const minute = plan.minute;
515
569
  const windows = [];
516
- const outliers = collectHourOutliers(ir);
517
- const times = outliers.hours.map(function time(hour) {
570
+ const times = collectHourOutliers(ir).map(function time(hour) {
518
571
  return getTime({ hour, minute }, opts);
519
572
  });
520
- ir.analyses.segments.hour.forEach(function classify(segment) {
573
+ segmentsOf(ir, "hour").forEach(function classify(segment) {
521
574
  if (segment.kind === "range") {
522
- windows.push(rangeWindow(
523
- +segment.bounds[0],
524
- +segment.bounds[1],
525
- minute,
526
- opts
527
- ));
575
+ windows.push(rangeWindow({
576
+ continuous: false,
577
+ from: +segment.bounds[0],
578
+ throughMinute: minute,
579
+ to: +segment.bounds[1]
580
+ }, opts));
528
581
  }
529
582
  });
530
583
  const phrase = rangeMinuteLead(ir, opts) + " " + joinList(windows, opts);
531
- return phrase + outlierTail(times, outliers.pureStrays, opts);
584
+ return phrase + outlierTail(times, opts);
532
585
  }
533
586
  function collectHourOutliers(ir) {
534
587
  const hours = [];
535
- let pureStrays = true;
536
- ir.analyses.segments.hour.forEach(function classify(segment) {
588
+ segmentsOf(ir, "hour").forEach(function classify(segment) {
537
589
  if (segment.kind === "step") {
538
590
  hours.push(...segment.fires);
539
- pureStrays = false;
540
591
  } else if (segment.kind !== "range") {
541
592
  hours.push(+segment.value);
542
593
  }
543
594
  });
544
- return { hours, pureStrays };
595
+ return hours;
545
596
  }
546
- function outlierTail(times, pureStrays, opts) {
597
+ function outlierTail(times, opts) {
547
598
  if (!times.length) {
548
599
  return "";
549
600
  }
550
- const connector = pureStrays && opts.style.untilWindow && !opts.short ? " plus " : " and at ";
551
- return connector + joinList(times, opts);
601
+ return " and at " + joinList(times, opts);
552
602
  }
553
603
  function isCadenceField(token) {
554
604
  return token === "*" || token.startsWith("*/") && token.indexOf("-") === -1;
@@ -562,7 +612,7 @@ function leadingCadence(ir, opts) {
562
612
  const text = minute === "*" ? "every minute" : (
563
613
  // A clean minute step's first segment is a step segment.
564
614
  stepCycle60(
565
- ir.analyses.segments.minute[0],
615
+ stepSegment(ir, "minute"),
566
616
  "minute",
567
617
  "hour",
568
618
  opts
@@ -580,7 +630,7 @@ function minuteConfinement(ir, opts) {
580
630
  if (isCadenceField(minute)) {
581
631
  return " of every other minute";
582
632
  }
583
- const segments = ir.analyses.segments.minute;
633
+ const segments = segmentsOf(ir, "minute");
584
634
  if (ir.shapes.minute === "single") {
585
635
  return " during minute :" + pad(minute);
586
636
  }
@@ -614,7 +664,12 @@ function hourConfinement(ir, opts) {
614
664
  }
615
665
  if (ir.shapes.hour === "range") {
616
666
  const bounds = hour.split("-");
617
- return " " + rangeWindow(+bounds[0], +bounds[1], 0, opts);
667
+ return " " + rangeWindow({
668
+ continuous: ir.pattern.minute === "*",
669
+ from: +bounds[0],
670
+ throughMinute: 0,
671
+ to: +bounds[1]
672
+ }, opts);
618
673
  }
619
674
  return " during the " + hourSegmentTimes(ir, { minute: 0, second: null }, false, opts) + " hours";
620
675
  }
@@ -625,14 +680,14 @@ function confinableHour(ir) {
625
680
  if (ir.shapes.hour !== "step") {
626
681
  return true;
627
682
  }
628
- const segment = ir.analyses.segments.hour[0];
683
+ const segment = stepSegment(ir, "hour");
629
684
  return ir.pattern.hour === "*/2" || segment.startToken.indexOf("-") !== -1;
630
685
  }
631
686
  function isMinuteStride(ir) {
632
687
  if (ir.shapes.minute !== "list") {
633
688
  return false;
634
689
  }
635
- const values = singleValues(ir.analyses.segments.minute);
690
+ const values = singleValues(segmentsOf(ir, "minute"));
636
691
  return values !== null && arithmeticStep(values) !== null;
637
692
  }
638
693
  function confinementEligible(ir, lead) {
@@ -702,16 +757,6 @@ function renderStride(stride, opts) {
702
757
  const num = seriesNumber();
703
758
  return cadence + " from " + num(start) + through(opts) + num(last) + " " + pluralize(last, unit) + " past the " + anchor;
704
759
  }
705
- function singleValues(segments) {
706
- const values = [];
707
- for (const segment of segments) {
708
- if (segment.kind !== "single") {
709
- return null;
710
- }
711
- values.push(+segment.value);
712
- }
713
- return values;
714
- }
715
760
  function strideFromSegments(segments, unit, anchor, opts) {
716
761
  const values = singleValues(segments);
717
762
  const step = values && arithmeticStep(values);
@@ -760,9 +805,6 @@ function hourStrideCadence(stride, opts) {
760
805
  }
761
806
  return cadence + " from " + getTime({ hour: start, minute: 0 }, opts) + through(opts) + getTime({ hour: last, minute: 0 }, opts);
762
807
  }
763
- function offsetCleanStride(stride) {
764
- return stride.start < stride.interval && 24 % stride.interval === 0;
765
- }
766
808
  function unevenHourCadence(ir, opts) {
767
809
  const stride = hourStride(ir);
768
810
  if (!stride || offsetCleanStride(stride)) {
@@ -770,26 +812,8 @@ function unevenHourCadence(ir, opts) {
770
812
  }
771
813
  return hourStrideCadence(stride, opts);
772
814
  }
773
- function hourListStride(values) {
774
- if (values.length < 2) {
775
- return null;
776
- }
777
- const interval = values[1] - values[0];
778
- if (interval < 2) {
779
- return null;
780
- }
781
- for (let i = 2; i < values.length; i += 1) {
782
- if (values[i] - values[i - 1] !== interval) {
783
- return null;
784
- }
785
- }
786
- if (values[0] !== 0 && values.length < 5) {
787
- return null;
788
- }
789
- return { interval, last: values[values.length - 1], start: values[0] };
790
- }
791
815
  function hourStride(ir) {
792
- const segments = ir.analyses.segments.hour;
816
+ const segments = segmentsOf(ir, "hour");
793
817
  if (segments.length === 1 && segments[0].kind === "step") {
794
818
  const segment = segments[0];
795
819
  if (segment.fires.length < 2) {
@@ -836,7 +860,7 @@ function hourCadence(ir, minute, opts) {
836
860
  return hourCadenceLead(ir, minute, opts) + ", " + hourStrideCadence(stride, opts) + trailingQualifier(ir, opts);
837
861
  }
838
862
  function cleanStrideSegment(ir) {
839
- const segments = ir.analyses.segments.hour;
863
+ const segments = segmentsOf(ir, "hour");
840
864
  const segment = segments.length === 1 && segments[0];
841
865
  if (!segment || segment.kind !== "step" || segment.startToken.indexOf("-") !== -1 || !(segment.interval in stepOrdinals)) {
842
866
  return null;
@@ -844,28 +868,28 @@ function cleanStrideSegment(ir) {
844
868
  return segment;
845
869
  }
846
870
  function hasHourWindow(ir) {
847
- return ir.analyses.segments.hour.some(function range(segment) {
871
+ return segmentsOf(ir, "hour").some(function range(segment) {
848
872
  return segment.kind === "range";
849
873
  });
850
874
  }
851
875
  function hourRangeWindowTail(ir, opts) {
852
876
  const windows = [];
853
- const outliers = collectHourOutliers(ir);
854
- ir.analyses.segments.hour.forEach(function classify(segment) {
877
+ const outlierHours = collectHourOutliers(ir);
878
+ segmentsOf(ir, "hour").forEach(function classify(segment) {
855
879
  if (segment.kind === "range") {
856
- windows.push(rangeWindow(
857
- +segment.bounds[0],
858
- +segment.bounds[1],
859
- 0,
860
- opts
861
- ));
880
+ windows.push(rangeWindow({
881
+ continuous: false,
882
+ from: +segment.bounds[0],
883
+ throughMinute: 0,
884
+ to: +segment.bounds[1]
885
+ }, opts));
862
886
  }
863
887
  });
864
888
  const phrase = "every hour " + joinList(windows, opts);
865
- const times = outliers.hours.map(function time(hour) {
889
+ const times = outlierHours.map(function time(hour) {
866
890
  return getTime({ hour, minute: 0 }, opts);
867
891
  });
868
- return phrase + outlierTail(times, outliers.pureStrays, opts);
892
+ return phrase + outlierTail(times, opts);
869
893
  }
870
894
  function hourRangeCadence(ir, minute, opts) {
871
895
  if (minute !== 0 || !hasHourWindow(ir)) {
@@ -950,7 +974,7 @@ function segmentHours(segment) {
950
974
  }
951
975
  function hourSegmentTimes(ir, fold, atContext, opts) {
952
976
  const { minute, second } = fold;
953
- const segments = ir.analyses.segments.hour;
977
+ const segments = segmentsOf(ir, "hour");
954
978
  const plain = mixedTwelve(segments.flatMap(function entries(segment) {
955
979
  return segmentHours(segment).map(function entry(hour) {
956
980
  return { hour: +hour, minute, second };
@@ -1070,7 +1094,7 @@ function datePhrase(ir, words, opts) {
1070
1094
  }
1071
1095
  function monthFoldsIntoDate(ir) {
1072
1096
  return !oddEvenMonth(ir.pattern.month) && // Reached only with a restricted month, which has segments.
1073
- ir.analyses.segments.month.every(function flat(segment) {
1097
+ segmentsOf(ir, "month").every(function flat(segment) {
1074
1098
  return segment.kind !== "range";
1075
1099
  });
1076
1100
  }
@@ -1101,7 +1125,7 @@ function dayUnionDatePieces(ir, opts) {
1101
1125
  return [oddEven];
1102
1126
  }
1103
1127
  const pieces = [];
1104
- ir.analyses.segments.date.forEach(function expand(segment) {
1128
+ segmentsOf(ir, "date").forEach(function expand(segment) {
1105
1129
  if (segment.kind === "range") {
1106
1130
  pieces.push("from the " + getOrdinal(segment.bounds[0]) + through(opts) + "the " + getOrdinal(segment.bounds[1]));
1107
1131
  } else if (segment.kind === "step") {
@@ -1121,7 +1145,7 @@ function dayUnionWeekdayPieces(ir, opts) {
1121
1145
  return [quartz.replace(/^on /, "")];
1122
1146
  }
1123
1147
  const pieces = [];
1124
- ir.analyses.segments.weekday.forEach(function expand(segment) {
1148
+ segmentsOf(ir, "weekday").forEach(function expand(segment) {
1125
1149
  if (segment.kind === "range" && segment.bounds[0] === "1" && segment.bounds[1] === "5") {
1126
1150
  pieces.push("a weekday");
1127
1151
  } else if (segment.kind === "range") {
@@ -1202,7 +1226,7 @@ function quartzWeekdayPhrase(weekdayField, opts) {
1202
1226
  function monthDatePhrase(ir, opts) {
1203
1227
  const month = monthName(ir, opts);
1204
1228
  const days = renderSegments(
1205
- ir.analyses.segments.date,
1229
+ segmentsOf(ir, "date"),
1206
1230
  opts.style.ordinals ? getOrdinal : cardinalDay,
1207
1231
  opts
1208
1232
  );
@@ -1245,14 +1269,14 @@ function stepDates(dateField) {
1245
1269
  return phrase;
1246
1270
  }
1247
1271
  function dateOrdinals(ir, opts) {
1248
- return renderSegments(ir.analyses.segments.date, getOrdinal, opts);
1272
+ return renderSegments(segmentsOf(ir, "date"), getOrdinal, opts);
1249
1273
  }
1250
1274
  function monthName(ir, opts) {
1251
1275
  const oddEven = oddEvenMonth(ir.pattern.month);
1252
1276
  if (oddEven) {
1253
1277
  return oddEven;
1254
1278
  }
1255
- return renderSegments(ir.analyses.segments.month, function name(value) {
1279
+ return renderSegments(segmentsOf(ir, "month"), function name(value) {
1256
1280
  return getMonth(value, opts);
1257
1281
  }, opts);
1258
1282
  }
@@ -1270,7 +1294,7 @@ function oddEvenMonth(monthField) {
1270
1294
  return start === "2" ? "every even-numbered month" : null;
1271
1295
  }
1272
1296
  function weekdayPhrase(ir, recurring, opts) {
1273
- const segments = orderWeekdaysForDisplay(ir.analyses.segments.weekday);
1297
+ const segments = orderWeekdaysForDisplay(segmentsOf(ir, "weekday"));
1274
1298
  const hasRange = segments.some(function range(segment) {
1275
1299
  return segment.kind === "range";
1276
1300
  });
@@ -1298,9 +1322,6 @@ function renderSegments(segments, word, opts) {
1298
1322
  });
1299
1323
  return joinList(pieces, opts);
1300
1324
  }
1301
- function isOpenStep(field) {
1302
- return field.indexOf("/") !== -1 && field.indexOf("-") === -1 && field.indexOf(",") === -1;
1303
- }
1304
1325
  function applyYear(description, ir, opts) {
1305
1326
  const yearField = ir.pattern.year;
1306
1327
  if (yearField === "*") {