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.cjs CHANGED
@@ -95,81 +95,9 @@ function isNonNegativeInteger(value) {
95
95
  const digits = /^\d+$/;
96
96
  return digits.test(value);
97
97
  }
98
- function arithmeticStep(values) {
99
- if (values.length < 5) {
100
- return null;
101
- }
102
- const interval = values[1] - values[0];
103
- if (interval < 2) {
104
- return null;
105
- }
106
- for (let i = 2; i < values.length; i += 1) {
107
- if (values[i] - values[i - 1] !== interval) {
108
- return null;
109
- }
110
- }
111
- return { start: values[0], interval, last: values[values.length - 1] };
112
- }
113
- function weekdayDisplayKey(value) {
114
- return value === 0 ? 7 : value;
115
- }
116
- function orderWeekdaysForDisplay(segments) {
117
- const flattened = segments.flatMap(function flat(segment) {
118
- return segment.kind === "step" ? segment.fires.map(function single(value) {
119
- return { kind: "single", value: "" + value };
120
- }) : [segment];
121
- });
122
- function key(segment) {
123
- return segment.kind === "range" ? weekdayDisplayKey(+segment.bounds[0]) : weekdayDisplayKey(+segment.value);
124
- }
125
- return flattened.map(function index(segment, position) {
126
- return [segment, position];
127
- }).sort(function byDisplayKey(a, b) {
128
- return key(a[0]) - key(b[0]) || a[1] - b[1];
129
- }).map(function unwrap(pair) {
130
- return pair[0];
131
- });
132
- }
133
98
  function toFieldNumber(token, numberMap) {
134
99
  return isNonNegativeInteger(token) ? +token : numberMap[token.toUpperCase()];
135
100
  }
136
- function segmentsOf(ir, field) {
137
- return ir.analyses.segments[field] ?? [];
138
- }
139
- function stepSegment(ir, field) {
140
- return segmentsOf(ir, field)[0];
141
- }
142
- function singleValues(segments) {
143
- const values = [];
144
- for (const segment of segments) {
145
- if (segment.kind !== "single") {
146
- return null;
147
- }
148
- values.push(+segment.value);
149
- }
150
- return values;
151
- }
152
- function offsetCleanStride(stride) {
153
- return stride.start < stride.interval && 24 % stride.interval === 0;
154
- }
155
- function hourListStride(values) {
156
- if (values.length < 2) {
157
- return null;
158
- }
159
- const interval = values[1] - values[0];
160
- if (interval < 2) {
161
- return null;
162
- }
163
- for (let i = 2; i < values.length; i += 1) {
164
- if (values[i] - values[i - 1] !== interval) {
165
- return null;
166
- }
167
- }
168
- if (values[0] !== 0 && values.length < 5) {
169
- return null;
170
- }
171
- return { interval, last: values[values.length - 1], start: values[0] };
172
- }
173
101
 
174
102
  // src/core/validate.ts
175
103
  function validateCronPattern(cronPattern) {
@@ -299,7 +227,7 @@ function normalizeField(value, field, spec) {
299
227
  const cycle = timeFieldCycle[field];
300
228
  const segments = stringValue.split(",").map(function canonical(segment) {
301
229
  return canonicalizeTokens(collapseFullSpanRange(
302
- enumerateNonUniformStep(
230
+ enumerateIfNonUniform(
303
231
  collapseFullSpanStep(
304
232
  collapseDegenerateRange(
305
233
  collapseOnceStep(collapseUnitStep(segment, spec), spec),
@@ -363,7 +291,7 @@ function collapseOnceStep(segment, spec) {
363
291
  }
364
292
  return start === "*" ? "" + spec.min : start;
365
293
  }
366
- function enumerateNonUniformStep(segment, spec, cycle) {
294
+ function enumerateIfNonUniform(segment, spec, cycle) {
367
295
  const parts = segment.split("/");
368
296
  if (typeof cycle !== "number" || parts.length !== 2 || includes(parts[0], "-")) {
369
297
  return segment;
@@ -502,6 +430,93 @@ function expandMacro(cronString) {
502
430
  throw new Error("`cronli5` does not recognize the macro `" + trimmed + "`.");
503
431
  }
504
432
 
433
+ // src/core/weekday.ts
434
+ function weekdayDisplayKey(value) {
435
+ return value === 0 ? 7 : value;
436
+ }
437
+ function orderWeekdaysForDisplay(segments) {
438
+ const flattened = segments.flatMap(function flat(segment) {
439
+ return segment.kind === "step" ? segment.fires.map(function single(value) {
440
+ return { kind: "single", value: "" + value };
441
+ }) : [segment];
442
+ });
443
+ function key(segment) {
444
+ return segment.kind === "range" ? weekdayDisplayKey(+segment.bounds[0]) : weekdayDisplayKey(+segment.value);
445
+ }
446
+ return flattened.map(function index(segment, position) {
447
+ return [segment, position];
448
+ }).sort(function byDisplayKey(a, b) {
449
+ return key(a[0]) - key(b[0]) || a[1] - b[1];
450
+ }).map(function unwrap(pair) {
451
+ return pair[0];
452
+ });
453
+ }
454
+
455
+ // src/core/cadence.ts
456
+ function arithmeticStep(values) {
457
+ if (values.length < 5) {
458
+ return null;
459
+ }
460
+ const interval = values[1] - values[0];
461
+ if (interval < 2) {
462
+ return null;
463
+ }
464
+ for (let i = 2; i < values.length; i += 1) {
465
+ if (values[i] - values[i - 1] !== interval) {
466
+ return null;
467
+ }
468
+ }
469
+ return { start: values[0], interval, last: values[values.length - 1] };
470
+ }
471
+ function segmentsOf(schedule, field) {
472
+ return schedule.analyses.segments[field] ?? [];
473
+ }
474
+ function stepSegment(schedule, field) {
475
+ return segmentsOf(schedule, field)[0];
476
+ }
477
+ function singleValues(segments) {
478
+ const values = [];
479
+ for (const segment of segments) {
480
+ if (segment.kind !== "single") {
481
+ return null;
482
+ }
483
+ values.push(+segment.value);
484
+ }
485
+ return values;
486
+ }
487
+ function offsetCleanStride(stride) {
488
+ return stride.start < stride.interval && 24 % stride.interval === 0;
489
+ }
490
+ function renderStride(spec, parts) {
491
+ const { start, interval, cycle } = spec;
492
+ const tiles = cycle % interval === 0;
493
+ if (start === 0 && tiles) {
494
+ return parts.bare();
495
+ }
496
+ if (start < interval && tiles) {
497
+ return parts.offset();
498
+ }
499
+ return parts.bounded();
500
+ }
501
+ function hourListStride(values) {
502
+ if (values.length < 2) {
503
+ return null;
504
+ }
505
+ const interval = values[1] - values[0];
506
+ if (interval < 2) {
507
+ return null;
508
+ }
509
+ for (let i = 2; i < values.length; i += 1) {
510
+ if (values[i] - values[i - 1] !== interval) {
511
+ return null;
512
+ }
513
+ }
514
+ if (values[0] !== 0 && values.length < 5) {
515
+ return null;
516
+ }
517
+ return { interval, last: values[values.length - 1], start: values[0] };
518
+ }
519
+
505
520
  // src/core/shapes.ts
506
521
  function isSingleValue(field) {
507
522
  return field !== "*" && !includes(field, ",") && !includes(field, "-") && !includes(field, "/");
@@ -656,11 +671,11 @@ function analyze(pattern) {
656
671
  minuteSpan: minuteSpan(pattern.minute),
657
672
  segments
658
673
  };
659
- const content = { analyses, pattern, shapes };
660
- return { ...content, plan: selectPlan(content) };
674
+ const facts = { analyses, pattern, shapes };
675
+ return { ...facts, plan: selectPlan(facts) };
661
676
  }
662
- function selectPlan(content) {
663
- const { analyses, pattern, shapes } = content;
677
+ function selectPlan(facts) {
678
+ const { analyses, pattern, shapes } = facts;
664
679
  if (pattern.second !== "0") {
665
680
  const seconds = planSeconds(pattern, shapes, analyses);
666
681
  if (seconds) {
@@ -1004,72 +1019,134 @@ function normalizeOptions(options) {
1004
1019
  years: !!options.years
1005
1020
  };
1006
1021
  }
1007
- function describe(ir, opts) {
1008
- const body = confinement(ir, opts) ?? render(ir, ir.plan, opts);
1009
- const lead = isDayUnion(ir, opts) ? dayUnionMonthLead(ir, opts) : "";
1010
- return applyYear(lead + body, ir, opts);
1022
+ function describe(schedule, opts) {
1023
+ const dense = denseCadence(schedule, opts);
1024
+ if (dense !== null) {
1025
+ return applyYear(dense, schedule, opts);
1026
+ }
1027
+ const body = confinement(schedule, opts) ?? render(schedule, schedule.plan, opts);
1028
+ const lead = isDayUnion(schedule, opts) ? dayUnionMonthLead(schedule, opts) : "";
1029
+ return applyYear(lead + body, schedule, opts);
1011
1030
  }
1012
- function render(ir, plan, opts) {
1031
+ function render(schedule, plan, opts) {
1013
1032
  const renderer = renderers[plan.kind];
1014
- return renderer(ir, plan, opts);
1033
+ return renderer(schedule, plan, opts);
1015
1034
  }
1016
- function renderEverySecond(ir, plan, opts) {
1017
- return "every second" + trailingQualifier(ir, opts);
1035
+ function isCadenceShape(shape) {
1036
+ return shape === "step" || shape === "range" || shape === "list";
1018
1037
  }
1019
- function renderStandaloneSeconds(ir, plan, opts) {
1020
- return secondsLeadClause(ir, opts) + trailingQualifier(ir, opts);
1038
+ function isDenseCadence(schedule, opts) {
1039
+ if (!opts.style.untilWindow || opts.short || schedule.plan.kind !== "composeSeconds" || schedule.plan.rest.kind === "clockTimes" || isDayUnion(schedule, opts)) {
1040
+ return false;
1041
+ }
1042
+ const { shapes } = schedule;
1043
+ return isCadenceShape(shapes.second) && isCadenceShape(shapes.minute) && isCadenceShape(shapes.hour);
1021
1044
  }
1022
- function renderSecondPastMinute(ir, plan, opts) {
1023
- const secondField = ir.pattern.second;
1024
- return getNumber(secondField, opts) + " " + pluralize(secondField, "second") + " past the minute, every minute" + trailingQualifier(ir, opts);
1045
+ function denseHourFragment(schedule, opts) {
1046
+ const stride = hourStride(schedule);
1047
+ if (stride) {
1048
+ return hourStrideCadence(stride, opts);
1049
+ }
1050
+ if (schedule.shapes.hour === "range") {
1051
+ const segment = segmentsOf(schedule, "hour").find(function range(part) {
1052
+ return part.kind === "range";
1053
+ });
1054
+ return rangeWindow({
1055
+ continuous: false,
1056
+ from: +segment.bounds[0],
1057
+ throughMinute: 0,
1058
+ to: +segment.bounds[1]
1059
+ }, opts);
1060
+ }
1061
+ return "during the " + hourSegmentTimes(schedule, { minute: 0, second: null }, false, opts) + " hours";
1025
1062
  }
1026
- function renderSecondsWithinMinute(ir, plan, opts) {
1027
- const minuteField = ir.pattern.minute;
1063
+ function denseMinuteFragment(schedule, opts) {
1064
+ if (schedule.shapes.minute === "step") {
1065
+ return stepCycle60(stepSegment(schedule, "minute"), "minute", "hour", opts);
1066
+ }
1067
+ if (schedule.shapes.minute === "range") {
1068
+ return minuteRangeLead(schedule.pattern.minute, opts);
1069
+ }
1070
+ return strideFromSegments(
1071
+ segmentsOf(schedule, "minute"),
1072
+ "minute",
1073
+ "hour",
1074
+ opts
1075
+ ) ?? listPastThe(
1076
+ segmentWords(segmentsOf(schedule, "minute"), opts),
1077
+ "minute",
1078
+ "hour",
1079
+ opts
1080
+ );
1081
+ }
1082
+ function denseCadence(schedule, opts) {
1083
+ if (!isDenseCadence(schedule, opts)) {
1084
+ return null;
1085
+ }
1086
+ const hour = denseHourFragment(schedule, opts);
1087
+ const minute = denseMinuteFragment(schedule, opts);
1088
+ const second = secondsClause(schedule, "minute", opts);
1089
+ const nested = hour + ", " + minute + ", and within each of those minutes, " + second;
1090
+ const anchor = trailingQualifier(schedule, opts).trim();
1091
+ return anchor ? anchor + ", " + nested : nested;
1092
+ }
1093
+ function renderEverySecond(schedule, plan, opts) {
1094
+ return "every second" + trailingQualifier(schedule, opts);
1095
+ }
1096
+ function renderStandaloneSeconds(schedule, plan, opts) {
1097
+ return secondsLeadClause(schedule, opts) + trailingQualifier(schedule, opts);
1098
+ }
1099
+ function renderSecondPastMinute(schedule, plan, opts) {
1100
+ const secondField = schedule.pattern.second;
1101
+ return getNumber(secondField, opts) + " " + pluralize(secondField, "second") + " past the minute, every minute" + trailingQualifier(schedule, opts);
1102
+ }
1103
+ function renderSecondsWithinMinute(schedule, plan, opts) {
1104
+ const minuteField = schedule.pattern.minute;
1028
1105
  const minuteWord = getNumber(minuteField, opts);
1029
1106
  const minuteUnit = pluralize(minuteField, "minute");
1030
1107
  if (plan.singleSecond) {
1031
- const secondField = ir.pattern.second;
1032
- return minuteWord + " " + minuteUnit + " and " + getNumber(secondField, opts) + " " + pluralize(secondField, "second") + " past the hour, every hour" + trailingQualifier(ir, opts);
1108
+ const secondField = schedule.pattern.second;
1109
+ return minuteWord + " " + minuteUnit + " and " + getNumber(secondField, opts) + " " + pluralize(secondField, "second") + " past the hour, every hour" + trailingQualifier(schedule, opts);
1033
1110
  }
1034
- return secondsLeadClause(ir, opts) + ", " + minuteWord + " " + minuteUnit + " past the hour, every hour" + trailingQualifier(ir, opts);
1111
+ return secondsLeadClause(schedule, opts) + ", " + minuteWord + " " + minuteUnit + " past the hour, every hour" + trailingQualifier(schedule, opts);
1035
1112
  }
1036
- function composeHourCadence(ir, plan, opts) {
1113
+ function composeHourCadence(schedule, plan, opts) {
1037
1114
  const clockRest = plan.rest.kind === "clockTimes" || plan.rest.kind === "compactClockTimes";
1038
- if (!clockRest || ir.shapes.minute !== "single") {
1115
+ if (!clockRest || schedule.shapes.minute !== "single") {
1039
1116
  return null;
1040
1117
  }
1041
- const minute = +ir.pattern.minute;
1042
- return hourCadence(ir, minute, opts) ?? hourRangeCadence(ir, minute, opts);
1118
+ const minute = +schedule.pattern.minute;
1119
+ return hourCadence(schedule, minute, opts) ?? hourRangeCadence(schedule, minute, opts);
1043
1120
  }
1044
- function clockTimesConfinement(ir, rest, opts) {
1045
- if (+rest.times[0].minute === 0 && ir.shapes.minute === "single") {
1046
- return secondsLeadClause(ir, opts) + " for one minute at " + durationHours(ir, rest, opts);
1121
+ function clockTimesConfinement(schedule, rest, opts) {
1122
+ if (+rest.times[0].minute === 0 && schedule.shapes.minute === "single") {
1123
+ return secondsLeadClause(schedule, opts) + " for one minute at " + durationHours(schedule, rest, opts);
1047
1124
  }
1048
- return secondsLeadClause(ir, opts) + " of " + clockTimesOf(ir, rest, opts);
1125
+ return secondsLeadClause(schedule, opts) + " of " + clockTimesOf(schedule, rest, opts);
1049
1126
  }
1050
- function renderComposeSeconds(ir, plan, opts) {
1051
- const cadence = composeHourCadence(ir, plan, opts);
1127
+ function renderComposeSeconds(schedule, plan, opts) {
1128
+ const cadence = composeHourCadence(schedule, plan, opts);
1052
1129
  if (cadence !== null) {
1053
1130
  return cadence;
1054
1131
  }
1055
- if (plan.rest.kind === "clockTimes" && (ir.shapes.second === "wildcard" || ir.shapes.second === "step")) {
1056
- return clockTimesConfinement(ir, plan.rest, opts);
1132
+ if (plan.rest.kind === "clockTimes" && (schedule.shapes.second === "wildcard" || schedule.shapes.second === "step")) {
1133
+ return clockTimesConfinement(schedule, plan.rest, opts);
1057
1134
  }
1058
- if (ir.shapes.second === "wildcard" && plan.rest.kind === "minuteFrequency" && plan.rest.hours.kind === "none" && ir.pattern.minute === "*/2") {
1059
- return "every second of every other minute" + trailingQualifier(ir, opts);
1135
+ if (schedule.shapes.second === "wildcard" && plan.rest.kind === "minuteFrequency" && plan.rest.hours.kind === "none" && schedule.pattern.minute === "*/2") {
1136
+ return "every second of every other minute" + trailingQualifier(schedule, opts);
1060
1137
  }
1061
- const restOwnsLead = plan.rest.kind === "compactClockTimes" && ir.analyses.clockSecond;
1062
- const lead = restOwnsLead ? "" : secondsLeadClause(ir, opts) + ", ";
1063
- return lead + render(ir, plan.rest, opts);
1138
+ const restOwnsLead = plan.rest.kind === "compactClockTimes" && schedule.analyses.clockSecond;
1139
+ const lead = restOwnsLead ? "" : secondsLeadClause(schedule, opts) + ", ";
1140
+ return lead + render(schedule, plan.rest, opts);
1064
1141
  }
1065
- function durationHours(ir, plan, opts) {
1142
+ function durationHours(schedule, plan, opts) {
1066
1143
  const hours = plan.times.map(function clock(time) {
1067
1144
  return getTime({ hour: time.hour, minute: 0 }, opts);
1068
1145
  });
1069
- const trail = dayQualifier(ir, leadingWords, opts);
1146
+ const trail = dayQualifier(schedule, leadingWords, opts);
1070
1147
  return joinList(hours, opts) + (trail && ", " + trail);
1071
1148
  }
1072
- function clockTimesOf(ir, plan, opts) {
1149
+ function clockTimesOf(schedule, plan, opts) {
1073
1150
  const times = plan.times.map(function clock(time) {
1074
1151
  return getTime({
1075
1152
  hour: time.hour,
@@ -1078,21 +1155,21 @@ function clockTimesOf(ir, plan, opts) {
1078
1155
  explicit: true
1079
1156
  }, opts);
1080
1157
  });
1081
- const trail = dayQualifier(ir, leadingWords, opts);
1158
+ const trail = dayQualifier(schedule, leadingWords, opts);
1082
1159
  return joinList(times, opts) + (trail && ", " + trail);
1083
1160
  }
1084
- function secondsLeadClause(ir, opts) {
1085
- return secondsClause(ir, "minute", opts);
1161
+ function secondsLeadClause(schedule, opts) {
1162
+ return secondsClause(schedule, "minute", opts);
1086
1163
  }
1087
- function secondsClause(ir, anchor, opts) {
1088
- const secondField = ir.pattern.second;
1089
- const shape = ir.shapes.second;
1164
+ function secondsClause(schedule, anchor, opts) {
1165
+ const secondField = schedule.pattern.second;
1166
+ const shape = schedule.shapes.second;
1090
1167
  if (secondField === "*") {
1091
1168
  return "every second";
1092
1169
  }
1093
1170
  if (shape === "step") {
1094
1171
  return stepCycle60(
1095
- stepSegment(ir, "second"),
1172
+ stepSegment(schedule, "second"),
1096
1173
  "second",
1097
1174
  anchor,
1098
1175
  opts
@@ -1107,44 +1184,44 @@ function secondsClause(ir, anchor, opts) {
1107
1184
  return "at " + getNumber(secondField, opts) + " " + pluralize(secondField, "second") + " past the " + anchor;
1108
1185
  }
1109
1186
  return strideFromSegments(
1110
- segmentsOf(ir, "second"),
1187
+ segmentsOf(schedule, "second"),
1111
1188
  "second",
1112
1189
  anchor,
1113
1190
  opts
1114
1191
  ) ?? listPastThe(
1115
- segmentWords(segmentsOf(ir, "second"), opts),
1192
+ segmentWords(segmentsOf(schedule, "second"), opts),
1116
1193
  "second",
1117
1194
  anchor,
1118
1195
  opts
1119
1196
  );
1120
1197
  }
1121
- function renderEveryMinute(ir, plan, opts) {
1122
- return "every minute" + trailingQualifier(ir, opts);
1198
+ function renderEveryMinute(schedule, plan, opts) {
1199
+ return "every minute" + trailingQualifier(schedule, opts);
1123
1200
  }
1124
- function renderSingleMinute(ir, plan, opts) {
1125
- const minuteField = ir.pattern.minute;
1126
- return getNumber(minuteField, opts) + " " + pluralize(minuteField, "minute") + " past the hour, every hour" + trailingQualifier(ir, opts);
1201
+ function renderSingleMinute(schedule, plan, opts) {
1202
+ const minuteField = schedule.pattern.minute;
1203
+ return getNumber(minuteField, opts) + " " + pluralize(minuteField, "minute") + " past the hour, every hour" + trailingQualifier(schedule, opts);
1127
1204
  }
1128
- function renderRangeOfMinutes(ir, plan, opts) {
1129
- return minuteRangeLead(ir.pattern.minute, opts) + trailingQualifier(ir, opts);
1205
+ function renderRangeOfMinutes(schedule, plan, opts) {
1206
+ return minuteRangeLead(schedule.pattern.minute, opts) + trailingQualifier(schedule, opts);
1130
1207
  }
1131
- function renderMultipleMinutes(ir, plan, opts) {
1132
- const stride = strideFromSegments(segmentsOf(ir, "minute"), "minute", "hour", opts);
1208
+ function renderMultipleMinutes(schedule, plan, opts) {
1209
+ const stride = strideFromSegments(segmentsOf(schedule, "minute"), "minute", "hour", opts);
1133
1210
  return (stride ?? listPastThe(segmentWords(
1134
- segmentsOf(ir, "minute"),
1211
+ segmentsOf(schedule, "minute"),
1135
1212
  opts
1136
- ), "minute", "hour", opts)) + trailingQualifier(ir, opts);
1213
+ ), "minute", "hour", opts)) + trailingQualifier(schedule, opts);
1137
1214
  }
1138
- function renderMinuteFrequency(ir, plan, opts) {
1215
+ function renderMinuteFrequency(schedule, plan, opts) {
1139
1216
  let phrase = stepCycle60(
1140
- stepSegment(ir, "minute"),
1217
+ stepSegment(schedule, "minute"),
1141
1218
  "minute",
1142
1219
  "hour",
1143
1220
  opts
1144
1221
  );
1145
1222
  if (plan.hours.kind === "during") {
1146
- const cadence = unevenHourCadence(ir, opts);
1147
- phrase += cadence ? ", " + cadence : " during the " + hourTimesFromPlan(ir, plan.hours.times, false, opts) + " hours";
1223
+ const cadence = unevenHourCadence(schedule, opts);
1224
+ phrase += cadence ? ", " + cadence : " during the " + hourTimesFromPlan(schedule, plan.hours.times, false, opts) + " hours";
1148
1225
  } else if (plan.hours.kind === "window") {
1149
1226
  phrase += " " + rangeWindow({
1150
1227
  continuous: false,
@@ -1153,45 +1230,50 @@ function renderMinuteFrequency(ir, plan, opts) {
1153
1230
  to: plan.hours.to
1154
1231
  }, opts);
1155
1232
  } else if (plan.hours.kind === "step") {
1156
- phrase += " " + everyNthHour(stepSegment(ir, "hour"), opts);
1233
+ phrase += " " + everyNthHour(stepSegment(schedule, "hour"), opts);
1157
1234
  }
1158
- return phrase + trailingQualifier(ir, opts);
1235
+ return phrase + trailingQualifier(schedule, opts);
1159
1236
  }
1160
- function renderMinuteSpanInHour(ir, plan, opts) {
1161
- if (ir.pattern.minute === "*") {
1162
- return "every minute of the " + getTime({ hour: plan.hour, minute: 0 }, opts) + " hour" + trailingQualifier(ir, opts);
1237
+ function renderMinuteSpanInHour(schedule, plan, opts) {
1238
+ if (schedule.pattern.minute === "*") {
1239
+ return "every minute of the " + getTime({ hour: plan.hour, minute: 0 }, opts) + " hour" + trailingQualifier(schedule, opts);
1163
1240
  }
1164
- 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);
1241
+ 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);
1165
1242
  }
1166
- function renderMinutesAcrossHours(ir, plan, opts) {
1167
- const cadence = unevenHourCadence(ir, opts);
1243
+ function renderMinutesAcrossHours(schedule, plan, opts) {
1244
+ const cadence = unevenHourCadence(schedule, opts);
1168
1245
  if (plan.form === "wildcard") {
1169
1246
  if (cadence !== null) {
1170
- return "every minute, " + cadence + trailingQualifier(ir, opts);
1247
+ return "every minute, " + cadence + trailingQualifier(schedule, opts);
1171
1248
  }
1172
- return "every minute during the " + hourTimesFromPlan(ir, plan.times, false, opts) + " hours" + trailingQualifier(ir, opts);
1249
+ return "every minute during the " + hourTimesFromPlan(schedule, plan.times, false, opts) + " hours" + trailingQualifier(schedule, opts);
1173
1250
  }
1174
1251
  if (plan.form === "range") {
1175
- const lead2 = minuteRangeLead(ir.pattern.minute, opts);
1252
+ const lead2 = minuteRangeLead(schedule.pattern.minute, opts);
1176
1253
  if (cadence !== null) {
1177
- return lead2 + ", " + cadence + trailingQualifier(ir, opts);
1254
+ return lead2 + ", " + cadence + trailingQualifier(schedule, opts);
1178
1255
  }
1179
1256
  if (singleHourFire(plan.times)) {
1180
- return lead2 + ", at " + hourTimesFromPlan(ir, plan.times, true, opts) + trailingQualifier(ir, opts);
1257
+ return lead2 + ", at " + hourTimesFromPlan(schedule, plan.times, true, opts) + trailingQualifier(schedule, opts);
1181
1258
  }
1182
- return lead2 + " during the " + hourTimesFromPlan(ir, plan.times, false, opts) + " hours" + trailingQualifier(ir, opts);
1259
+ return lead2 + " during the " + hourTimesFromPlan(schedule, plan.times, false, opts) + " hours" + trailingQualifier(schedule, opts);
1183
1260
  }
1184
- const lead = strideFromSegments(segmentsOf(ir, "minute"), "minute", "hour", opts) ?? listPastThe(
1185
- segmentWords(segmentsOf(ir, "minute"), opts),
1261
+ const lead = strideFromSegments(
1262
+ segmentsOf(schedule, "minute"),
1263
+ "minute",
1264
+ "hour",
1265
+ opts
1266
+ ) ?? listPastThe(
1267
+ segmentWords(segmentsOf(schedule, "minute"), opts),
1186
1268
  "minute",
1187
1269
  "hour",
1188
1270
  opts
1189
1271
  );
1190
1272
  if (cadence !== null) {
1191
- return lead + ", " + cadence + trailingQualifier(ir, opts);
1273
+ return lead + ", " + cadence + trailingQualifier(schedule, opts);
1192
1274
  }
1193
- const times = hourTimesFromPlan(ir, plan.times, true, opts);
1194
- return lead + ", at " + times + trailingQualifier(ir, opts);
1275
+ const times = hourTimesFromPlan(schedule, plan.times, true, opts);
1276
+ return lead + ", at " + times + trailingQualifier(schedule, opts);
1195
1277
  }
1196
1278
  var stepOrdinals = {
1197
1279
  2: "other",
@@ -1206,60 +1288,65 @@ function everyNthHour(segment, opts) {
1206
1288
  const start = segment.startToken === "*" ? 0 : +segment.startToken;
1207
1289
  return start === 0 ? base : base + " starting at " + getTime({ hour: start, minute: 0 }, opts);
1208
1290
  }
1209
- function renderMinuteSpanAcrossHourStep(ir, plan, opts) {
1210
- const segment = stepSegment(ir, "hour");
1291
+ function renderMinuteSpanAcrossHourStep(schedule, plan, opts) {
1292
+ const segment = stepSegment(schedule, "hour");
1211
1293
  if (plan.form === "wildcard") {
1212
- return "every minute " + everyNthHour(segment, opts) + trailingQualifier(ir, opts);
1294
+ return "every minute " + everyNthHour(segment, opts) + trailingQualifier(schedule, opts);
1213
1295
  }
1214
- const lead = plan.form === "list" ? strideFromSegments(segmentsOf(ir, "minute"), "minute", "hour", opts) ?? listPastThe(
1215
- segmentWords(segmentsOf(ir, "minute"), opts),
1296
+ const lead = plan.form === "list" ? strideFromSegments(
1297
+ segmentsOf(schedule, "minute"),
1298
+ "minute",
1299
+ "hour",
1300
+ opts
1301
+ ) ?? listPastThe(
1302
+ segmentWords(segmentsOf(schedule, "minute"), opts),
1216
1303
  "minute",
1217
1304
  "hour",
1218
1305
  opts
1219
- ) : minuteRangeLead(ir.pattern.minute, opts);
1220
- const cadence = unevenHourCadence(ir, opts);
1221
- return lead + ", " + (cadence ?? stepHours(segment, opts)) + trailingQualifier(ir, opts);
1306
+ ) : minuteRangeLead(schedule.pattern.minute, opts);
1307
+ const cadence = unevenHourCadence(schedule, opts);
1308
+ return lead + ", " + (cadence ?? stepHours(segment, opts)) + trailingQualifier(schedule, opts);
1222
1309
  }
1223
1310
  function minuteRangeLead(minuteField, opts) {
1224
1311
  const bounds = minuteField.split("-");
1225
1312
  const num = seriesNumber();
1226
1313
  return "every minute from " + num(bounds[0]) + through(opts) + num(bounds[1]) + " past the hour";
1227
1314
  }
1228
- function renderEveryHour(ir, plan, opts) {
1229
- return "every hour" + trailingQualifier(ir, opts);
1315
+ function renderEveryHour(schedule, plan, opts) {
1316
+ return "every hour" + trailingQualifier(schedule, opts);
1230
1317
  }
1231
- function renderHourRange(ir, plan, opts) {
1318
+ function renderHourRange(schedule, plan, opts) {
1232
1319
  const window = hourWindow(boundedWindow(plan), opts);
1233
1320
  if (plan.minuteForm === "wildcard") {
1234
- return "every minute " + window + trailingQualifier(ir, opts);
1321
+ return "every minute " + window + trailingQualifier(schedule, opts);
1235
1322
  }
1236
1323
  if (plan.minuteForm === "range") {
1237
- return minuteRangeLead(ir.pattern.minute, opts) + ", " + window + trailingQualifier(ir, opts);
1324
+ return minuteRangeLead(schedule.pattern.minute, opts) + ", " + window + trailingQualifier(schedule, opts);
1238
1325
  }
1239
- return rangeMinuteLead(ir, opts) + " " + window + trailingQualifier(ir, opts);
1326
+ return rangeMinuteLead(schedule, opts) + " " + window + trailingQualifier(schedule, opts);
1240
1327
  }
1241
- function rangeMinuteLead(ir, opts) {
1242
- if (ir.pattern.minute === "0") {
1328
+ function rangeMinuteLead(schedule, opts) {
1329
+ if (schedule.pattern.minute === "0") {
1243
1330
  return "every hour";
1244
1331
  }
1245
1332
  return strideFromSegments(
1246
- segmentsOf(ir, "minute"),
1333
+ segmentsOf(schedule, "minute"),
1247
1334
  "minute",
1248
1335
  "hour",
1249
1336
  opts
1250
1337
  ) ?? listPastThe(
1251
- segmentWords(segmentsOf(ir, "minute"), opts),
1338
+ segmentWords(segmentsOf(schedule, "minute"), opts),
1252
1339
  "minute",
1253
1340
  "hour",
1254
1341
  opts
1255
1342
  );
1256
1343
  }
1257
- function renderHourStep(ir, plan, opts) {
1258
- const cadence = unevenHourCadence(ir, opts);
1344
+ function renderHourStep(schedule, plan, opts) {
1345
+ const cadence = unevenHourCadence(schedule, opts);
1259
1346
  if (cadence !== null) {
1260
- return cadence + trailingQualifier(ir, opts);
1347
+ return cadence + trailingQualifier(schedule, opts);
1261
1348
  }
1262
- return stepHours(stepSegment(ir, "hour"), opts) + trailingQualifier(ir, opts);
1349
+ return stepHours(stepSegment(schedule, "hour"), opts) + trailingQualifier(schedule, opts);
1263
1350
  }
1264
1351
  function boundedWindow(plan) {
1265
1352
  const continuous = plan.minuteForm === "wildcard";
@@ -1282,10 +1369,10 @@ function hourWindow(window, opts) {
1282
1369
  to: window.to
1283
1370
  }, opts);
1284
1371
  }
1285
- function renderClockTimes(ir, plan, opts) {
1286
- if (ir.shapes.minute === "single") {
1287
- const minute = +ir.pattern.minute;
1288
- const cadence = hourCadence(ir, minute, opts) ?? hourRangeCadence(ir, minute, opts);
1372
+ function renderClockTimes(schedule, plan, opts) {
1373
+ if (schedule.shapes.minute === "single") {
1374
+ const minute = +schedule.pattern.minute;
1375
+ const cadence = hourCadence(schedule, minute, opts) ?? hourRangeCadence(schedule, minute, opts);
1289
1376
  if (cadence !== null) {
1290
1377
  return cadence;
1291
1378
  }
@@ -1299,47 +1386,52 @@ function renderClockTimes(ir, plan, opts) {
1299
1386
  plain
1300
1387
  }, opts);
1301
1388
  });
1302
- return interpretDayQualifier(ir, opts) + "at " + joinList(times, opts) + dayUnionTrail(ir, opts);
1389
+ return interpretDayQualifier(schedule, opts) + "at " + joinList(times, opts) + dayUnionTrail(schedule, opts);
1303
1390
  }
1304
- function dayUnionTrail(ir, opts) {
1305
- return isDayUnion(ir, opts) ? dayUnionCondition(ir, opts) : "";
1391
+ function dayUnionTrail(schedule, opts) {
1392
+ return isDayUnion(schedule, opts) ? dayUnionCondition(schedule, opts) : "";
1306
1393
  }
1307
- function renderCompactClockTimes(ir, plan, opts) {
1394
+ function renderCompactClockTimes(schedule, plan, opts) {
1308
1395
  if (plan.fold) {
1309
- const cadence2 = hourCadence(ir, +plan.minute, opts) ?? hourRangeCadence(ir, +plan.minute, opts);
1396
+ const cadence2 = hourCadence(schedule, +plan.minute, opts) ?? hourRangeCadence(schedule, +plan.minute, opts);
1310
1397
  if (cadence2 !== null) {
1311
1398
  return cadence2;
1312
1399
  }
1313
- const hasRange = segmentsOf(ir, "hour").some(function range(segment) {
1400
+ const hasRange = segmentsOf(schedule, "hour").some(function range(segment) {
1314
1401
  return segment.kind === "range";
1315
1402
  });
1316
- if (hasRange && !ir.analyses.clockSecond) {
1317
- return foldedHourWindows(ir, plan, opts) + trailingQualifier(ir, opts);
1403
+ if (hasRange && !schedule.analyses.clockSecond) {
1404
+ return foldedHourWindows(schedule, plan, opts) + trailingQualifier(schedule, opts);
1318
1405
  }
1319
- const fold = { minute: plan.minute, second: ir.analyses.clockSecond };
1320
- return interpretDayQualifier(ir, opts) + "at " + hourSegmentTimes(ir, fold, true, opts) + dayUnionTrail(ir, opts);
1406
+ const fold = { minute: plan.minute, second: schedule.analyses.clockSecond };
1407
+ return interpretDayQualifier(schedule, opts) + "at " + hourSegmentTimes(schedule, fold, true, opts) + dayUnionTrail(schedule, opts);
1321
1408
  }
1322
1409
  const minuteLead = (
1323
1410
  // The non-fold branch is a minute list, which has segments. An
1324
1411
  // offset/uneven step enumerated to that list reads as a stride.
1325
- strideFromSegments(segmentsOf(ir, "minute"), "minute", "hour", opts) ?? listPastThe(
1326
- segmentWords(segmentsOf(ir, "minute"), opts),
1412
+ strideFromSegments(
1413
+ segmentsOf(schedule, "minute"),
1414
+ "minute",
1415
+ "hour",
1416
+ opts
1417
+ ) ?? listPastThe(
1418
+ segmentWords(segmentsOf(schedule, "minute"), opts),
1327
1419
  "minute",
1328
1420
  "hour",
1329
1421
  opts
1330
1422
  )
1331
1423
  );
1332
- const cadence = unevenHourCadence(ir, opts);
1333
- const phrase = cadence ? minuteLead + ", " + cadence + trailingQualifier(ir, opts) : minuteLead + ", at " + hourSegmentTimes(ir, { minute: 0, second: null }, true, opts) + trailingQualifier(ir, opts);
1334
- return ir.analyses.clockSecond ? secondsLeadClause(ir, opts) + ", " + phrase : phrase;
1424
+ const cadence = unevenHourCadence(schedule, opts);
1425
+ const phrase = cadence ? minuteLead + ", " + cadence + trailingQualifier(schedule, opts) : minuteLead + ", at " + hourSegmentTimes(schedule, { minute: 0, second: null }, true, opts) + trailingQualifier(schedule, opts);
1426
+ return schedule.analyses.clockSecond ? secondsLeadClause(schedule, opts) + ", " + phrase : phrase;
1335
1427
  }
1336
- function foldedHourWindows(ir, plan, opts) {
1428
+ function foldedHourWindows(schedule, plan, opts) {
1337
1429
  const minute = plan.minute;
1338
1430
  const windows = [];
1339
- const times = collectHourOutliers(ir).map(function time(hour) {
1431
+ const times = collectHourOutliers(schedule).map(function time(hour) {
1340
1432
  return getTime({ hour, minute }, opts);
1341
1433
  });
1342
- segmentsOf(ir, "hour").forEach(function classify(segment) {
1434
+ segmentsOf(schedule, "hour").forEach(function classify(segment) {
1343
1435
  if (segment.kind === "range") {
1344
1436
  windows.push(rangeWindow({
1345
1437
  continuous: false,
@@ -1349,12 +1441,12 @@ function foldedHourWindows(ir, plan, opts) {
1349
1441
  }, opts));
1350
1442
  }
1351
1443
  });
1352
- const phrase = rangeMinuteLead(ir, opts) + " " + joinList(windows, opts);
1444
+ const phrase = rangeMinuteLead(schedule, opts) + " " + joinList(windows, opts);
1353
1445
  return phrase + outlierTail(times, opts);
1354
1446
  }
1355
- function collectHourOutliers(ir) {
1447
+ function collectHourOutliers(schedule) {
1356
1448
  const hours = [];
1357
- segmentsOf(ir, "hour").forEach(function classify(segment) {
1449
+ segmentsOf(schedule, "hour").forEach(function classify(segment) {
1358
1450
  if (segment.kind === "step") {
1359
1451
  hours.push(...segment.fires);
1360
1452
  } else if (segment.kind !== "range") {
@@ -1372,16 +1464,16 @@ function outlierTail(times, opts) {
1372
1464
  function isCadenceField(token) {
1373
1465
  return token === "*" || token.startsWith("*/") && token.indexOf("-") === -1;
1374
1466
  }
1375
- function leadingCadence(ir, opts) {
1376
- const { second, minute } = ir.pattern;
1467
+ function leadingCadence(schedule, opts) {
1468
+ const { second, minute } = schedule.pattern;
1377
1469
  if (isCadenceField(second)) {
1378
- return { secondLead: true, text: secondsClause(ir, "minute", opts) };
1470
+ return { secondLead: true, text: secondsClause(schedule, "minute", opts) };
1379
1471
  }
1380
1472
  if (second === "0" && isCadenceField(minute)) {
1381
1473
  const text = minute === "*" ? "every minute" : (
1382
1474
  // A clean minute step's first segment is a step segment.
1383
1475
  stepCycle60(
1384
- stepSegment(ir, "minute"),
1476
+ stepSegment(schedule, "minute"),
1385
1477
  "minute",
1386
1478
  "hour",
1387
1479
  opts
@@ -1391,19 +1483,19 @@ function leadingCadence(ir, opts) {
1391
1483
  }
1392
1484
  return null;
1393
1485
  }
1394
- function minuteConfinement(ir, opts) {
1395
- const minute = ir.pattern.minute;
1486
+ function minuteConfinement(schedule, opts) {
1487
+ const minute = schedule.pattern.minute;
1396
1488
  if (minute === "*") {
1397
1489
  return "";
1398
1490
  }
1399
1491
  if (isCadenceField(minute)) {
1400
1492
  return " of every other minute";
1401
1493
  }
1402
- const segments = segmentsOf(ir, "minute");
1403
- if (ir.shapes.minute === "single") {
1494
+ const segments = segmentsOf(schedule, "minute");
1495
+ if (schedule.shapes.minute === "single") {
1404
1496
  return " during minute :" + pad(minute);
1405
1497
  }
1406
- if (ir.shapes.minute === "range") {
1498
+ if (schedule.shapes.minute === "range") {
1407
1499
  const bounds = minute.split("-");
1408
1500
  return " during minutes :" + pad(bounds[0]) + through(opts) + ":" + pad(bounds[1]);
1409
1501
  }
@@ -1412,64 +1504,61 @@ function minuteConfinement(ir, opts) {
1412
1504
  });
1413
1505
  return " during minutes " + joinList(values, opts);
1414
1506
  }
1415
- function hourConfinement(ir, opts) {
1416
- const hour = ir.pattern.hour;
1507
+ function hourConfinement(schedule, opts) {
1508
+ const hour = schedule.pattern.hour;
1417
1509
  if (hour === "*") {
1418
- const minutePinned = ir.pattern.minute !== "*" && !isCadenceField(ir.pattern.minute);
1510
+ const minutePinned = schedule.pattern.minute !== "*" && !isCadenceField(schedule.pattern.minute);
1419
1511
  return minutePinned ? " of every hour" : "";
1420
1512
  }
1421
1513
  if (isCadenceField(hour)) {
1422
1514
  return hour === "*/2" ? " of every other hour" : "";
1423
1515
  }
1424
- if (ir.shapes.hour === "single") {
1516
+ if (schedule.shapes.hour === "single") {
1425
1517
  const h = +hour;
1426
- if (ir.shapes.minute === "step") {
1518
+ if (schedule.shapes.minute === "step") {
1427
1519
  return " from " + getTime({ hour: h, minute: 0 }, opts) + " until " + getTime({ hour: (h + 1) % 24, minute: 0 }, opts);
1428
1520
  }
1429
- if (ir.pattern.minute !== "*" && !isCadenceField(ir.pattern.minute)) {
1521
+ if (schedule.pattern.minute !== "*" && !isCadenceField(schedule.pattern.minute)) {
1430
1522
  return " at " + getTime({ hour: h, minute: 0 }, opts);
1431
1523
  }
1432
1524
  return " of the " + getTime({ hour: h, minute: 0 }, opts) + " hour";
1433
1525
  }
1434
- if (ir.shapes.hour === "range") {
1526
+ if (schedule.shapes.hour === "range") {
1435
1527
  const bounds = hour.split("-");
1436
1528
  return " " + rangeWindow({
1437
- continuous: ir.pattern.minute === "*",
1529
+ continuous: schedule.pattern.minute === "*",
1438
1530
  from: +bounds[0],
1439
1531
  throughMinute: 0,
1440
1532
  to: +bounds[1]
1441
1533
  }, opts);
1442
1534
  }
1443
- return " during the " + hourSegmentTimes(ir, { minute: 0, second: null }, false, opts) + " hours";
1444
- }
1445
- function isContiguousHourRange(ir) {
1446
- return ir.shapes.hour === "range";
1535
+ return " during the " + hourSegmentTimes(schedule, { minute: 0, second: null }, false, opts) + " hours";
1447
1536
  }
1448
- function confinableHour(ir) {
1449
- if (ir.shapes.hour !== "step") {
1537
+ function confinableHour(schedule) {
1538
+ if (schedule.shapes.hour !== "step") {
1450
1539
  return true;
1451
1540
  }
1452
- const segment = stepSegment(ir, "hour");
1453
- return ir.pattern.hour === "*/2" || segment.startToken.indexOf("-") !== -1;
1541
+ const segment = stepSegment(schedule, "hour");
1542
+ return schedule.pattern.hour === "*/2" || segment.startToken.indexOf("-") !== -1;
1454
1543
  }
1455
- function isMinuteStride(ir) {
1456
- if (ir.shapes.minute !== "list") {
1544
+ function isMinuteStride(schedule) {
1545
+ if (schedule.shapes.minute !== "list") {
1457
1546
  return false;
1458
1547
  }
1459
- const values = singleValues(segmentsOf(ir, "minute"));
1548
+ const values = singleValues(segmentsOf(schedule, "minute"));
1460
1549
  return values !== null && arithmeticStep(values) !== null;
1461
1550
  }
1462
- function confinementEligible(ir, lead) {
1463
- const { minute, hour } = ir.pattern;
1551
+ function confinementEligible(schedule, lead) {
1552
+ const { minute, hour } = schedule.pattern;
1464
1553
  const minuteStep = isCadenceField(minute) && minute !== "*";
1465
- if (!confinableHour(ir)) {
1554
+ if (!confinableHour(schedule)) {
1466
1555
  return false;
1467
1556
  }
1468
1557
  if (lead.secondLead) {
1469
1558
  if (minuteStep) {
1470
- return minute === "*/2" && !isContiguousHourRange(ir);
1559
+ return minute === "*/2" && schedule.shapes.hour !== "range";
1471
1560
  }
1472
- if (isMinuteStride(ir) || ir.shapes.minute === "list" && ir.shapes.hour === "list") {
1561
+ if (isMinuteStride(schedule) || schedule.shapes.minute === "list" && schedule.shapes.hour === "list") {
1473
1562
  return false;
1474
1563
  }
1475
1564
  return true;
@@ -1477,21 +1566,21 @@ function confinementEligible(ir, lead) {
1477
1566
  if (hour === "*/2") {
1478
1567
  return true;
1479
1568
  }
1480
- return ir.shapes.hour === "single" && minute === "*/2";
1569
+ return schedule.shapes.hour === "single" && minute === "*/2";
1481
1570
  }
1482
- function confinement(ir, opts) {
1571
+ function confinement(schedule, opts) {
1483
1572
  if (!opts.style.untilWindow || opts.short) {
1484
1573
  return null;
1485
1574
  }
1486
- if (ir.pattern.minute === "*" && ir.pattern.hour === "*") {
1575
+ if (schedule.pattern.minute === "*" && schedule.pattern.hour === "*") {
1487
1576
  return null;
1488
1577
  }
1489
- const lead = leadingCadence(ir, opts);
1490
- if (!lead || !confinementEligible(ir, lead)) {
1578
+ const lead = leadingCadence(schedule, opts);
1579
+ if (!lead || !confinementEligible(schedule, lead)) {
1491
1580
  return null;
1492
1581
  }
1493
- const minutePart = lead.secondLead ? minuteConfinement(ir, opts) : "";
1494
- return lead.text + minutePart + hourConfinement(ir, opts) + trailingQualifier(ir, opts);
1582
+ const minutePart = lead.secondLead ? minuteConfinement(schedule, opts) : "";
1583
+ return lead.text + minutePart + hourConfinement(schedule, opts) + trailingQualifier(schedule, opts);
1495
1584
  }
1496
1585
  var renderers = {
1497
1586
  clockTimes: renderClockTimes,
@@ -1513,23 +1602,25 @@ var renderers = {
1513
1602
  singleMinute: renderSingleMinute,
1514
1603
  standaloneSeconds: renderStandaloneSeconds
1515
1604
  };
1516
- function renderStride(stride, opts) {
1605
+ function renderStride2(stride, opts) {
1517
1606
  const { interval, start, last, cycle, unit, anchor } = stride;
1518
1607
  const cadence = "every " + getNumber(interval, opts) + " " + unit + "s";
1519
- const tiles = cycle % interval === 0;
1520
- if (start === 0 && tiles) {
1521
- return cadence;
1522
- }
1523
- if (start < interval && tiles) {
1524
- return cadence + " from " + getNumber(start, opts) + " " + pluralize(start, unit) + " past the " + anchor;
1525
- }
1526
- const num = seriesNumber();
1527
- return cadence + " from " + num(start) + through(opts) + num(last) + " " + pluralize(last, unit) + " past the " + anchor;
1608
+ return renderStride({ start, interval, cycle }, {
1609
+ bare: () => cadence,
1610
+ // A clean wrap from a non-zero offset: name the start, no endpoint.
1611
+ offset: () => cadence + " from " + getNumber(start, opts) + " " + pluralize(start, unit) + " past the " + anchor,
1612
+ // A bounded, non-wrapping set: pin both endpoints. Each bound is a value,
1613
+ // so it reads as a digit, matching the range idiom ("from 0 through 30").
1614
+ bounded: () => {
1615
+ const num = seriesNumber();
1616
+ return cadence + " from " + num(start) + through(opts) + num(last) + " " + pluralize(last, unit) + " past the " + anchor;
1617
+ }
1618
+ });
1528
1619
  }
1529
1620
  function strideFromSegments(segments, unit, anchor, opts) {
1530
1621
  const values = singleValues(segments);
1531
1622
  const step = values && arithmeticStep(values);
1532
- return step ? renderStride({ ...step, cycle: 60, unit, anchor }, opts) : null;
1623
+ return step ? renderStride2({ ...step, cycle: 60, unit, anchor }, opts) : null;
1533
1624
  }
1534
1625
  function stepCycle60(segment, unit, anchor, opts) {
1535
1626
  if (segment.startToken.indexOf("-") !== -1) {
@@ -1539,7 +1630,7 @@ function stepCycle60(segment, unit, anchor, opts) {
1539
1630
  if (start !== 0 && segment.fires.length <= 3) {
1540
1631
  return listPastThe(numberWords(segment.fires, opts), unit, anchor, opts);
1541
1632
  }
1542
- return renderStride({
1633
+ return renderStride2({
1543
1634
  interval: segment.interval,
1544
1635
  start,
1545
1636
  last: segment.fires[segment.fires.length - 1],
@@ -1565,24 +1656,21 @@ function stepHours(segment, opts) {
1565
1656
  function hourStrideCadence(stride, opts) {
1566
1657
  const { start, interval, last } = stride;
1567
1658
  const cadence = "every " + getNumber(interval, opts) + " hours";
1568
- const tiles = 24 % interval === 0;
1569
- if (start === 0 && tiles) {
1570
- return cadence;
1571
- }
1572
- if (start < interval && tiles) {
1573
- return cadence + " from " + getTime({ hour: start, minute: 0 }, opts);
1574
- }
1575
- return cadence + " from " + getTime({ hour: start, minute: 0 }, opts) + through(opts) + getTime({ hour: last, minute: 0 }, opts);
1659
+ return renderStride({ start, interval, cycle: 24 }, {
1660
+ bare: () => cadence,
1661
+ offset: () => cadence + " from " + getTime({ hour: start, minute: 0 }, opts),
1662
+ bounded: () => cadence + " from " + getTime({ hour: start, minute: 0 }, opts) + through(opts) + getTime({ hour: last, minute: 0 }, opts)
1663
+ });
1576
1664
  }
1577
- function unevenHourCadence(ir, opts) {
1578
- const stride = hourStride(ir);
1665
+ function unevenHourCadence(schedule, opts) {
1666
+ const stride = hourStride(schedule);
1579
1667
  if (!stride || offsetCleanStride(stride)) {
1580
1668
  return null;
1581
1669
  }
1582
1670
  return hourStrideCadence(stride, opts);
1583
1671
  }
1584
- function hourStride(ir) {
1585
- const segments = segmentsOf(ir, "hour");
1672
+ function hourStride(schedule) {
1673
+ const segments = segmentsOf(schedule, "hour");
1586
1674
  if (segments.length === 1 && segments[0].kind === "step") {
1587
1675
  const segment = segments[0];
1588
1676
  if (segment.fires.length < 2) {
@@ -1594,57 +1682,57 @@ function hourStride(ir) {
1594
1682
  const values = singleValues(segments);
1595
1683
  return values && hourListStride(values);
1596
1684
  }
1597
- function subMinuteSecond(ir) {
1598
- return ir.pattern.second === "*" || ir.shapes.second === "step";
1685
+ function subMinuteSecond(schedule) {
1686
+ return schedule.pattern.second === "*" || schedule.shapes.second === "step";
1599
1687
  }
1600
- function hourCadenceLead(ir, minute, opts) {
1688
+ function hourCadenceLead(schedule, minute, opts) {
1601
1689
  if (minute === 0) {
1602
- if (subMinuteSecond(ir)) {
1603
- return secondsClause(ir, "minute", opts) + " for one minute";
1690
+ if (subMinuteSecond(schedule)) {
1691
+ return secondsClause(schedule, "minute", opts) + " for one minute";
1604
1692
  }
1605
- return secondsClause(ir, "hour", opts);
1693
+ return secondsClause(schedule, "hour", opts);
1606
1694
  }
1607
1695
  const minutePhrase = getNumber(minute, opts) + " " + pluralize(minute, "minute") + " past the hour";
1608
- if (ir.pattern.second === "0") {
1696
+ if (schedule.pattern.second === "0") {
1609
1697
  return minutePhrase;
1610
1698
  }
1611
- return secondsClause(ir, "minute", opts) + ", " + minutePhrase;
1699
+ return secondsClause(schedule, "minute", opts) + ", " + minutePhrase;
1612
1700
  }
1613
- function hourCadence(ir, minute, opts) {
1614
- const stride = hourStride(ir);
1701
+ function hourCadence(schedule, minute, opts) {
1702
+ const stride = hourStride(schedule);
1615
1703
  if (!stride) {
1616
1704
  return null;
1617
1705
  }
1618
1706
  const fires = (stride.last - stride.start) / stride.interval + 1;
1619
- if (ir.pattern.second === "0" && fires <= maxClockTimes && offsetCleanStride(stride)) {
1707
+ if (schedule.pattern.second === "0" && fires <= maxClockTimes && offsetCleanStride(stride)) {
1620
1708
  return null;
1621
1709
  }
1622
- const minuteZeroStride = minute === 0 && subMinuteSecond(ir) && cleanStrideSegment(ir);
1710
+ const minuteZeroStride = minute === 0 && subMinuteSecond(schedule) && cleanStrideSegment(schedule);
1623
1711
  if (minuteZeroStride) {
1624
- return secondsClause(ir, "minute", opts) + " for one minute " + everyNthHour(minuteZeroStride, opts) + trailingQualifier(ir, opts);
1712
+ return secondsClause(schedule, "minute", opts) + " for one minute " + everyNthHour(minuteZeroStride, opts) + trailingQualifier(schedule, opts);
1625
1713
  }
1626
- if (minute === 0 && ir.pattern.second === "0") {
1627
- return hourStrideCadence(stride, opts) + trailingQualifier(ir, opts);
1714
+ if (minute === 0 && schedule.pattern.second === "0") {
1715
+ return hourStrideCadence(stride, opts) + trailingQualifier(schedule, opts);
1628
1716
  }
1629
- return hourCadenceLead(ir, minute, opts) + ", " + hourStrideCadence(stride, opts) + trailingQualifier(ir, opts);
1717
+ return hourCadenceLead(schedule, minute, opts) + ", " + hourStrideCadence(stride, opts) + trailingQualifier(schedule, opts);
1630
1718
  }
1631
- function cleanStrideSegment(ir) {
1632
- const segments = segmentsOf(ir, "hour");
1719
+ function cleanStrideSegment(schedule) {
1720
+ const segments = segmentsOf(schedule, "hour");
1633
1721
  const segment = segments.length === 1 && segments[0];
1634
1722
  if (!segment || segment.kind !== "step" || segment.startToken.indexOf("-") !== -1 || !(segment.interval in stepOrdinals)) {
1635
1723
  return null;
1636
1724
  }
1637
1725
  return segment;
1638
1726
  }
1639
- function hasHourWindow(ir) {
1640
- return segmentsOf(ir, "hour").some(function range(segment) {
1727
+ function hasHourWindow(schedule) {
1728
+ return segmentsOf(schedule, "hour").some(function range(segment) {
1641
1729
  return segment.kind === "range";
1642
1730
  });
1643
1731
  }
1644
- function hourRangeWindowTail(ir, opts) {
1732
+ function hourRangeWindowTail(schedule, opts) {
1645
1733
  const windows = [];
1646
- const outlierHours = collectHourOutliers(ir);
1647
- segmentsOf(ir, "hour").forEach(function classify(segment) {
1734
+ const outlierHours = collectHourOutliers(schedule);
1735
+ segmentsOf(schedule, "hour").forEach(function classify(segment) {
1648
1736
  if (segment.kind === "range") {
1649
1737
  windows.push(rangeWindow({
1650
1738
  continuous: false,
@@ -1660,17 +1748,17 @@ function hourRangeWindowTail(ir, opts) {
1660
1748
  });
1661
1749
  return phrase + outlierTail(times, opts);
1662
1750
  }
1663
- function hourRangeCadence(ir, minute, opts) {
1664
- if (minute !== 0 || !hasHourWindow(ir)) {
1751
+ function hourRangeCadence(schedule, minute, opts) {
1752
+ if (minute !== 0 || !hasHourWindow(schedule)) {
1665
1753
  return null;
1666
1754
  }
1667
- if (ir.pattern.second === "0") {
1755
+ if (schedule.pattern.second === "0") {
1668
1756
  return null;
1669
1757
  }
1670
- if (subMinuteSecond(ir)) {
1671
- return secondsClause(ir, "minute", opts) + " for one minute during the " + hourSegmentTimes(ir, { minute: 0, second: null }, false, opts) + " hours" + trailingQualifier(ir, opts);
1758
+ if (subMinuteSecond(schedule)) {
1759
+ return secondsClause(schedule, "minute", opts) + " for one minute during the " + hourSegmentTimes(schedule, { minute: 0, second: null }, false, opts) + " hours" + trailingQualifier(schedule, opts);
1672
1760
  }
1673
- return hourCadenceLead(ir, minute, opts) + ", " + hourRangeWindowTail(ir, opts) + trailingQualifier(ir, opts);
1761
+ return hourCadenceLead(schedule, minute, opts) + ", " + hourRangeWindowTail(schedule, opts) + trailingQualifier(schedule, opts);
1674
1762
  }
1675
1763
  function seriesNumber() {
1676
1764
  return function format(n) {
@@ -1729,11 +1817,11 @@ function hourTimes(hours, opts) {
1729
1817
  function singleHourFire(times) {
1730
1818
  return times.kind === "fires" && times.fires.length === 1;
1731
1819
  }
1732
- function hourTimesFromPlan(ir, times, atContext, opts) {
1820
+ function hourTimesFromPlan(schedule, times, atContext, opts) {
1733
1821
  if (times.kind === "fires") {
1734
1822
  return hourTimes(times.fires, opts);
1735
1823
  }
1736
- return hourSegmentTimes(ir, { minute: 0, second: null }, atContext, opts);
1824
+ return hourSegmentTimes(schedule, { minute: 0, second: null }, atContext, opts);
1737
1825
  }
1738
1826
  function segmentHours(segment) {
1739
1827
  if (segment.kind === "range") {
@@ -1741,9 +1829,9 @@ function segmentHours(segment) {
1741
1829
  }
1742
1830
  return segment.kind === "step" ? segment.fires : [segment.value];
1743
1831
  }
1744
- function hourSegmentTimes(ir, fold, atContext, opts) {
1832
+ function hourSegmentTimes(schedule, fold, atContext, opts) {
1745
1833
  const { minute, second } = fold;
1746
- const segments = segmentsOf(ir, "hour");
1834
+ const segments = segmentsOf(schedule, "hour");
1747
1835
  const plain = mixedTwelve(segments.flatMap(function entries(segment) {
1748
1836
  return segmentHours(segment).map(function entry(hour) {
1749
1837
  return { hour: +hour, minute, second };
@@ -1806,85 +1894,85 @@ var leadingWords = {
1806
1894
  stepDate: "",
1807
1895
  weekday: "every "
1808
1896
  };
1809
- function trailingQualifier(ir, opts) {
1810
- if (isDayUnion(ir, opts)) {
1811
- return dayUnionCondition(ir, opts);
1897
+ function trailingQualifier(schedule, opts) {
1898
+ if (isDayUnion(schedule, opts)) {
1899
+ return dayUnionCondition(schedule, opts);
1812
1900
  }
1813
- const phrase = dayQualifier(ir, trailingWords, opts);
1901
+ const phrase = dayQualifier(schedule, trailingWords, opts);
1814
1902
  return phrase && " " + phrase;
1815
1903
  }
1816
- function interpretDayQualifier(ir, opts) {
1817
- if (isDayUnion(ir, opts)) {
1904
+ function interpretDayQualifier(schedule, opts) {
1905
+ if (isDayUnion(schedule, opts)) {
1818
1906
  return "";
1819
1907
  }
1820
- return dayQualifier(ir, leadingWords, opts) + " ";
1908
+ return dayQualifier(schedule, leadingWords, opts) + " ";
1821
1909
  }
1822
- function dayQualifier(ir, words, opts) {
1823
- const pattern = ir.pattern;
1910
+ function dayQualifier(schedule, words, opts) {
1911
+ const pattern = schedule.pattern;
1824
1912
  if (pattern.date !== "*" && pattern.weekday !== "*") {
1825
- return dateOrWeekday(ir, opts);
1913
+ return dateOrWeekday(schedule, opts);
1826
1914
  }
1827
1915
  if (pattern.date !== "*") {
1828
- return datePhrase(ir, words, opts);
1916
+ return datePhrase(schedule, words, opts);
1829
1917
  }
1830
1918
  if (pattern.weekday !== "*") {
1831
1919
  const quartzWeekday = quartzWeekdayPhrase(pattern.weekday, opts);
1832
1920
  if (quartzWeekday) {
1833
- return monthScopeForRecurrence(quartzWeekday, ir, opts);
1921
+ return monthScopeForRecurrence(quartzWeekday, schedule, opts);
1834
1922
  }
1835
- const weekdays = words.weekday + weekdayPhrase(ir, words.recurringWeekday, opts);
1836
- return weekdays + monthScope(ir, opts);
1923
+ const weekdays = words.weekday + weekdayPhrase(schedule, words.recurringWeekday, opts);
1924
+ return weekdays + monthScope(schedule, opts);
1837
1925
  }
1838
1926
  if (pattern.month !== "*") {
1839
- return words.month + monthName(ir, opts);
1927
+ return words.month + monthName(schedule, opts);
1840
1928
  }
1841
1929
  return words.all;
1842
1930
  }
1843
- function datePhrase(ir, words, opts) {
1844
- const pattern = ir.pattern;
1931
+ function datePhrase(schedule, words, opts) {
1932
+ const pattern = schedule.pattern;
1845
1933
  const quartzDate = quartzDatePhrase(pattern.date, opts);
1846
1934
  if (quartzDate) {
1847
- return monthScopeForRecurrence(quartzDate, ir, opts);
1935
+ return monthScopeForRecurrence(quartzDate, schedule, opts);
1848
1936
  }
1849
1937
  if (isOpenStep(pattern.date)) {
1850
1938
  return monthScopeForRecurrence(
1851
1939
  words.stepDate + stepDates(pattern.date),
1852
- ir,
1940
+ schedule,
1853
1941
  opts
1854
1942
  );
1855
1943
  }
1856
- if (pattern.month !== "*" && !monthFoldsIntoDate(ir)) {
1857
- return "on the " + dateOrdinals(ir, opts) + monthScope(ir, opts);
1944
+ if (pattern.month !== "*" && !monthFoldsIntoDate(schedule)) {
1945
+ return "on the " + dateOrdinals(schedule, opts) + monthScope(schedule, opts);
1858
1946
  }
1859
1947
  if (pattern.month !== "*") {
1860
- return "on " + monthDatePhrase(ir, opts);
1948
+ return "on " + monthDatePhrase(schedule, opts);
1861
1949
  }
1862
- return "on the " + dateOrdinals(ir, opts);
1950
+ return "on the " + dateOrdinals(schedule, opts);
1863
1951
  }
1864
- function monthFoldsIntoDate(ir) {
1865
- return !oddEvenMonth(ir.pattern.month) && // Reached only with a restricted month, which has segments.
1866
- segmentsOf(ir, "month").every(function flat(segment) {
1952
+ function monthFoldsIntoDate(schedule) {
1953
+ return !oddEvenMonth(schedule.pattern.month) && // Reached only with a restricted month, which has segments.
1954
+ segmentsOf(schedule, "month").every(function flat(segment) {
1867
1955
  return segment.kind !== "range";
1868
1956
  });
1869
1957
  }
1870
- function isDayUnion(ir, opts) {
1871
- return ir.pattern.date !== "*" && ir.pattern.weekday !== "*" && !!opts.style.untilWindow && !opts.short;
1958
+ function isDayUnion(schedule, opts) {
1959
+ return schedule.pattern.date !== "*" && schedule.pattern.weekday !== "*" && !!opts.style.untilWindow && !opts.short;
1872
1960
  }
1873
- function dayUnionCondition(ir, opts) {
1961
+ function dayUnionCondition(schedule, opts) {
1874
1962
  const pieces = [
1875
- ...dayUnionDatePieces(ir, opts),
1876
- ...dayUnionWeekdayPieces(ir, opts)
1963
+ ...dayUnionDatePieces(schedule, opts),
1964
+ ...dayUnionWeekdayPieces(schedule, opts)
1877
1965
  ];
1878
1966
  return " whenever the day is " + joinOr(pieces, opts);
1879
1967
  }
1880
- function dayUnionMonthLead(ir, opts) {
1881
- if (ir.pattern.month === "*") {
1968
+ function dayUnionMonthLead(schedule, opts) {
1969
+ if (schedule.pattern.month === "*") {
1882
1970
  return "";
1883
1971
  }
1884
- return "in " + monthName(ir, opts) + " ";
1972
+ return "in " + monthName(schedule, opts) + " ";
1885
1973
  }
1886
- function dayUnionDatePieces(ir, opts) {
1887
- const dateField = ir.pattern.date;
1974
+ function dayUnionDatePieces(schedule, opts) {
1975
+ const dateField = schedule.pattern.date;
1888
1976
  const quartz = quartzDatePhrase(dateField, opts);
1889
1977
  if (quartz) {
1890
1978
  return [quartz.replace(/^on /, "")];
@@ -1894,7 +1982,7 @@ function dayUnionDatePieces(ir, opts) {
1894
1982
  return [oddEven];
1895
1983
  }
1896
1984
  const pieces = [];
1897
- segmentsOf(ir, "date").forEach(function expand(segment) {
1985
+ segmentsOf(schedule, "date").forEach(function expand(segment) {
1898
1986
  if (segment.kind === "range") {
1899
1987
  pieces.push("from the " + getOrdinal(segment.bounds[0]) + through(opts) + "the " + getOrdinal(segment.bounds[1]));
1900
1988
  } else if (segment.kind === "step") {
@@ -1907,14 +1995,14 @@ function dayUnionDatePieces(ir, opts) {
1907
1995
  });
1908
1996
  return pieces;
1909
1997
  }
1910
- function dayUnionWeekdayPieces(ir, opts) {
1911
- const weekdayField = ir.pattern.weekday;
1998
+ function dayUnionWeekdayPieces(schedule, opts) {
1999
+ const weekdayField = schedule.pattern.weekday;
1912
2000
  const quartz = quartzWeekdayPhrase(weekdayField, opts);
1913
2001
  if (quartz) {
1914
2002
  return [quartz.replace(/^on /, "")];
1915
2003
  }
1916
2004
  const pieces = [];
1917
- segmentsOf(ir, "weekday").forEach(function expand(segment) {
2005
+ segmentsOf(schedule, "weekday").forEach(function expand(segment) {
1918
2006
  if (segment.kind === "range" && segment.bounds[0] === "1" && segment.bounds[1] === "5") {
1919
2007
  pieces.push("a weekday");
1920
2008
  } else if (segment.kind === "range") {
@@ -1942,16 +2030,16 @@ function oddEvenDay(dateField) {
1942
2030
  }
1943
2031
  return start === "2" ? "an even-numbered day" : null;
1944
2032
  }
1945
- function dateOrWeekday(ir, opts) {
1946
- const pattern = ir.pattern;
1947
- const weekdayPart = quartzWeekdayPhrase(pattern.weekday, opts) || "on " + weekdayPhrase(ir, false, opts);
1948
- if (pattern.month !== "*" && monthFoldsIntoDate(ir) && !quartzDatePhrase(pattern.date, opts) && !isOpenStep(pattern.date)) {
1949
- return "on " + monthDatePhrase(ir, opts) + " or " + weekdayPart + " in " + monthName(ir, opts);
2033
+ function dateOrWeekday(schedule, opts) {
2034
+ const pattern = schedule.pattern;
2035
+ const weekdayPart = quartzWeekdayPhrase(pattern.weekday, opts) || "on " + weekdayPhrase(schedule, false, opts);
2036
+ if (pattern.month !== "*" && monthFoldsIntoDate(schedule) && !quartzDatePhrase(pattern.date, opts) && !isOpenStep(pattern.date)) {
2037
+ return "on " + monthDatePhrase(schedule, opts) + " or " + weekdayPart + " in " + monthName(schedule, opts);
1950
2038
  }
1951
- return datePart(ir, opts) + " or " + weekdayPart + orMonthScope(ir, opts);
2039
+ return datePart(schedule, opts) + " or " + weekdayPart + orMonthScope(schedule, opts);
1952
2040
  }
1953
- function datePart(ir, opts) {
1954
- const pattern = ir.pattern;
2041
+ function datePart(schedule, opts) {
2042
+ const pattern = schedule.pattern;
1955
2043
  const quartzDate = quartzDatePhrase(pattern.date, opts);
1956
2044
  if (quartzDate) {
1957
2045
  return quartzDate;
@@ -1959,13 +2047,13 @@ function datePart(ir, opts) {
1959
2047
  if (isOpenStep(pattern.date)) {
1960
2048
  return stepDates(pattern.date);
1961
2049
  }
1962
- return "on the " + dateOrdinals(ir, opts);
2050
+ return "on the " + dateOrdinals(schedule, opts);
1963
2051
  }
1964
- function orMonthScope(ir, opts) {
1965
- if (ir.pattern.month === "*") {
2052
+ function orMonthScope(schedule, opts) {
2053
+ if (schedule.pattern.month === "*") {
1966
2054
  return "";
1967
2055
  }
1968
- return ", in " + monthName(ir, opts);
2056
+ return ", in " + monthName(schedule, opts);
1969
2057
  }
1970
2058
  function quartzDatePhrase(dateField, opts) {
1971
2059
  if (dateField === "L") {
@@ -1992,39 +2080,39 @@ function quartzWeekdayPhrase(weekdayField, opts) {
1992
2080
  return "on the last " + getWeekday(weekdayField.slice(0, -1), opts) + " of the month";
1993
2081
  }
1994
2082
  }
1995
- function monthDatePhrase(ir, opts) {
1996
- const month = monthName(ir, opts);
2083
+ function monthDatePhrase(schedule, opts) {
2084
+ const month = monthName(schedule, opts);
1997
2085
  const days = renderSegments(
1998
- segmentsOf(ir, "date"),
2086
+ segmentsOf(schedule, "date"),
1999
2087
  opts.style.ordinals ? getOrdinal : cardinalDay,
2000
2088
  opts
2001
2089
  );
2002
- if (opts.style.dayFirst && ir.shapes.date === "single" && ir.shapes.month !== "single") {
2003
- return "the " + getOrdinal(ir.pattern.date) + " of " + month;
2090
+ if (opts.style.dayFirst && schedule.shapes.date === "single" && schedule.shapes.month !== "single") {
2091
+ return "the " + getOrdinal(schedule.pattern.date) + " of " + month;
2004
2092
  }
2005
2093
  return opts.style.dayFirst ? days + " " + month : month + " " + days;
2006
2094
  }
2007
2095
  function cardinalDay(value) {
2008
2096
  return "" + value;
2009
2097
  }
2010
- function monthScope(ir, opts) {
2011
- if (ir.pattern.month === "*") {
2098
+ function monthScope(schedule, opts) {
2099
+ if (schedule.pattern.month === "*") {
2012
2100
  return "";
2013
2101
  }
2014
- return " in " + monthName(ir, opts);
2102
+ return " in " + monthName(schedule, opts);
2015
2103
  }
2016
- function monthScopeForRecurrence(phrase, ir, opts) {
2017
- if (ir.pattern.month === "*") {
2104
+ function monthScopeForRecurrence(phrase, schedule, opts) {
2105
+ if (schedule.pattern.month === "*") {
2018
2106
  return phrase;
2019
2107
  }
2020
2108
  const carriesRecurrence = phrase.indexOf(" of the month") !== -1;
2021
- if (carriesRecurrence && ir.shapes.month === "range") {
2022
- return phrase.replace(" of the month", " of each month") + " from " + monthName(ir, opts);
2109
+ if (carriesRecurrence && schedule.shapes.month === "range") {
2110
+ return phrase.replace(" of the month", " of each month") + " from " + monthName(schedule, opts);
2023
2111
  }
2024
- if (carriesRecurrence && (ir.shapes.month === "single" || ir.shapes.month === "step")) {
2025
- return phrase.replace(" of the month", "") + " in " + monthName(ir, opts);
2112
+ if (carriesRecurrence && (schedule.shapes.month === "single" || schedule.shapes.month === "step")) {
2113
+ return phrase.replace(" of the month", "") + " in " + monthName(schedule, opts);
2026
2114
  }
2027
- return phrase + " in " + monthName(ir, opts);
2115
+ return phrase + " in " + monthName(schedule, opts);
2028
2116
  }
2029
2117
  function stepDates(dateField) {
2030
2118
  const parts = dateField.split("/");
@@ -2037,15 +2125,15 @@ function stepDates(dateField) {
2037
2125
  }
2038
2126
  return phrase;
2039
2127
  }
2040
- function dateOrdinals(ir, opts) {
2041
- return renderSegments(segmentsOf(ir, "date"), getOrdinal, opts);
2128
+ function dateOrdinals(schedule, opts) {
2129
+ return renderSegments(segmentsOf(schedule, "date"), getOrdinal, opts);
2042
2130
  }
2043
- function monthName(ir, opts) {
2044
- const oddEven = oddEvenMonth(ir.pattern.month);
2131
+ function monthName(schedule, opts) {
2132
+ const oddEven = oddEvenMonth(schedule.pattern.month);
2045
2133
  if (oddEven) {
2046
2134
  return oddEven;
2047
2135
  }
2048
- return renderSegments(segmentsOf(ir, "month"), function name(value) {
2136
+ return renderSegments(segmentsOf(schedule, "month"), function name(value) {
2049
2137
  return getMonth(value, opts);
2050
2138
  }, opts);
2051
2139
  }
@@ -2062,8 +2150,8 @@ function oddEvenMonth(monthField) {
2062
2150
  }
2063
2151
  return start === "2" ? "every even-numbered month" : null;
2064
2152
  }
2065
- function weekdayPhrase(ir, recurring, opts) {
2066
- const segments = orderWeekdaysForDisplay(segmentsOf(ir, "weekday"));
2153
+ function weekdayPhrase(schedule, recurring, opts) {
2154
+ const segments = orderWeekdaysForDisplay(segmentsOf(schedule, "weekday"));
2067
2155
  const hasRange = segments.some(function range(segment) {
2068
2156
  return segment.kind === "range";
2069
2157
  });
@@ -2091,8 +2179,8 @@ function renderSegments(segments, word, opts) {
2091
2179
  });
2092
2180
  return joinList(pieces, opts);
2093
2181
  }
2094
- function applyYear(description, ir, opts) {
2095
- const yearField = ir.pattern.year;
2182
+ function applyYear(description, schedule, opts) {
2183
+ const yearField = schedule.pattern.year;
2096
2184
  if (yearField === "*") {
2097
2185
  return description;
2098
2186
  }
@@ -2100,7 +2188,7 @@ function applyYear(description, ir, opts) {
2100
2188
  return description + ", " + stepYears(yearField, opts);
2101
2189
  }
2102
2190
  const label = yearLabel(yearField, opts);
2103
- if (yearField.indexOf("-") === -1 && yearField.indexOf(",") === -1 && ir.pattern.date !== "*" && description.indexOf(" at ") !== -1) {
2191
+ if (yearField.indexOf("-") === -1 && yearField.indexOf(",") === -1 && schedule.pattern.date !== "*" && description.indexOf(" at ") !== -1) {
2104
2192
  const yearGlue = opts.style.dayFirst ? " " : ", ";
2105
2193
  return description.replace(" at ", yearGlue + label + " at ");
2106
2194
  }
@@ -2223,9 +2311,9 @@ function interpretCronPattern(cronPattern, lang, opts) {
2223
2311
  if (typeof cronPattern === "string" && cronPattern.trim().toLowerCase() === "@reboot") {
2224
2312
  return lang.reboot;
2225
2313
  }
2226
- const ir = analyze(prepare(cronPattern, opts));
2227
- const plan = lang.plan ? lang.plan(ir, ir.plan) : ir.plan;
2228
- return lang.describe({ ...ir, plan }, opts);
2314
+ const schedule = analyze(prepare(cronPattern, opts));
2315
+ const plan = lang.plan ? lang.plan(schedule, schedule.plan) : schedule.plan;
2316
+ return lang.describe({ ...schedule, plan }, opts);
2229
2317
  }
2230
2318
  var cronli5_default = cronli5;
2231
2319
  /**