cronli5 0.2.1 → 0.3.4

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.
Files changed (55) hide show
  1. package/CHANGELOG.md +109 -0
  2. package/README.md +4 -4
  3. package/cronli5.min.js +2 -2
  4. package/dist/cronli5.cjs +471 -383
  5. package/dist/cronli5.js +471 -383
  6. package/dist/lang/de.cjs +286 -215
  7. package/dist/lang/de.js +286 -215
  8. package/dist/lang/en.cjs +413 -327
  9. package/dist/lang/en.js +413 -327
  10. package/dist/lang/es.cjs +303 -265
  11. package/dist/lang/es.js +303 -265
  12. package/dist/lang/fi.cjs +311 -266
  13. package/dist/lang/fi.js +311 -266
  14. package/dist/lang/zh.cjs +320 -240
  15. package/dist/lang/zh.js +320 -240
  16. package/package.json +6 -6
  17. package/src/core/analyze.ts +12 -12
  18. package/src/core/cadence.ts +164 -0
  19. package/src/core/index.ts +3 -1
  20. package/src/core/normalize.ts +3 -3
  21. package/src/core/parse.ts +1 -1
  22. package/src/core/{ir.ts → schedule.ts} +17 -18
  23. package/src/core/specs.ts +1 -1
  24. package/src/core/util.ts +3 -165
  25. package/src/core/validate.ts +1 -1
  26. package/src/core/weekday.ts +54 -0
  27. package/src/cronli5.ts +5 -5
  28. package/src/lang/de/index.ts +329 -219
  29. package/src/lang/en/dialects.ts +1 -1
  30. package/src/lang/en/index.ts +521 -372
  31. package/src/lang/es/index.ts +338 -286
  32. package/src/lang/es/notes.md +1 -1
  33. package/src/lang/fi/dialects.ts +1 -1
  34. package/src/lang/fi/index.ts +365 -299
  35. package/src/lang/fi/notes.md +23 -8
  36. package/src/lang/fi/status.json +1 -1
  37. package/src/lang/zh/index.ts +386 -245
  38. package/src/types.ts +6 -6
  39. package/types/core/analyze.d.ts +3 -3
  40. package/types/core/cadence.d.ts +33 -0
  41. package/types/core/index.d.ts +3 -1
  42. package/types/core/normalize.d.ts +1 -1
  43. package/types/core/parse.d.ts +1 -1
  44. package/types/core/{ir.d.ts → schedule.d.ts} +11 -16
  45. package/types/core/specs.d.ts +1 -1
  46. package/types/core/util.d.ts +1 -30
  47. package/types/core/weekday.d.ts +10 -0
  48. package/types/lang/de/index.d.ts +1 -1
  49. package/types/lang/en/dialects.d.ts +1 -1
  50. package/types/lang/en/index.d.ts +1 -1
  51. package/types/lang/es/index.d.ts +1 -1
  52. package/types/lang/fi/dialects.d.ts +1 -1
  53. package/types/lang/fi/index.d.ts +1 -1
  54. package/types/lang/zh/index.d.ts +1 -1
  55. package/types/types.d.ts +5 -5
package/dist/cronli5.js CHANGED
@@ -69,81 +69,9 @@ function isNonNegativeInteger(value) {
69
69
  const digits = /^\d+$/;
70
70
  return digits.test(value);
71
71
  }
72
- function arithmeticStep(values) {
73
- if (values.length < 5) {
74
- return null;
75
- }
76
- const interval = values[1] - values[0];
77
- if (interval < 2) {
78
- return null;
79
- }
80
- for (let i = 2; i < values.length; i += 1) {
81
- if (values[i] - values[i - 1] !== interval) {
82
- return null;
83
- }
84
- }
85
- return { start: values[0], interval, last: values[values.length - 1] };
86
- }
87
- function weekdayDisplayKey(value) {
88
- return value === 0 ? 7 : value;
89
- }
90
- function orderWeekdaysForDisplay(segments) {
91
- const flattened = segments.flatMap(function flat(segment) {
92
- return segment.kind === "step" ? segment.fires.map(function single(value) {
93
- return { kind: "single", value: "" + value };
94
- }) : [segment];
95
- });
96
- function key(segment) {
97
- return segment.kind === "range" ? weekdayDisplayKey(+segment.bounds[0]) : weekdayDisplayKey(+segment.value);
98
- }
99
- return flattened.map(function index(segment, position) {
100
- return [segment, position];
101
- }).sort(function byDisplayKey(a, b) {
102
- return key(a[0]) - key(b[0]) || a[1] - b[1];
103
- }).map(function unwrap(pair) {
104
- return pair[0];
105
- });
106
- }
107
72
  function toFieldNumber(token, numberMap) {
108
73
  return isNonNegativeInteger(token) ? +token : numberMap[token.toUpperCase()];
109
74
  }
110
- function segmentsOf(ir, field) {
111
- return ir.analyses.segments[field] ?? [];
112
- }
113
- function stepSegment(ir, field) {
114
- return segmentsOf(ir, field)[0];
115
- }
116
- function singleValues(segments) {
117
- const values = [];
118
- for (const segment of segments) {
119
- if (segment.kind !== "single") {
120
- return null;
121
- }
122
- values.push(+segment.value);
123
- }
124
- return values;
125
- }
126
- function offsetCleanStride(stride) {
127
- return stride.start < stride.interval && 24 % stride.interval === 0;
128
- }
129
- function hourListStride(values) {
130
- if (values.length < 2) {
131
- return null;
132
- }
133
- const interval = values[1] - values[0];
134
- if (interval < 2) {
135
- return null;
136
- }
137
- for (let i = 2; i < values.length; i += 1) {
138
- if (values[i] - values[i - 1] !== interval) {
139
- return null;
140
- }
141
- }
142
- if (values[0] !== 0 && values.length < 5) {
143
- return null;
144
- }
145
- return { interval, last: values[values.length - 1], start: values[0] };
146
- }
147
75
 
148
76
  // src/core/validate.ts
149
77
  function validateCronPattern(cronPattern) {
@@ -273,7 +201,7 @@ function normalizeField(value, field, spec) {
273
201
  const cycle = timeFieldCycle[field];
274
202
  const segments = stringValue.split(",").map(function canonical(segment) {
275
203
  return canonicalizeTokens(collapseFullSpanRange(
276
- enumerateNonUniformStep(
204
+ enumerateIfNonUniform(
277
205
  collapseFullSpanStep(
278
206
  collapseDegenerateRange(
279
207
  collapseOnceStep(collapseUnitStep(segment, spec), spec),
@@ -337,7 +265,7 @@ function collapseOnceStep(segment, spec) {
337
265
  }
338
266
  return start === "*" ? "" + spec.min : start;
339
267
  }
340
- function enumerateNonUniformStep(segment, spec, cycle) {
268
+ function enumerateIfNonUniform(segment, spec, cycle) {
341
269
  const parts = segment.split("/");
342
270
  if (typeof cycle !== "number" || parts.length !== 2 || includes(parts[0], "-")) {
343
271
  return segment;
@@ -476,6 +404,93 @@ function expandMacro(cronString) {
476
404
  throw new Error("`cronli5` does not recognize the macro `" + trimmed + "`.");
477
405
  }
478
406
 
407
+ // src/core/weekday.ts
408
+ function weekdayDisplayKey(value) {
409
+ return value === 0 ? 7 : value;
410
+ }
411
+ function orderWeekdaysForDisplay(segments) {
412
+ const flattened = segments.flatMap(function flat(segment) {
413
+ return segment.kind === "step" ? segment.fires.map(function single(value) {
414
+ return { kind: "single", value: "" + value };
415
+ }) : [segment];
416
+ });
417
+ function key(segment) {
418
+ return segment.kind === "range" ? weekdayDisplayKey(+segment.bounds[0]) : weekdayDisplayKey(+segment.value);
419
+ }
420
+ return flattened.map(function index(segment, position) {
421
+ return [segment, position];
422
+ }).sort(function byDisplayKey(a, b) {
423
+ return key(a[0]) - key(b[0]) || a[1] - b[1];
424
+ }).map(function unwrap(pair) {
425
+ return pair[0];
426
+ });
427
+ }
428
+
429
+ // src/core/cadence.ts
430
+ function arithmeticStep(values) {
431
+ if (values.length < 5) {
432
+ return null;
433
+ }
434
+ const interval = values[1] - values[0];
435
+ if (interval < 2) {
436
+ return null;
437
+ }
438
+ for (let i = 2; i < values.length; i += 1) {
439
+ if (values[i] - values[i - 1] !== interval) {
440
+ return null;
441
+ }
442
+ }
443
+ return { start: values[0], interval, last: values[values.length - 1] };
444
+ }
445
+ function segmentsOf(schedule, field) {
446
+ return schedule.analyses.segments[field] ?? [];
447
+ }
448
+ function stepSegment(schedule, field) {
449
+ return segmentsOf(schedule, field)[0];
450
+ }
451
+ function singleValues(segments) {
452
+ const values = [];
453
+ for (const segment of segments) {
454
+ if (segment.kind !== "single") {
455
+ return null;
456
+ }
457
+ values.push(+segment.value);
458
+ }
459
+ return values;
460
+ }
461
+ function offsetCleanStride(stride) {
462
+ return stride.start < stride.interval && 24 % stride.interval === 0;
463
+ }
464
+ function renderStride(spec, parts) {
465
+ const { start, interval, cycle } = spec;
466
+ const tiles = cycle % interval === 0;
467
+ if (start === 0 && tiles) {
468
+ return parts.bare();
469
+ }
470
+ if (start < interval && tiles) {
471
+ return parts.offset();
472
+ }
473
+ return parts.bounded();
474
+ }
475
+ function hourListStride(values) {
476
+ if (values.length < 2) {
477
+ return null;
478
+ }
479
+ const interval = values[1] - values[0];
480
+ if (interval < 2) {
481
+ return null;
482
+ }
483
+ for (let i = 2; i < values.length; i += 1) {
484
+ if (values[i] - values[i - 1] !== interval) {
485
+ return null;
486
+ }
487
+ }
488
+ if (values[0] !== 0 && values.length < 5) {
489
+ return null;
490
+ }
491
+ return { interval, last: values[values.length - 1], start: values[0] };
492
+ }
493
+
479
494
  // src/core/shapes.ts
480
495
  function isSingleValue(field) {
481
496
  return field !== "*" && !includes(field, ",") && !includes(field, "-") && !includes(field, "/");
@@ -630,11 +645,11 @@ function analyze(pattern) {
630
645
  minuteSpan: minuteSpan(pattern.minute),
631
646
  segments
632
647
  };
633
- const content = { analyses, pattern, shapes };
634
- return { ...content, plan: selectPlan(content) };
648
+ const facts = { analyses, pattern, shapes };
649
+ return { ...facts, plan: selectPlan(facts) };
635
650
  }
636
- function selectPlan(content) {
637
- const { analyses, pattern, shapes } = content;
651
+ function selectPlan(facts) {
652
+ const { analyses, pattern, shapes } = facts;
638
653
  if (pattern.second !== "0") {
639
654
  const seconds = planSeconds(pattern, shapes, analyses);
640
655
  if (seconds) {
@@ -978,72 +993,134 @@ function normalizeOptions(options) {
978
993
  years: !!options.years
979
994
  };
980
995
  }
981
- function describe(ir, opts) {
982
- const body = confinement(ir, opts) ?? render(ir, ir.plan, opts);
983
- const lead = isDayUnion(ir, opts) ? dayUnionMonthLead(ir, opts) : "";
984
- return applyYear(lead + body, ir, opts);
996
+ function describe(schedule, opts) {
997
+ const dense = denseCadence(schedule, opts);
998
+ if (dense !== null) {
999
+ return applyYear(dense, schedule, opts);
1000
+ }
1001
+ const body = confinement(schedule, opts) ?? render(schedule, schedule.plan, opts);
1002
+ const lead = isDayUnion(schedule, opts) ? dayUnionMonthLead(schedule, opts) : "";
1003
+ return applyYear(lead + body, schedule, opts);
985
1004
  }
986
- function render(ir, plan, opts) {
1005
+ function render(schedule, plan, opts) {
987
1006
  const renderer = renderers[plan.kind];
988
- return renderer(ir, plan, opts);
1007
+ return renderer(schedule, plan, opts);
989
1008
  }
990
- function renderEverySecond(ir, plan, opts) {
991
- return "every second" + trailingQualifier(ir, opts);
1009
+ function isCadenceShape(shape) {
1010
+ return shape === "step" || shape === "range" || shape === "list";
992
1011
  }
993
- function renderStandaloneSeconds(ir, plan, opts) {
994
- return secondsLeadClause(ir, opts) + trailingQualifier(ir, opts);
1012
+ function isDenseCadence(schedule, opts) {
1013
+ if (!opts.style.untilWindow || opts.short || schedule.plan.kind !== "composeSeconds" || schedule.plan.rest.kind === "clockTimes" || isDayUnion(schedule, opts)) {
1014
+ return false;
1015
+ }
1016
+ const { shapes } = schedule;
1017
+ return isCadenceShape(shapes.second) && isCadenceShape(shapes.minute) && isCadenceShape(shapes.hour);
995
1018
  }
996
- function renderSecondPastMinute(ir, plan, opts) {
997
- const secondField = ir.pattern.second;
998
- return getNumber(secondField, opts) + " " + pluralize(secondField, "second") + " past the minute, every minute" + trailingQualifier(ir, opts);
1019
+ function denseHourFragment(schedule, opts) {
1020
+ const stride = hourStride(schedule);
1021
+ if (stride) {
1022
+ return hourStrideCadence(stride, opts);
1023
+ }
1024
+ if (schedule.shapes.hour === "range") {
1025
+ const segment = segmentsOf(schedule, "hour").find(function range(part) {
1026
+ return part.kind === "range";
1027
+ });
1028
+ return rangeWindow({
1029
+ continuous: false,
1030
+ from: +segment.bounds[0],
1031
+ throughMinute: 0,
1032
+ to: +segment.bounds[1]
1033
+ }, opts);
1034
+ }
1035
+ return "during the " + hourSegmentTimes(schedule, { minute: 0, second: null }, false, opts) + " hours";
999
1036
  }
1000
- function renderSecondsWithinMinute(ir, plan, opts) {
1001
- const minuteField = ir.pattern.minute;
1037
+ function denseMinuteFragment(schedule, opts) {
1038
+ if (schedule.shapes.minute === "step") {
1039
+ return stepCycle60(stepSegment(schedule, "minute"), "minute", "hour", opts);
1040
+ }
1041
+ if (schedule.shapes.minute === "range") {
1042
+ return minuteRangeLead(schedule.pattern.minute, opts);
1043
+ }
1044
+ return strideFromSegments(
1045
+ segmentsOf(schedule, "minute"),
1046
+ "minute",
1047
+ "hour",
1048
+ opts
1049
+ ) ?? listPastThe(
1050
+ segmentWords(segmentsOf(schedule, "minute"), opts),
1051
+ "minute",
1052
+ "hour",
1053
+ opts
1054
+ );
1055
+ }
1056
+ function denseCadence(schedule, opts) {
1057
+ if (!isDenseCadence(schedule, opts)) {
1058
+ return null;
1059
+ }
1060
+ const hour = denseHourFragment(schedule, opts);
1061
+ const minute = denseMinuteFragment(schedule, opts);
1062
+ const second = secondsClause(schedule, "minute", opts);
1063
+ const nested = hour + ", " + minute + ", and within each of those minutes, " + second;
1064
+ const anchor = trailingQualifier(schedule, opts).trim();
1065
+ return anchor ? anchor + ", " + nested : nested;
1066
+ }
1067
+ function renderEverySecond(schedule, plan, opts) {
1068
+ return "every second" + trailingQualifier(schedule, opts);
1069
+ }
1070
+ function renderStandaloneSeconds(schedule, plan, opts) {
1071
+ return secondsLeadClause(schedule, opts) + trailingQualifier(schedule, opts);
1072
+ }
1073
+ function renderSecondPastMinute(schedule, plan, opts) {
1074
+ const secondField = schedule.pattern.second;
1075
+ return getNumber(secondField, opts) + " " + pluralize(secondField, "second") + " past the minute, every minute" + trailingQualifier(schedule, opts);
1076
+ }
1077
+ function renderSecondsWithinMinute(schedule, plan, opts) {
1078
+ const minuteField = schedule.pattern.minute;
1002
1079
  const minuteWord = getNumber(minuteField, opts);
1003
1080
  const minuteUnit = pluralize(minuteField, "minute");
1004
1081
  if (plan.singleSecond) {
1005
- const secondField = ir.pattern.second;
1006
- return minuteWord + " " + minuteUnit + " and " + getNumber(secondField, opts) + " " + pluralize(secondField, "second") + " past the hour, every hour" + trailingQualifier(ir, opts);
1082
+ const secondField = schedule.pattern.second;
1083
+ return minuteWord + " " + minuteUnit + " and " + getNumber(secondField, opts) + " " + pluralize(secondField, "second") + " past the hour, every hour" + trailingQualifier(schedule, opts);
1007
1084
  }
1008
- return secondsLeadClause(ir, opts) + ", " + minuteWord + " " + minuteUnit + " past the hour, every hour" + trailingQualifier(ir, opts);
1085
+ return secondsLeadClause(schedule, opts) + ", " + minuteWord + " " + minuteUnit + " past the hour, every hour" + trailingQualifier(schedule, opts);
1009
1086
  }
1010
- function composeHourCadence(ir, plan, opts) {
1087
+ function composeHourCadence(schedule, plan, opts) {
1011
1088
  const clockRest = plan.rest.kind === "clockTimes" || plan.rest.kind === "compactClockTimes";
1012
- if (!clockRest || ir.shapes.minute !== "single") {
1089
+ if (!clockRest || schedule.shapes.minute !== "single") {
1013
1090
  return null;
1014
1091
  }
1015
- const minute = +ir.pattern.minute;
1016
- return hourCadence(ir, minute, opts) ?? hourRangeCadence(ir, minute, opts);
1092
+ const minute = +schedule.pattern.minute;
1093
+ return hourCadence(schedule, minute, opts) ?? hourRangeCadence(schedule, minute, opts);
1017
1094
  }
1018
- function clockTimesConfinement(ir, rest, opts) {
1019
- if (+rest.times[0].minute === 0 && ir.shapes.minute === "single") {
1020
- return secondsLeadClause(ir, opts) + " for one minute at " + durationHours(ir, rest, opts);
1095
+ function clockTimesConfinement(schedule, rest, opts) {
1096
+ if (+rest.times[0].minute === 0 && schedule.shapes.minute === "single") {
1097
+ return secondsLeadClause(schedule, opts) + " for one minute at " + durationHours(schedule, rest, opts);
1021
1098
  }
1022
- return secondsLeadClause(ir, opts) + " of " + clockTimesOf(ir, rest, opts);
1099
+ return secondsLeadClause(schedule, opts) + " of " + clockTimesOf(schedule, rest, opts);
1023
1100
  }
1024
- function renderComposeSeconds(ir, plan, opts) {
1025
- const cadence = composeHourCadence(ir, plan, opts);
1101
+ function renderComposeSeconds(schedule, plan, opts) {
1102
+ const cadence = composeHourCadence(schedule, plan, opts);
1026
1103
  if (cadence !== null) {
1027
1104
  return cadence;
1028
1105
  }
1029
- if (plan.rest.kind === "clockTimes" && (ir.shapes.second === "wildcard" || ir.shapes.second === "step")) {
1030
- return clockTimesConfinement(ir, plan.rest, opts);
1106
+ if (plan.rest.kind === "clockTimes" && (schedule.shapes.second === "wildcard" || schedule.shapes.second === "step")) {
1107
+ return clockTimesConfinement(schedule, plan.rest, opts);
1031
1108
  }
1032
- if (ir.shapes.second === "wildcard" && plan.rest.kind === "minuteFrequency" && plan.rest.hours.kind === "none" && ir.pattern.minute === "*/2") {
1033
- return "every second of every other minute" + trailingQualifier(ir, opts);
1109
+ if (schedule.shapes.second === "wildcard" && plan.rest.kind === "minuteFrequency" && plan.rest.hours.kind === "none" && schedule.pattern.minute === "*/2") {
1110
+ return "every second of every other minute" + trailingQualifier(schedule, opts);
1034
1111
  }
1035
- const restOwnsLead = plan.rest.kind === "compactClockTimes" && ir.analyses.clockSecond;
1036
- const lead = restOwnsLead ? "" : secondsLeadClause(ir, opts) + ", ";
1037
- return lead + render(ir, plan.rest, opts);
1112
+ const restOwnsLead = plan.rest.kind === "compactClockTimes" && schedule.analyses.clockSecond;
1113
+ const lead = restOwnsLead ? "" : secondsLeadClause(schedule, opts) + ", ";
1114
+ return lead + render(schedule, plan.rest, opts);
1038
1115
  }
1039
- function durationHours(ir, plan, opts) {
1116
+ function durationHours(schedule, plan, opts) {
1040
1117
  const hours = plan.times.map(function clock(time) {
1041
1118
  return getTime({ hour: time.hour, minute: 0 }, opts);
1042
1119
  });
1043
- const trail = dayQualifier(ir, leadingWords, opts);
1120
+ const trail = dayQualifier(schedule, leadingWords, opts);
1044
1121
  return joinList(hours, opts) + (trail && ", " + trail);
1045
1122
  }
1046
- function clockTimesOf(ir, plan, opts) {
1123
+ function clockTimesOf(schedule, plan, opts) {
1047
1124
  const times = plan.times.map(function clock(time) {
1048
1125
  return getTime({
1049
1126
  hour: time.hour,
@@ -1052,21 +1129,21 @@ function clockTimesOf(ir, plan, opts) {
1052
1129
  explicit: true
1053
1130
  }, opts);
1054
1131
  });
1055
- const trail = dayQualifier(ir, leadingWords, opts);
1132
+ const trail = dayQualifier(schedule, leadingWords, opts);
1056
1133
  return joinList(times, opts) + (trail && ", " + trail);
1057
1134
  }
1058
- function secondsLeadClause(ir, opts) {
1059
- return secondsClause(ir, "minute", opts);
1135
+ function secondsLeadClause(schedule, opts) {
1136
+ return secondsClause(schedule, "minute", opts);
1060
1137
  }
1061
- function secondsClause(ir, anchor, opts) {
1062
- const secondField = ir.pattern.second;
1063
- const shape = ir.shapes.second;
1138
+ function secondsClause(schedule, anchor, opts) {
1139
+ const secondField = schedule.pattern.second;
1140
+ const shape = schedule.shapes.second;
1064
1141
  if (secondField === "*") {
1065
1142
  return "every second";
1066
1143
  }
1067
1144
  if (shape === "step") {
1068
1145
  return stepCycle60(
1069
- stepSegment(ir, "second"),
1146
+ stepSegment(schedule, "second"),
1070
1147
  "second",
1071
1148
  anchor,
1072
1149
  opts
@@ -1081,44 +1158,44 @@ function secondsClause(ir, anchor, opts) {
1081
1158
  return "at " + getNumber(secondField, opts) + " " + pluralize(secondField, "second") + " past the " + anchor;
1082
1159
  }
1083
1160
  return strideFromSegments(
1084
- segmentsOf(ir, "second"),
1161
+ segmentsOf(schedule, "second"),
1085
1162
  "second",
1086
1163
  anchor,
1087
1164
  opts
1088
1165
  ) ?? listPastThe(
1089
- segmentWords(segmentsOf(ir, "second"), opts),
1166
+ segmentWords(segmentsOf(schedule, "second"), opts),
1090
1167
  "second",
1091
1168
  anchor,
1092
1169
  opts
1093
1170
  );
1094
1171
  }
1095
- function renderEveryMinute(ir, plan, opts) {
1096
- return "every minute" + trailingQualifier(ir, opts);
1172
+ function renderEveryMinute(schedule, plan, opts) {
1173
+ return "every minute" + trailingQualifier(schedule, opts);
1097
1174
  }
1098
- function renderSingleMinute(ir, plan, opts) {
1099
- const minuteField = ir.pattern.minute;
1100
- return getNumber(minuteField, opts) + " " + pluralize(minuteField, "minute") + " past the hour, every hour" + trailingQualifier(ir, opts);
1175
+ function renderSingleMinute(schedule, plan, opts) {
1176
+ const minuteField = schedule.pattern.minute;
1177
+ return getNumber(minuteField, opts) + " " + pluralize(minuteField, "minute") + " past the hour, every hour" + trailingQualifier(schedule, opts);
1101
1178
  }
1102
- function renderRangeOfMinutes(ir, plan, opts) {
1103
- return minuteRangeLead(ir.pattern.minute, opts) + trailingQualifier(ir, opts);
1179
+ function renderRangeOfMinutes(schedule, plan, opts) {
1180
+ return minuteRangeLead(schedule.pattern.minute, opts) + trailingQualifier(schedule, opts);
1104
1181
  }
1105
- function renderMultipleMinutes(ir, plan, opts) {
1106
- const stride = strideFromSegments(segmentsOf(ir, "minute"), "minute", "hour", opts);
1182
+ function renderMultipleMinutes(schedule, plan, opts) {
1183
+ const stride = strideFromSegments(segmentsOf(schedule, "minute"), "minute", "hour", opts);
1107
1184
  return (stride ?? listPastThe(segmentWords(
1108
- segmentsOf(ir, "minute"),
1185
+ segmentsOf(schedule, "minute"),
1109
1186
  opts
1110
- ), "minute", "hour", opts)) + trailingQualifier(ir, opts);
1187
+ ), "minute", "hour", opts)) + trailingQualifier(schedule, opts);
1111
1188
  }
1112
- function renderMinuteFrequency(ir, plan, opts) {
1189
+ function renderMinuteFrequency(schedule, plan, opts) {
1113
1190
  let phrase = stepCycle60(
1114
- stepSegment(ir, "minute"),
1191
+ stepSegment(schedule, "minute"),
1115
1192
  "minute",
1116
1193
  "hour",
1117
1194
  opts
1118
1195
  );
1119
1196
  if (plan.hours.kind === "during") {
1120
- const cadence = unevenHourCadence(ir, opts);
1121
- phrase += cadence ? ", " + cadence : " during the " + hourTimesFromPlan(ir, plan.hours.times, false, opts) + " hours";
1197
+ const cadence = unevenHourCadence(schedule, opts);
1198
+ phrase += cadence ? ", " + cadence : " during the " + hourTimesFromPlan(schedule, plan.hours.times, false, opts) + " hours";
1122
1199
  } else if (plan.hours.kind === "window") {
1123
1200
  phrase += " " + rangeWindow({
1124
1201
  continuous: false,
@@ -1127,45 +1204,50 @@ function renderMinuteFrequency(ir, plan, opts) {
1127
1204
  to: plan.hours.to
1128
1205
  }, opts);
1129
1206
  } else if (plan.hours.kind === "step") {
1130
- phrase += " " + everyNthHour(stepSegment(ir, "hour"), opts);
1207
+ phrase += " " + everyNthHour(stepSegment(schedule, "hour"), opts);
1131
1208
  }
1132
- return phrase + trailingQualifier(ir, opts);
1209
+ return phrase + trailingQualifier(schedule, opts);
1133
1210
  }
1134
- function renderMinuteSpanInHour(ir, plan, opts) {
1135
- if (ir.pattern.minute === "*") {
1136
- return "every minute of the " + getTime({ hour: plan.hour, minute: 0 }, opts) + " hour" + trailingQualifier(ir, opts);
1211
+ function renderMinuteSpanInHour(schedule, plan, opts) {
1212
+ if (schedule.pattern.minute === "*") {
1213
+ return "every minute of the " + getTime({ hour: plan.hour, minute: 0 }, opts) + " hour" + trailingQualifier(schedule, opts);
1137
1214
  }
1138
- return "every minute from " + getTime({ hour: plan.hour, minute: plan.span[0] }, opts) + through(opts) + getTime({ hour: plan.hour, minute: plan.span[1] }, opts) + trailingQualifier(ir, opts);
1215
+ return "every minute from " + getTime({ hour: plan.hour, minute: plan.span[0] }, opts) + through(opts) + getTime({ hour: plan.hour, minute: plan.span[1] }, opts) + trailingQualifier(schedule, opts);
1139
1216
  }
1140
- function renderMinutesAcrossHours(ir, plan, opts) {
1141
- const cadence = unevenHourCadence(ir, opts);
1217
+ function renderMinutesAcrossHours(schedule, plan, opts) {
1218
+ const cadence = unevenHourCadence(schedule, opts);
1142
1219
  if (plan.form === "wildcard") {
1143
1220
  if (cadence !== null) {
1144
- return "every minute, " + cadence + trailingQualifier(ir, opts);
1221
+ return "every minute, " + cadence + trailingQualifier(schedule, opts);
1145
1222
  }
1146
- return "every minute during the " + hourTimesFromPlan(ir, plan.times, false, opts) + " hours" + trailingQualifier(ir, opts);
1223
+ return "every minute during the " + hourTimesFromPlan(schedule, plan.times, false, opts) + " hours" + trailingQualifier(schedule, opts);
1147
1224
  }
1148
1225
  if (plan.form === "range") {
1149
- const lead2 = minuteRangeLead(ir.pattern.minute, opts);
1226
+ const lead2 = minuteRangeLead(schedule.pattern.minute, opts);
1150
1227
  if (cadence !== null) {
1151
- return lead2 + ", " + cadence + trailingQualifier(ir, opts);
1228
+ return lead2 + ", " + cadence + trailingQualifier(schedule, opts);
1152
1229
  }
1153
1230
  if (singleHourFire(plan.times)) {
1154
- return lead2 + ", at " + hourTimesFromPlan(ir, plan.times, true, opts) + trailingQualifier(ir, opts);
1231
+ return lead2 + ", at " + hourTimesFromPlan(schedule, plan.times, true, opts) + trailingQualifier(schedule, opts);
1155
1232
  }
1156
- return lead2 + " during the " + hourTimesFromPlan(ir, plan.times, false, opts) + " hours" + trailingQualifier(ir, opts);
1233
+ return lead2 + " during the " + hourTimesFromPlan(schedule, plan.times, false, opts) + " hours" + trailingQualifier(schedule, opts);
1157
1234
  }
1158
- const lead = strideFromSegments(segmentsOf(ir, "minute"), "minute", "hour", opts) ?? listPastThe(
1159
- segmentWords(segmentsOf(ir, "minute"), opts),
1235
+ const lead = strideFromSegments(
1236
+ segmentsOf(schedule, "minute"),
1237
+ "minute",
1238
+ "hour",
1239
+ opts
1240
+ ) ?? listPastThe(
1241
+ segmentWords(segmentsOf(schedule, "minute"), opts),
1160
1242
  "minute",
1161
1243
  "hour",
1162
1244
  opts
1163
1245
  );
1164
1246
  if (cadence !== null) {
1165
- return lead + ", " + cadence + trailingQualifier(ir, opts);
1247
+ return lead + ", " + cadence + trailingQualifier(schedule, opts);
1166
1248
  }
1167
- const times = hourTimesFromPlan(ir, plan.times, true, opts);
1168
- return lead + ", at " + times + trailingQualifier(ir, opts);
1249
+ const times = hourTimesFromPlan(schedule, plan.times, true, opts);
1250
+ return lead + ", at " + times + trailingQualifier(schedule, opts);
1169
1251
  }
1170
1252
  var stepOrdinals = {
1171
1253
  2: "other",
@@ -1180,60 +1262,65 @@ function everyNthHour(segment, opts) {
1180
1262
  const start = segment.startToken === "*" ? 0 : +segment.startToken;
1181
1263
  return start === 0 ? base : base + " starting at " + getTime({ hour: start, minute: 0 }, opts);
1182
1264
  }
1183
- function renderMinuteSpanAcrossHourStep(ir, plan, opts) {
1184
- const segment = stepSegment(ir, "hour");
1265
+ function renderMinuteSpanAcrossHourStep(schedule, plan, opts) {
1266
+ const segment = stepSegment(schedule, "hour");
1185
1267
  if (plan.form === "wildcard") {
1186
- return "every minute " + everyNthHour(segment, opts) + trailingQualifier(ir, opts);
1268
+ return "every minute " + everyNthHour(segment, opts) + trailingQualifier(schedule, opts);
1187
1269
  }
1188
- const lead = plan.form === "list" ? strideFromSegments(segmentsOf(ir, "minute"), "minute", "hour", opts) ?? listPastThe(
1189
- segmentWords(segmentsOf(ir, "minute"), opts),
1270
+ const lead = plan.form === "list" ? strideFromSegments(
1271
+ segmentsOf(schedule, "minute"),
1272
+ "minute",
1273
+ "hour",
1274
+ opts
1275
+ ) ?? listPastThe(
1276
+ segmentWords(segmentsOf(schedule, "minute"), opts),
1190
1277
  "minute",
1191
1278
  "hour",
1192
1279
  opts
1193
- ) : minuteRangeLead(ir.pattern.minute, opts);
1194
- const cadence = unevenHourCadence(ir, opts);
1195
- return lead + ", " + (cadence ?? stepHours(segment, opts)) + trailingQualifier(ir, opts);
1280
+ ) : minuteRangeLead(schedule.pattern.minute, opts);
1281
+ const cadence = unevenHourCadence(schedule, opts);
1282
+ return lead + ", " + (cadence ?? stepHours(segment, opts)) + trailingQualifier(schedule, opts);
1196
1283
  }
1197
1284
  function minuteRangeLead(minuteField, opts) {
1198
1285
  const bounds = minuteField.split("-");
1199
1286
  const num = seriesNumber();
1200
1287
  return "every minute from " + num(bounds[0]) + through(opts) + num(bounds[1]) + " past the hour";
1201
1288
  }
1202
- function renderEveryHour(ir, plan, opts) {
1203
- return "every hour" + trailingQualifier(ir, opts);
1289
+ function renderEveryHour(schedule, plan, opts) {
1290
+ return "every hour" + trailingQualifier(schedule, opts);
1204
1291
  }
1205
- function renderHourRange(ir, plan, opts) {
1292
+ function renderHourRange(schedule, plan, opts) {
1206
1293
  const window = hourWindow(boundedWindow(plan), opts);
1207
1294
  if (plan.minuteForm === "wildcard") {
1208
- return "every minute " + window + trailingQualifier(ir, opts);
1295
+ return "every minute " + window + trailingQualifier(schedule, opts);
1209
1296
  }
1210
1297
  if (plan.minuteForm === "range") {
1211
- return minuteRangeLead(ir.pattern.minute, opts) + ", " + window + trailingQualifier(ir, opts);
1298
+ return minuteRangeLead(schedule.pattern.minute, opts) + ", " + window + trailingQualifier(schedule, opts);
1212
1299
  }
1213
- return rangeMinuteLead(ir, opts) + " " + window + trailingQualifier(ir, opts);
1300
+ return rangeMinuteLead(schedule, opts) + " " + window + trailingQualifier(schedule, opts);
1214
1301
  }
1215
- function rangeMinuteLead(ir, opts) {
1216
- if (ir.pattern.minute === "0") {
1302
+ function rangeMinuteLead(schedule, opts) {
1303
+ if (schedule.pattern.minute === "0") {
1217
1304
  return "every hour";
1218
1305
  }
1219
1306
  return strideFromSegments(
1220
- segmentsOf(ir, "minute"),
1307
+ segmentsOf(schedule, "minute"),
1221
1308
  "minute",
1222
1309
  "hour",
1223
1310
  opts
1224
1311
  ) ?? listPastThe(
1225
- segmentWords(segmentsOf(ir, "minute"), opts),
1312
+ segmentWords(segmentsOf(schedule, "minute"), opts),
1226
1313
  "minute",
1227
1314
  "hour",
1228
1315
  opts
1229
1316
  );
1230
1317
  }
1231
- function renderHourStep(ir, plan, opts) {
1232
- const cadence = unevenHourCadence(ir, opts);
1318
+ function renderHourStep(schedule, plan, opts) {
1319
+ const cadence = unevenHourCadence(schedule, opts);
1233
1320
  if (cadence !== null) {
1234
- return cadence + trailingQualifier(ir, opts);
1321
+ return cadence + trailingQualifier(schedule, opts);
1235
1322
  }
1236
- return stepHours(stepSegment(ir, "hour"), opts) + trailingQualifier(ir, opts);
1323
+ return stepHours(stepSegment(schedule, "hour"), opts) + trailingQualifier(schedule, opts);
1237
1324
  }
1238
1325
  function boundedWindow(plan) {
1239
1326
  const continuous = plan.minuteForm === "wildcard";
@@ -1256,10 +1343,10 @@ function hourWindow(window, opts) {
1256
1343
  to: window.to
1257
1344
  }, opts);
1258
1345
  }
1259
- function renderClockTimes(ir, plan, opts) {
1260
- if (ir.shapes.minute === "single") {
1261
- const minute = +ir.pattern.minute;
1262
- const cadence = hourCadence(ir, minute, opts) ?? hourRangeCadence(ir, minute, opts);
1346
+ function renderClockTimes(schedule, plan, opts) {
1347
+ if (schedule.shapes.minute === "single") {
1348
+ const minute = +schedule.pattern.minute;
1349
+ const cadence = hourCadence(schedule, minute, opts) ?? hourRangeCadence(schedule, minute, opts);
1263
1350
  if (cadence !== null) {
1264
1351
  return cadence;
1265
1352
  }
@@ -1273,47 +1360,52 @@ function renderClockTimes(ir, plan, opts) {
1273
1360
  plain
1274
1361
  }, opts);
1275
1362
  });
1276
- return interpretDayQualifier(ir, opts) + "at " + joinList(times, opts) + dayUnionTrail(ir, opts);
1363
+ return interpretDayQualifier(schedule, opts) + "at " + joinList(times, opts) + dayUnionTrail(schedule, opts);
1277
1364
  }
1278
- function dayUnionTrail(ir, opts) {
1279
- return isDayUnion(ir, opts) ? dayUnionCondition(ir, opts) : "";
1365
+ function dayUnionTrail(schedule, opts) {
1366
+ return isDayUnion(schedule, opts) ? dayUnionCondition(schedule, opts) : "";
1280
1367
  }
1281
- function renderCompactClockTimes(ir, plan, opts) {
1368
+ function renderCompactClockTimes(schedule, plan, opts) {
1282
1369
  if (plan.fold) {
1283
- const cadence2 = hourCadence(ir, +plan.minute, opts) ?? hourRangeCadence(ir, +plan.minute, opts);
1370
+ const cadence2 = hourCadence(schedule, +plan.minute, opts) ?? hourRangeCadence(schedule, +plan.minute, opts);
1284
1371
  if (cadence2 !== null) {
1285
1372
  return cadence2;
1286
1373
  }
1287
- const hasRange = segmentsOf(ir, "hour").some(function range(segment) {
1374
+ const hasRange = segmentsOf(schedule, "hour").some(function range(segment) {
1288
1375
  return segment.kind === "range";
1289
1376
  });
1290
- if (hasRange && !ir.analyses.clockSecond) {
1291
- return foldedHourWindows(ir, plan, opts) + trailingQualifier(ir, opts);
1377
+ if (hasRange && !schedule.analyses.clockSecond) {
1378
+ return foldedHourWindows(schedule, plan, opts) + trailingQualifier(schedule, opts);
1292
1379
  }
1293
- const fold = { minute: plan.minute, second: ir.analyses.clockSecond };
1294
- return interpretDayQualifier(ir, opts) + "at " + hourSegmentTimes(ir, fold, true, opts) + dayUnionTrail(ir, opts);
1380
+ const fold = { minute: plan.minute, second: schedule.analyses.clockSecond };
1381
+ return interpretDayQualifier(schedule, opts) + "at " + hourSegmentTimes(schedule, fold, true, opts) + dayUnionTrail(schedule, opts);
1295
1382
  }
1296
1383
  const minuteLead = (
1297
1384
  // The non-fold branch is a minute list, which has segments. An
1298
1385
  // offset/uneven step enumerated to that list reads as a stride.
1299
- strideFromSegments(segmentsOf(ir, "minute"), "minute", "hour", opts) ?? listPastThe(
1300
- segmentWords(segmentsOf(ir, "minute"), opts),
1386
+ strideFromSegments(
1387
+ segmentsOf(schedule, "minute"),
1388
+ "minute",
1389
+ "hour",
1390
+ opts
1391
+ ) ?? listPastThe(
1392
+ segmentWords(segmentsOf(schedule, "minute"), opts),
1301
1393
  "minute",
1302
1394
  "hour",
1303
1395
  opts
1304
1396
  )
1305
1397
  );
1306
- const cadence = unevenHourCadence(ir, opts);
1307
- const phrase = cadence ? minuteLead + ", " + cadence + trailingQualifier(ir, opts) : minuteLead + ", at " + hourSegmentTimes(ir, { minute: 0, second: null }, true, opts) + trailingQualifier(ir, opts);
1308
- return ir.analyses.clockSecond ? secondsLeadClause(ir, opts) + ", " + phrase : phrase;
1398
+ const cadence = unevenHourCadence(schedule, opts);
1399
+ const phrase = cadence ? minuteLead + ", " + cadence + trailingQualifier(schedule, opts) : minuteLead + ", at " + hourSegmentTimes(schedule, { minute: 0, second: null }, true, opts) + trailingQualifier(schedule, opts);
1400
+ return schedule.analyses.clockSecond ? secondsLeadClause(schedule, opts) + ", " + phrase : phrase;
1309
1401
  }
1310
- function foldedHourWindows(ir, plan, opts) {
1402
+ function foldedHourWindows(schedule, plan, opts) {
1311
1403
  const minute = plan.minute;
1312
1404
  const windows = [];
1313
- const times = collectHourOutliers(ir).map(function time(hour) {
1405
+ const times = collectHourOutliers(schedule).map(function time(hour) {
1314
1406
  return getTime({ hour, minute }, opts);
1315
1407
  });
1316
- segmentsOf(ir, "hour").forEach(function classify(segment) {
1408
+ segmentsOf(schedule, "hour").forEach(function classify(segment) {
1317
1409
  if (segment.kind === "range") {
1318
1410
  windows.push(rangeWindow({
1319
1411
  continuous: false,
@@ -1323,12 +1415,12 @@ function foldedHourWindows(ir, plan, opts) {
1323
1415
  }, opts));
1324
1416
  }
1325
1417
  });
1326
- const phrase = rangeMinuteLead(ir, opts) + " " + joinList(windows, opts);
1418
+ const phrase = rangeMinuteLead(schedule, opts) + " " + joinList(windows, opts);
1327
1419
  return phrase + outlierTail(times, opts);
1328
1420
  }
1329
- function collectHourOutliers(ir) {
1421
+ function collectHourOutliers(schedule) {
1330
1422
  const hours = [];
1331
- segmentsOf(ir, "hour").forEach(function classify(segment) {
1423
+ segmentsOf(schedule, "hour").forEach(function classify(segment) {
1332
1424
  if (segment.kind === "step") {
1333
1425
  hours.push(...segment.fires);
1334
1426
  } else if (segment.kind !== "range") {
@@ -1346,16 +1438,16 @@ function outlierTail(times, opts) {
1346
1438
  function isCadenceField(token) {
1347
1439
  return token === "*" || token.startsWith("*/") && token.indexOf("-") === -1;
1348
1440
  }
1349
- function leadingCadence(ir, opts) {
1350
- const { second, minute } = ir.pattern;
1441
+ function leadingCadence(schedule, opts) {
1442
+ const { second, minute } = schedule.pattern;
1351
1443
  if (isCadenceField(second)) {
1352
- return { secondLead: true, text: secondsClause(ir, "minute", opts) };
1444
+ return { secondLead: true, text: secondsClause(schedule, "minute", opts) };
1353
1445
  }
1354
1446
  if (second === "0" && isCadenceField(minute)) {
1355
1447
  const text = minute === "*" ? "every minute" : (
1356
1448
  // A clean minute step's first segment is a step segment.
1357
1449
  stepCycle60(
1358
- stepSegment(ir, "minute"),
1450
+ stepSegment(schedule, "minute"),
1359
1451
  "minute",
1360
1452
  "hour",
1361
1453
  opts
@@ -1365,19 +1457,19 @@ function leadingCadence(ir, opts) {
1365
1457
  }
1366
1458
  return null;
1367
1459
  }
1368
- function minuteConfinement(ir, opts) {
1369
- const minute = ir.pattern.minute;
1460
+ function minuteConfinement(schedule, opts) {
1461
+ const minute = schedule.pattern.minute;
1370
1462
  if (minute === "*") {
1371
1463
  return "";
1372
1464
  }
1373
1465
  if (isCadenceField(minute)) {
1374
1466
  return " of every other minute";
1375
1467
  }
1376
- const segments = segmentsOf(ir, "minute");
1377
- if (ir.shapes.minute === "single") {
1468
+ const segments = segmentsOf(schedule, "minute");
1469
+ if (schedule.shapes.minute === "single") {
1378
1470
  return " during minute :" + pad(minute);
1379
1471
  }
1380
- if (ir.shapes.minute === "range") {
1472
+ if (schedule.shapes.minute === "range") {
1381
1473
  const bounds = minute.split("-");
1382
1474
  return " during minutes :" + pad(bounds[0]) + through(opts) + ":" + pad(bounds[1]);
1383
1475
  }
@@ -1386,64 +1478,61 @@ function minuteConfinement(ir, opts) {
1386
1478
  });
1387
1479
  return " during minutes " + joinList(values, opts);
1388
1480
  }
1389
- function hourConfinement(ir, opts) {
1390
- const hour = ir.pattern.hour;
1481
+ function hourConfinement(schedule, opts) {
1482
+ const hour = schedule.pattern.hour;
1391
1483
  if (hour === "*") {
1392
- const minutePinned = ir.pattern.minute !== "*" && !isCadenceField(ir.pattern.minute);
1484
+ const minutePinned = schedule.pattern.minute !== "*" && !isCadenceField(schedule.pattern.minute);
1393
1485
  return minutePinned ? " of every hour" : "";
1394
1486
  }
1395
1487
  if (isCadenceField(hour)) {
1396
1488
  return hour === "*/2" ? " of every other hour" : "";
1397
1489
  }
1398
- if (ir.shapes.hour === "single") {
1490
+ if (schedule.shapes.hour === "single") {
1399
1491
  const h = +hour;
1400
- if (ir.shapes.minute === "step") {
1492
+ if (schedule.shapes.minute === "step") {
1401
1493
  return " from " + getTime({ hour: h, minute: 0 }, opts) + " until " + getTime({ hour: (h + 1) % 24, minute: 0 }, opts);
1402
1494
  }
1403
- if (ir.pattern.minute !== "*" && !isCadenceField(ir.pattern.minute)) {
1495
+ if (schedule.pattern.minute !== "*" && !isCadenceField(schedule.pattern.minute)) {
1404
1496
  return " at " + getTime({ hour: h, minute: 0 }, opts);
1405
1497
  }
1406
1498
  return " of the " + getTime({ hour: h, minute: 0 }, opts) + " hour";
1407
1499
  }
1408
- if (ir.shapes.hour === "range") {
1500
+ if (schedule.shapes.hour === "range") {
1409
1501
  const bounds = hour.split("-");
1410
1502
  return " " + rangeWindow({
1411
- continuous: ir.pattern.minute === "*",
1503
+ continuous: schedule.pattern.minute === "*",
1412
1504
  from: +bounds[0],
1413
1505
  throughMinute: 0,
1414
1506
  to: +bounds[1]
1415
1507
  }, opts);
1416
1508
  }
1417
- return " during the " + hourSegmentTimes(ir, { minute: 0, second: null }, false, opts) + " hours";
1418
- }
1419
- function isContiguousHourRange(ir) {
1420
- return ir.shapes.hour === "range";
1509
+ return " during the " + hourSegmentTimes(schedule, { minute: 0, second: null }, false, opts) + " hours";
1421
1510
  }
1422
- function confinableHour(ir) {
1423
- if (ir.shapes.hour !== "step") {
1511
+ function confinableHour(schedule) {
1512
+ if (schedule.shapes.hour !== "step") {
1424
1513
  return true;
1425
1514
  }
1426
- const segment = stepSegment(ir, "hour");
1427
- return ir.pattern.hour === "*/2" || segment.startToken.indexOf("-") !== -1;
1515
+ const segment = stepSegment(schedule, "hour");
1516
+ return schedule.pattern.hour === "*/2" || segment.startToken.indexOf("-") !== -1;
1428
1517
  }
1429
- function isMinuteStride(ir) {
1430
- if (ir.shapes.minute !== "list") {
1518
+ function isMinuteStride(schedule) {
1519
+ if (schedule.shapes.minute !== "list") {
1431
1520
  return false;
1432
1521
  }
1433
- const values = singleValues(segmentsOf(ir, "minute"));
1522
+ const values = singleValues(segmentsOf(schedule, "minute"));
1434
1523
  return values !== null && arithmeticStep(values) !== null;
1435
1524
  }
1436
- function confinementEligible(ir, lead) {
1437
- const { minute, hour } = ir.pattern;
1525
+ function confinementEligible(schedule, lead) {
1526
+ const { minute, hour } = schedule.pattern;
1438
1527
  const minuteStep = isCadenceField(minute) && minute !== "*";
1439
- if (!confinableHour(ir)) {
1528
+ if (!confinableHour(schedule)) {
1440
1529
  return false;
1441
1530
  }
1442
1531
  if (lead.secondLead) {
1443
1532
  if (minuteStep) {
1444
- return minute === "*/2" && !isContiguousHourRange(ir);
1533
+ return minute === "*/2" && schedule.shapes.hour !== "range";
1445
1534
  }
1446
- if (isMinuteStride(ir) || ir.shapes.minute === "list" && ir.shapes.hour === "list") {
1535
+ if (isMinuteStride(schedule) || schedule.shapes.minute === "list" && schedule.shapes.hour === "list") {
1447
1536
  return false;
1448
1537
  }
1449
1538
  return true;
@@ -1451,21 +1540,21 @@ function confinementEligible(ir, lead) {
1451
1540
  if (hour === "*/2") {
1452
1541
  return true;
1453
1542
  }
1454
- return ir.shapes.hour === "single" && minute === "*/2";
1543
+ return schedule.shapes.hour === "single" && minute === "*/2";
1455
1544
  }
1456
- function confinement(ir, opts) {
1545
+ function confinement(schedule, opts) {
1457
1546
  if (!opts.style.untilWindow || opts.short) {
1458
1547
  return null;
1459
1548
  }
1460
- if (ir.pattern.minute === "*" && ir.pattern.hour === "*") {
1549
+ if (schedule.pattern.minute === "*" && schedule.pattern.hour === "*") {
1461
1550
  return null;
1462
1551
  }
1463
- const lead = leadingCadence(ir, opts);
1464
- if (!lead || !confinementEligible(ir, lead)) {
1552
+ const lead = leadingCadence(schedule, opts);
1553
+ if (!lead || !confinementEligible(schedule, lead)) {
1465
1554
  return null;
1466
1555
  }
1467
- const minutePart = lead.secondLead ? minuteConfinement(ir, opts) : "";
1468
- return lead.text + minutePart + hourConfinement(ir, opts) + trailingQualifier(ir, opts);
1556
+ const minutePart = lead.secondLead ? minuteConfinement(schedule, opts) : "";
1557
+ return lead.text + minutePart + hourConfinement(schedule, opts) + trailingQualifier(schedule, opts);
1469
1558
  }
1470
1559
  var renderers = {
1471
1560
  clockTimes: renderClockTimes,
@@ -1487,23 +1576,25 @@ var renderers = {
1487
1576
  singleMinute: renderSingleMinute,
1488
1577
  standaloneSeconds: renderStandaloneSeconds
1489
1578
  };
1490
- function renderStride(stride, opts) {
1579
+ function renderStride2(stride, opts) {
1491
1580
  const { interval, start, last, cycle, unit, anchor } = stride;
1492
1581
  const cadence = "every " + getNumber(interval, opts) + " " + unit + "s";
1493
- const tiles = cycle % interval === 0;
1494
- if (start === 0 && tiles) {
1495
- return cadence;
1496
- }
1497
- if (start < interval && tiles) {
1498
- return cadence + " from " + getNumber(start, opts) + " " + pluralize(start, unit) + " past the " + anchor;
1499
- }
1500
- const num = seriesNumber();
1501
- return cadence + " from " + num(start) + through(opts) + num(last) + " " + pluralize(last, unit) + " past the " + anchor;
1582
+ return renderStride({ start, interval, cycle }, {
1583
+ bare: () => cadence,
1584
+ // A clean wrap from a non-zero offset: name the start, no endpoint.
1585
+ offset: () => cadence + " from " + getNumber(start, opts) + " " + pluralize(start, unit) + " past the " + anchor,
1586
+ // A bounded, non-wrapping set: pin both endpoints. Each bound is a value,
1587
+ // so it reads as a digit, matching the range idiom ("from 0 through 30").
1588
+ bounded: () => {
1589
+ const num = seriesNumber();
1590
+ return cadence + " from " + num(start) + through(opts) + num(last) + " " + pluralize(last, unit) + " past the " + anchor;
1591
+ }
1592
+ });
1502
1593
  }
1503
1594
  function strideFromSegments(segments, unit, anchor, opts) {
1504
1595
  const values = singleValues(segments);
1505
1596
  const step = values && arithmeticStep(values);
1506
- return step ? renderStride({ ...step, cycle: 60, unit, anchor }, opts) : null;
1597
+ return step ? renderStride2({ ...step, cycle: 60, unit, anchor }, opts) : null;
1507
1598
  }
1508
1599
  function stepCycle60(segment, unit, anchor, opts) {
1509
1600
  if (segment.startToken.indexOf("-") !== -1) {
@@ -1513,7 +1604,7 @@ function stepCycle60(segment, unit, anchor, opts) {
1513
1604
  if (start !== 0 && segment.fires.length <= 3) {
1514
1605
  return listPastThe(numberWords(segment.fires, opts), unit, anchor, opts);
1515
1606
  }
1516
- return renderStride({
1607
+ return renderStride2({
1517
1608
  interval: segment.interval,
1518
1609
  start,
1519
1610
  last: segment.fires[segment.fires.length - 1],
@@ -1539,24 +1630,21 @@ function stepHours(segment, opts) {
1539
1630
  function hourStrideCadence(stride, opts) {
1540
1631
  const { start, interval, last } = stride;
1541
1632
  const cadence = "every " + getNumber(interval, opts) + " hours";
1542
- const tiles = 24 % interval === 0;
1543
- if (start === 0 && tiles) {
1544
- return cadence;
1545
- }
1546
- if (start < interval && tiles) {
1547
- return cadence + " from " + getTime({ hour: start, minute: 0 }, opts);
1548
- }
1549
- return cadence + " from " + getTime({ hour: start, minute: 0 }, opts) + through(opts) + getTime({ hour: last, minute: 0 }, opts);
1633
+ return renderStride({ start, interval, cycle: 24 }, {
1634
+ bare: () => cadence,
1635
+ offset: () => cadence + " from " + getTime({ hour: start, minute: 0 }, opts),
1636
+ bounded: () => cadence + " from " + getTime({ hour: start, minute: 0 }, opts) + through(opts) + getTime({ hour: last, minute: 0 }, opts)
1637
+ });
1550
1638
  }
1551
- function unevenHourCadence(ir, opts) {
1552
- const stride = hourStride(ir);
1639
+ function unevenHourCadence(schedule, opts) {
1640
+ const stride = hourStride(schedule);
1553
1641
  if (!stride || offsetCleanStride(stride)) {
1554
1642
  return null;
1555
1643
  }
1556
1644
  return hourStrideCadence(stride, opts);
1557
1645
  }
1558
- function hourStride(ir) {
1559
- const segments = segmentsOf(ir, "hour");
1646
+ function hourStride(schedule) {
1647
+ const segments = segmentsOf(schedule, "hour");
1560
1648
  if (segments.length === 1 && segments[0].kind === "step") {
1561
1649
  const segment = segments[0];
1562
1650
  if (segment.fires.length < 2) {
@@ -1568,57 +1656,57 @@ function hourStride(ir) {
1568
1656
  const values = singleValues(segments);
1569
1657
  return values && hourListStride(values);
1570
1658
  }
1571
- function subMinuteSecond(ir) {
1572
- return ir.pattern.second === "*" || ir.shapes.second === "step";
1659
+ function subMinuteSecond(schedule) {
1660
+ return schedule.pattern.second === "*" || schedule.shapes.second === "step";
1573
1661
  }
1574
- function hourCadenceLead(ir, minute, opts) {
1662
+ function hourCadenceLead(schedule, minute, opts) {
1575
1663
  if (minute === 0) {
1576
- if (subMinuteSecond(ir)) {
1577
- return secondsClause(ir, "minute", opts) + " for one minute";
1664
+ if (subMinuteSecond(schedule)) {
1665
+ return secondsClause(schedule, "minute", opts) + " for one minute";
1578
1666
  }
1579
- return secondsClause(ir, "hour", opts);
1667
+ return secondsClause(schedule, "hour", opts);
1580
1668
  }
1581
1669
  const minutePhrase = getNumber(minute, opts) + " " + pluralize(minute, "minute") + " past the hour";
1582
- if (ir.pattern.second === "0") {
1670
+ if (schedule.pattern.second === "0") {
1583
1671
  return minutePhrase;
1584
1672
  }
1585
- return secondsClause(ir, "minute", opts) + ", " + minutePhrase;
1673
+ return secondsClause(schedule, "minute", opts) + ", " + minutePhrase;
1586
1674
  }
1587
- function hourCadence(ir, minute, opts) {
1588
- const stride = hourStride(ir);
1675
+ function hourCadence(schedule, minute, opts) {
1676
+ const stride = hourStride(schedule);
1589
1677
  if (!stride) {
1590
1678
  return null;
1591
1679
  }
1592
1680
  const fires = (stride.last - stride.start) / stride.interval + 1;
1593
- if (ir.pattern.second === "0" && fires <= maxClockTimes && offsetCleanStride(stride)) {
1681
+ if (schedule.pattern.second === "0" && fires <= maxClockTimes && offsetCleanStride(stride)) {
1594
1682
  return null;
1595
1683
  }
1596
- const minuteZeroStride = minute === 0 && subMinuteSecond(ir) && cleanStrideSegment(ir);
1684
+ const minuteZeroStride = minute === 0 && subMinuteSecond(schedule) && cleanStrideSegment(schedule);
1597
1685
  if (minuteZeroStride) {
1598
- return secondsClause(ir, "minute", opts) + " for one minute " + everyNthHour(minuteZeroStride, opts) + trailingQualifier(ir, opts);
1686
+ return secondsClause(schedule, "minute", opts) + " for one minute " + everyNthHour(minuteZeroStride, opts) + trailingQualifier(schedule, opts);
1599
1687
  }
1600
- if (minute === 0 && ir.pattern.second === "0") {
1601
- return hourStrideCadence(stride, opts) + trailingQualifier(ir, opts);
1688
+ if (minute === 0 && schedule.pattern.second === "0") {
1689
+ return hourStrideCadence(stride, opts) + trailingQualifier(schedule, opts);
1602
1690
  }
1603
- return hourCadenceLead(ir, minute, opts) + ", " + hourStrideCadence(stride, opts) + trailingQualifier(ir, opts);
1691
+ return hourCadenceLead(schedule, minute, opts) + ", " + hourStrideCadence(stride, opts) + trailingQualifier(schedule, opts);
1604
1692
  }
1605
- function cleanStrideSegment(ir) {
1606
- const segments = segmentsOf(ir, "hour");
1693
+ function cleanStrideSegment(schedule) {
1694
+ const segments = segmentsOf(schedule, "hour");
1607
1695
  const segment = segments.length === 1 && segments[0];
1608
1696
  if (!segment || segment.kind !== "step" || segment.startToken.indexOf("-") !== -1 || !(segment.interval in stepOrdinals)) {
1609
1697
  return null;
1610
1698
  }
1611
1699
  return segment;
1612
1700
  }
1613
- function hasHourWindow(ir) {
1614
- return segmentsOf(ir, "hour").some(function range(segment) {
1701
+ function hasHourWindow(schedule) {
1702
+ return segmentsOf(schedule, "hour").some(function range(segment) {
1615
1703
  return segment.kind === "range";
1616
1704
  });
1617
1705
  }
1618
- function hourRangeWindowTail(ir, opts) {
1706
+ function hourRangeWindowTail(schedule, opts) {
1619
1707
  const windows = [];
1620
- const outlierHours = collectHourOutliers(ir);
1621
- segmentsOf(ir, "hour").forEach(function classify(segment) {
1708
+ const outlierHours = collectHourOutliers(schedule);
1709
+ segmentsOf(schedule, "hour").forEach(function classify(segment) {
1622
1710
  if (segment.kind === "range") {
1623
1711
  windows.push(rangeWindow({
1624
1712
  continuous: false,
@@ -1634,17 +1722,17 @@ function hourRangeWindowTail(ir, opts) {
1634
1722
  });
1635
1723
  return phrase + outlierTail(times, opts);
1636
1724
  }
1637
- function hourRangeCadence(ir, minute, opts) {
1638
- if (minute !== 0 || !hasHourWindow(ir)) {
1725
+ function hourRangeCadence(schedule, minute, opts) {
1726
+ if (minute !== 0 || !hasHourWindow(schedule)) {
1639
1727
  return null;
1640
1728
  }
1641
- if (ir.pattern.second === "0") {
1729
+ if (schedule.pattern.second === "0") {
1642
1730
  return null;
1643
1731
  }
1644
- if (subMinuteSecond(ir)) {
1645
- return secondsClause(ir, "minute", opts) + " for one minute during the " + hourSegmentTimes(ir, { minute: 0, second: null }, false, opts) + " hours" + trailingQualifier(ir, opts);
1732
+ if (subMinuteSecond(schedule)) {
1733
+ return secondsClause(schedule, "minute", opts) + " for one minute during the " + hourSegmentTimes(schedule, { minute: 0, second: null }, false, opts) + " hours" + trailingQualifier(schedule, opts);
1646
1734
  }
1647
- return hourCadenceLead(ir, minute, opts) + ", " + hourRangeWindowTail(ir, opts) + trailingQualifier(ir, opts);
1735
+ return hourCadenceLead(schedule, minute, opts) + ", " + hourRangeWindowTail(schedule, opts) + trailingQualifier(schedule, opts);
1648
1736
  }
1649
1737
  function seriesNumber() {
1650
1738
  return function format(n) {
@@ -1703,11 +1791,11 @@ function hourTimes(hours, opts) {
1703
1791
  function singleHourFire(times) {
1704
1792
  return times.kind === "fires" && times.fires.length === 1;
1705
1793
  }
1706
- function hourTimesFromPlan(ir, times, atContext, opts) {
1794
+ function hourTimesFromPlan(schedule, times, atContext, opts) {
1707
1795
  if (times.kind === "fires") {
1708
1796
  return hourTimes(times.fires, opts);
1709
1797
  }
1710
- return hourSegmentTimes(ir, { minute: 0, second: null }, atContext, opts);
1798
+ return hourSegmentTimes(schedule, { minute: 0, second: null }, atContext, opts);
1711
1799
  }
1712
1800
  function segmentHours(segment) {
1713
1801
  if (segment.kind === "range") {
@@ -1715,9 +1803,9 @@ function segmentHours(segment) {
1715
1803
  }
1716
1804
  return segment.kind === "step" ? segment.fires : [segment.value];
1717
1805
  }
1718
- function hourSegmentTimes(ir, fold, atContext, opts) {
1806
+ function hourSegmentTimes(schedule, fold, atContext, opts) {
1719
1807
  const { minute, second } = fold;
1720
- const segments = segmentsOf(ir, "hour");
1808
+ const segments = segmentsOf(schedule, "hour");
1721
1809
  const plain = mixedTwelve(segments.flatMap(function entries(segment) {
1722
1810
  return segmentHours(segment).map(function entry(hour) {
1723
1811
  return { hour: +hour, minute, second };
@@ -1780,85 +1868,85 @@ var leadingWords = {
1780
1868
  stepDate: "",
1781
1869
  weekday: "every "
1782
1870
  };
1783
- function trailingQualifier(ir, opts) {
1784
- if (isDayUnion(ir, opts)) {
1785
- return dayUnionCondition(ir, opts);
1871
+ function trailingQualifier(schedule, opts) {
1872
+ if (isDayUnion(schedule, opts)) {
1873
+ return dayUnionCondition(schedule, opts);
1786
1874
  }
1787
- const phrase = dayQualifier(ir, trailingWords, opts);
1875
+ const phrase = dayQualifier(schedule, trailingWords, opts);
1788
1876
  return phrase && " " + phrase;
1789
1877
  }
1790
- function interpretDayQualifier(ir, opts) {
1791
- if (isDayUnion(ir, opts)) {
1878
+ function interpretDayQualifier(schedule, opts) {
1879
+ if (isDayUnion(schedule, opts)) {
1792
1880
  return "";
1793
1881
  }
1794
- return dayQualifier(ir, leadingWords, opts) + " ";
1882
+ return dayQualifier(schedule, leadingWords, opts) + " ";
1795
1883
  }
1796
- function dayQualifier(ir, words, opts) {
1797
- const pattern = ir.pattern;
1884
+ function dayQualifier(schedule, words, opts) {
1885
+ const pattern = schedule.pattern;
1798
1886
  if (pattern.date !== "*" && pattern.weekday !== "*") {
1799
- return dateOrWeekday(ir, opts);
1887
+ return dateOrWeekday(schedule, opts);
1800
1888
  }
1801
1889
  if (pattern.date !== "*") {
1802
- return datePhrase(ir, words, opts);
1890
+ return datePhrase(schedule, words, opts);
1803
1891
  }
1804
1892
  if (pattern.weekday !== "*") {
1805
1893
  const quartzWeekday = quartzWeekdayPhrase(pattern.weekday, opts);
1806
1894
  if (quartzWeekday) {
1807
- return monthScopeForRecurrence(quartzWeekday, ir, opts);
1895
+ return monthScopeForRecurrence(quartzWeekday, schedule, opts);
1808
1896
  }
1809
- const weekdays = words.weekday + weekdayPhrase(ir, words.recurringWeekday, opts);
1810
- return weekdays + monthScope(ir, opts);
1897
+ const weekdays = words.weekday + weekdayPhrase(schedule, words.recurringWeekday, opts);
1898
+ return weekdays + monthScope(schedule, opts);
1811
1899
  }
1812
1900
  if (pattern.month !== "*") {
1813
- return words.month + monthName(ir, opts);
1901
+ return words.month + monthName(schedule, opts);
1814
1902
  }
1815
1903
  return words.all;
1816
1904
  }
1817
- function datePhrase(ir, words, opts) {
1818
- const pattern = ir.pattern;
1905
+ function datePhrase(schedule, words, opts) {
1906
+ const pattern = schedule.pattern;
1819
1907
  const quartzDate = quartzDatePhrase(pattern.date, opts);
1820
1908
  if (quartzDate) {
1821
- return monthScopeForRecurrence(quartzDate, ir, opts);
1909
+ return monthScopeForRecurrence(quartzDate, schedule, opts);
1822
1910
  }
1823
1911
  if (isOpenStep(pattern.date)) {
1824
1912
  return monthScopeForRecurrence(
1825
1913
  words.stepDate + stepDates(pattern.date),
1826
- ir,
1914
+ schedule,
1827
1915
  opts
1828
1916
  );
1829
1917
  }
1830
- if (pattern.month !== "*" && !monthFoldsIntoDate(ir)) {
1831
- return "on the " + dateOrdinals(ir, opts) + monthScope(ir, opts);
1918
+ if (pattern.month !== "*" && !monthFoldsIntoDate(schedule)) {
1919
+ return "on the " + dateOrdinals(schedule, opts) + monthScope(schedule, opts);
1832
1920
  }
1833
1921
  if (pattern.month !== "*") {
1834
- return "on " + monthDatePhrase(ir, opts);
1922
+ return "on " + monthDatePhrase(schedule, opts);
1835
1923
  }
1836
- return "on the " + dateOrdinals(ir, opts);
1924
+ return "on the " + dateOrdinals(schedule, opts);
1837
1925
  }
1838
- function monthFoldsIntoDate(ir) {
1839
- return !oddEvenMonth(ir.pattern.month) && // Reached only with a restricted month, which has segments.
1840
- segmentsOf(ir, "month").every(function flat(segment) {
1926
+ function monthFoldsIntoDate(schedule) {
1927
+ return !oddEvenMonth(schedule.pattern.month) && // Reached only with a restricted month, which has segments.
1928
+ segmentsOf(schedule, "month").every(function flat(segment) {
1841
1929
  return segment.kind !== "range";
1842
1930
  });
1843
1931
  }
1844
- function isDayUnion(ir, opts) {
1845
- return ir.pattern.date !== "*" && ir.pattern.weekday !== "*" && !!opts.style.untilWindow && !opts.short;
1932
+ function isDayUnion(schedule, opts) {
1933
+ return schedule.pattern.date !== "*" && schedule.pattern.weekday !== "*" && !!opts.style.untilWindow && !opts.short;
1846
1934
  }
1847
- function dayUnionCondition(ir, opts) {
1935
+ function dayUnionCondition(schedule, opts) {
1848
1936
  const pieces = [
1849
- ...dayUnionDatePieces(ir, opts),
1850
- ...dayUnionWeekdayPieces(ir, opts)
1937
+ ...dayUnionDatePieces(schedule, opts),
1938
+ ...dayUnionWeekdayPieces(schedule, opts)
1851
1939
  ];
1852
1940
  return " whenever the day is " + joinOr(pieces, opts);
1853
1941
  }
1854
- function dayUnionMonthLead(ir, opts) {
1855
- if (ir.pattern.month === "*") {
1942
+ function dayUnionMonthLead(schedule, opts) {
1943
+ if (schedule.pattern.month === "*") {
1856
1944
  return "";
1857
1945
  }
1858
- return "in " + monthName(ir, opts) + " ";
1946
+ return "in " + monthName(schedule, opts) + " ";
1859
1947
  }
1860
- function dayUnionDatePieces(ir, opts) {
1861
- const dateField = ir.pattern.date;
1948
+ function dayUnionDatePieces(schedule, opts) {
1949
+ const dateField = schedule.pattern.date;
1862
1950
  const quartz = quartzDatePhrase(dateField, opts);
1863
1951
  if (quartz) {
1864
1952
  return [quartz.replace(/^on /, "")];
@@ -1868,7 +1956,7 @@ function dayUnionDatePieces(ir, opts) {
1868
1956
  return [oddEven];
1869
1957
  }
1870
1958
  const pieces = [];
1871
- segmentsOf(ir, "date").forEach(function expand(segment) {
1959
+ segmentsOf(schedule, "date").forEach(function expand(segment) {
1872
1960
  if (segment.kind === "range") {
1873
1961
  pieces.push("from the " + getOrdinal(segment.bounds[0]) + through(opts) + "the " + getOrdinal(segment.bounds[1]));
1874
1962
  } else if (segment.kind === "step") {
@@ -1881,14 +1969,14 @@ function dayUnionDatePieces(ir, opts) {
1881
1969
  });
1882
1970
  return pieces;
1883
1971
  }
1884
- function dayUnionWeekdayPieces(ir, opts) {
1885
- const weekdayField = ir.pattern.weekday;
1972
+ function dayUnionWeekdayPieces(schedule, opts) {
1973
+ const weekdayField = schedule.pattern.weekday;
1886
1974
  const quartz = quartzWeekdayPhrase(weekdayField, opts);
1887
1975
  if (quartz) {
1888
1976
  return [quartz.replace(/^on /, "")];
1889
1977
  }
1890
1978
  const pieces = [];
1891
- segmentsOf(ir, "weekday").forEach(function expand(segment) {
1979
+ segmentsOf(schedule, "weekday").forEach(function expand(segment) {
1892
1980
  if (segment.kind === "range" && segment.bounds[0] === "1" && segment.bounds[1] === "5") {
1893
1981
  pieces.push("a weekday");
1894
1982
  } else if (segment.kind === "range") {
@@ -1916,16 +2004,16 @@ function oddEvenDay(dateField) {
1916
2004
  }
1917
2005
  return start === "2" ? "an even-numbered day" : null;
1918
2006
  }
1919
- function dateOrWeekday(ir, opts) {
1920
- const pattern = ir.pattern;
1921
- const weekdayPart = quartzWeekdayPhrase(pattern.weekday, opts) || "on " + weekdayPhrase(ir, false, opts);
1922
- if (pattern.month !== "*" && monthFoldsIntoDate(ir) && !quartzDatePhrase(pattern.date, opts) && !isOpenStep(pattern.date)) {
1923
- return "on " + monthDatePhrase(ir, opts) + " or " + weekdayPart + " in " + monthName(ir, opts);
2007
+ function dateOrWeekday(schedule, opts) {
2008
+ const pattern = schedule.pattern;
2009
+ const weekdayPart = quartzWeekdayPhrase(pattern.weekday, opts) || "on " + weekdayPhrase(schedule, false, opts);
2010
+ if (pattern.month !== "*" && monthFoldsIntoDate(schedule) && !quartzDatePhrase(pattern.date, opts) && !isOpenStep(pattern.date)) {
2011
+ return "on " + monthDatePhrase(schedule, opts) + " or " + weekdayPart + " in " + monthName(schedule, opts);
1924
2012
  }
1925
- return datePart(ir, opts) + " or " + weekdayPart + orMonthScope(ir, opts);
2013
+ return datePart(schedule, opts) + " or " + weekdayPart + orMonthScope(schedule, opts);
1926
2014
  }
1927
- function datePart(ir, opts) {
1928
- const pattern = ir.pattern;
2015
+ function datePart(schedule, opts) {
2016
+ const pattern = schedule.pattern;
1929
2017
  const quartzDate = quartzDatePhrase(pattern.date, opts);
1930
2018
  if (quartzDate) {
1931
2019
  return quartzDate;
@@ -1933,13 +2021,13 @@ function datePart(ir, opts) {
1933
2021
  if (isOpenStep(pattern.date)) {
1934
2022
  return stepDates(pattern.date);
1935
2023
  }
1936
- return "on the " + dateOrdinals(ir, opts);
2024
+ return "on the " + dateOrdinals(schedule, opts);
1937
2025
  }
1938
- function orMonthScope(ir, opts) {
1939
- if (ir.pattern.month === "*") {
2026
+ function orMonthScope(schedule, opts) {
2027
+ if (schedule.pattern.month === "*") {
1940
2028
  return "";
1941
2029
  }
1942
- return ", in " + monthName(ir, opts);
2030
+ return ", in " + monthName(schedule, opts);
1943
2031
  }
1944
2032
  function quartzDatePhrase(dateField, opts) {
1945
2033
  if (dateField === "L") {
@@ -1966,39 +2054,39 @@ function quartzWeekdayPhrase(weekdayField, opts) {
1966
2054
  return "on the last " + getWeekday(weekdayField.slice(0, -1), opts) + " of the month";
1967
2055
  }
1968
2056
  }
1969
- function monthDatePhrase(ir, opts) {
1970
- const month = monthName(ir, opts);
2057
+ function monthDatePhrase(schedule, opts) {
2058
+ const month = monthName(schedule, opts);
1971
2059
  const days = renderSegments(
1972
- segmentsOf(ir, "date"),
2060
+ segmentsOf(schedule, "date"),
1973
2061
  opts.style.ordinals ? getOrdinal : cardinalDay,
1974
2062
  opts
1975
2063
  );
1976
- if (opts.style.dayFirst && ir.shapes.date === "single" && ir.shapes.month !== "single") {
1977
- return "the " + getOrdinal(ir.pattern.date) + " of " + month;
2064
+ if (opts.style.dayFirst && schedule.shapes.date === "single" && schedule.shapes.month !== "single") {
2065
+ return "the " + getOrdinal(schedule.pattern.date) + " of " + month;
1978
2066
  }
1979
2067
  return opts.style.dayFirst ? days + " " + month : month + " " + days;
1980
2068
  }
1981
2069
  function cardinalDay(value) {
1982
2070
  return "" + value;
1983
2071
  }
1984
- function monthScope(ir, opts) {
1985
- if (ir.pattern.month === "*") {
2072
+ function monthScope(schedule, opts) {
2073
+ if (schedule.pattern.month === "*") {
1986
2074
  return "";
1987
2075
  }
1988
- return " in " + monthName(ir, opts);
2076
+ return " in " + monthName(schedule, opts);
1989
2077
  }
1990
- function monthScopeForRecurrence(phrase, ir, opts) {
1991
- if (ir.pattern.month === "*") {
2078
+ function monthScopeForRecurrence(phrase, schedule, opts) {
2079
+ if (schedule.pattern.month === "*") {
1992
2080
  return phrase;
1993
2081
  }
1994
2082
  const carriesRecurrence = phrase.indexOf(" of the month") !== -1;
1995
- if (carriesRecurrence && ir.shapes.month === "range") {
1996
- return phrase.replace(" of the month", " of each month") + " from " + monthName(ir, opts);
2083
+ if (carriesRecurrence && schedule.shapes.month === "range") {
2084
+ return phrase.replace(" of the month", " of each month") + " from " + monthName(schedule, opts);
1997
2085
  }
1998
- if (carriesRecurrence && (ir.shapes.month === "single" || ir.shapes.month === "step")) {
1999
- return phrase.replace(" of the month", "") + " in " + monthName(ir, opts);
2086
+ if (carriesRecurrence && (schedule.shapes.month === "single" || schedule.shapes.month === "step")) {
2087
+ return phrase.replace(" of the month", "") + " in " + monthName(schedule, opts);
2000
2088
  }
2001
- return phrase + " in " + monthName(ir, opts);
2089
+ return phrase + " in " + monthName(schedule, opts);
2002
2090
  }
2003
2091
  function stepDates(dateField) {
2004
2092
  const parts = dateField.split("/");
@@ -2011,15 +2099,15 @@ function stepDates(dateField) {
2011
2099
  }
2012
2100
  return phrase;
2013
2101
  }
2014
- function dateOrdinals(ir, opts) {
2015
- return renderSegments(segmentsOf(ir, "date"), getOrdinal, opts);
2102
+ function dateOrdinals(schedule, opts) {
2103
+ return renderSegments(segmentsOf(schedule, "date"), getOrdinal, opts);
2016
2104
  }
2017
- function monthName(ir, opts) {
2018
- const oddEven = oddEvenMonth(ir.pattern.month);
2105
+ function monthName(schedule, opts) {
2106
+ const oddEven = oddEvenMonth(schedule.pattern.month);
2019
2107
  if (oddEven) {
2020
2108
  return oddEven;
2021
2109
  }
2022
- return renderSegments(segmentsOf(ir, "month"), function name(value) {
2110
+ return renderSegments(segmentsOf(schedule, "month"), function name(value) {
2023
2111
  return getMonth(value, opts);
2024
2112
  }, opts);
2025
2113
  }
@@ -2036,8 +2124,8 @@ function oddEvenMonth(monthField) {
2036
2124
  }
2037
2125
  return start === "2" ? "every even-numbered month" : null;
2038
2126
  }
2039
- function weekdayPhrase(ir, recurring, opts) {
2040
- const segments = orderWeekdaysForDisplay(segmentsOf(ir, "weekday"));
2127
+ function weekdayPhrase(schedule, recurring, opts) {
2128
+ const segments = orderWeekdaysForDisplay(segmentsOf(schedule, "weekday"));
2041
2129
  const hasRange = segments.some(function range(segment) {
2042
2130
  return segment.kind === "range";
2043
2131
  });
@@ -2065,8 +2153,8 @@ function renderSegments(segments, word, opts) {
2065
2153
  });
2066
2154
  return joinList(pieces, opts);
2067
2155
  }
2068
- function applyYear(description, ir, opts) {
2069
- const yearField = ir.pattern.year;
2156
+ function applyYear(description, schedule, opts) {
2157
+ const yearField = schedule.pattern.year;
2070
2158
  if (yearField === "*") {
2071
2159
  return description;
2072
2160
  }
@@ -2074,7 +2162,7 @@ function applyYear(description, ir, opts) {
2074
2162
  return description + ", " + stepYears(yearField, opts);
2075
2163
  }
2076
2164
  const label = yearLabel(yearField, opts);
2077
- if (yearField.indexOf("-") === -1 && yearField.indexOf(",") === -1 && ir.pattern.date !== "*" && description.indexOf(" at ") !== -1) {
2165
+ if (yearField.indexOf("-") === -1 && yearField.indexOf(",") === -1 && schedule.pattern.date !== "*" && description.indexOf(" at ") !== -1) {
2078
2166
  const yearGlue = opts.style.dayFirst ? " " : ", ";
2079
2167
  return description.replace(" at ", yearGlue + label + " at ");
2080
2168
  }
@@ -2197,9 +2285,9 @@ function interpretCronPattern(cronPattern, lang, opts) {
2197
2285
  if (typeof cronPattern === "string" && cronPattern.trim().toLowerCase() === "@reboot") {
2198
2286
  return lang.reboot;
2199
2287
  }
2200
- const ir = analyze(prepare(cronPattern, opts));
2201
- const plan = lang.plan ? lang.plan(ir, ir.plan) : ir.plan;
2202
- return lang.describe({ ...ir, plan }, opts);
2288
+ const schedule = analyze(prepare(cronPattern, opts));
2289
+ const plan = lang.plan ? lang.plan(schedule, schedule.plan) : schedule.plan;
2290
+ return lang.describe({ ...schedule, plan }, opts);
2203
2291
  }
2204
2292
  var cronli5_default = cronli5;
2205
2293
  export {