cronli5 0.2.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/CHANGELOG.md +90 -0
  2. package/README.md +4 -4
  3. package/cronli5.min.js +2 -2
  4. package/dist/cronli5.cjs +514 -407
  5. package/dist/cronli5.js +514 -407
  6. package/dist/lang/de.cjs +296 -225
  7. package/dist/lang/de.js +296 -225
  8. package/dist/lang/en.cjs +471 -364
  9. package/dist/lang/en.js +471 -364
  10. package/dist/lang/es.cjs +318 -281
  11. package/dist/lang/es.js +318 -281
  12. package/dist/lang/fi.cjs +326 -276
  13. package/dist/lang/fi.js +326 -276
  14. package/dist/lang/zh.cjs +308 -236
  15. package/dist/lang/zh.js +308 -236
  16. package/package.json +1 -1
  17. package/src/core/analyze.ts +22 -21
  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} +23 -24
  23. package/src/core/shapes.ts +8 -1
  24. package/src/core/specs.ts +1 -1
  25. package/src/core/util.ts +4 -83
  26. package/src/core/validate.ts +2 -2
  27. package/src/core/weekday.ts +54 -0
  28. package/src/cronli5.ts +7 -7
  29. package/src/lang/de/index.ts +329 -288
  30. package/src/lang/en/dialects.ts +1 -1
  31. package/src/lang/en/index.ts +640 -516
  32. package/src/lang/es/index.ts +342 -374
  33. package/src/lang/es/notes.md +1 -1
  34. package/src/lang/fi/dialects.ts +1 -1
  35. package/src/lang/fi/index.ts +367 -372
  36. package/src/lang/fi/notes.md +23 -8
  37. package/src/lang/fi/status.json +1 -1
  38. package/src/lang/zh/index.ts +344 -262
  39. package/src/types.ts +6 -6
  40. package/types/core/analyze.d.ts +4 -4
  41. package/types/core/cadence.d.ts +33 -0
  42. package/types/core/index.d.ts +3 -1
  43. package/types/core/normalize.d.ts +1 -1
  44. package/types/core/parse.d.ts +1 -1
  45. package/types/core/{ir.d.ts → schedule.d.ts} +16 -21
  46. package/types/core/shapes.d.ts +2 -1
  47. package/types/core/specs.d.ts +1 -1
  48. package/types/core/util.d.ts +1 -15
  49. package/types/core/weekday.d.ts +10 -0
  50. package/types/lang/de/index.d.ts +1 -1
  51. package/types/lang/en/dialects.d.ts +1 -1
  52. package/types/lang/en/index.d.ts +1 -1
  53. package/types/lang/es/index.d.ts +1 -1
  54. package/types/lang/fi/dialects.d.ts +1 -1
  55. package/types/lang/fi/index.d.ts +1 -1
  56. package/types/lang/zh/index.d.ts +1 -1
  57. package/types/types.d.ts +5 -5
package/dist/lang/es.cjs CHANGED
@@ -57,6 +57,16 @@ function isNonNegativeInteger(value) {
57
57
  const digits = /^\d+$/;
58
58
  return digits.test(value);
59
59
  }
60
+ function toFieldNumber(token, numberMap) {
61
+ return isNonNegativeInteger(token) ? +token : numberMap[token.toUpperCase()];
62
+ }
63
+
64
+ // src/core/shapes.ts
65
+ function isOpenStep(field) {
66
+ return field.indexOf("/") !== -1 && field.indexOf("-") === -1 && field.indexOf(",") === -1;
67
+ }
68
+
69
+ // src/core/cadence.ts
60
70
  function arithmeticStep(values) {
61
71
  if (values.length < 5) {
62
72
  return null;
@@ -72,6 +82,56 @@ function arithmeticStep(values) {
72
82
  }
73
83
  return { start: values[0], interval, last: values[values.length - 1] };
74
84
  }
85
+ function segmentsOf(schedule, field) {
86
+ return schedule.analyses.segments[field] ?? [];
87
+ }
88
+ function stepSegment(schedule, field) {
89
+ return segmentsOf(schedule, field)[0];
90
+ }
91
+ function singleValues(segments) {
92
+ const values = [];
93
+ for (const segment of segments) {
94
+ if (segment.kind !== "single") {
95
+ return null;
96
+ }
97
+ values.push(+segment.value);
98
+ }
99
+ return values;
100
+ }
101
+ function offsetCleanStride(stride) {
102
+ return stride.start < stride.interval && 24 % stride.interval === 0;
103
+ }
104
+ function renderStride(spec, parts) {
105
+ const { start, interval, cycle } = spec;
106
+ const tiles = cycle % interval === 0;
107
+ if (start === 0 && tiles) {
108
+ return parts.bare();
109
+ }
110
+ if (start < interval && tiles) {
111
+ return parts.offset();
112
+ }
113
+ return parts.bounded();
114
+ }
115
+ function hourListStride(values) {
116
+ if (values.length < 2) {
117
+ return null;
118
+ }
119
+ const interval = values[1] - values[0];
120
+ if (interval < 2) {
121
+ return null;
122
+ }
123
+ for (let i = 2; i < values.length; i += 1) {
124
+ if (values[i] - values[i - 1] !== interval) {
125
+ return null;
126
+ }
127
+ }
128
+ if (values[0] !== 0 && values.length < 5) {
129
+ return null;
130
+ }
131
+ return { interval, last: values[values.length - 1], start: values[0] };
132
+ }
133
+
134
+ // src/core/weekday.ts
75
135
  function weekdayDisplayKey(value) {
76
136
  return value === 0 ? 7 : value;
77
137
  }
@@ -92,9 +152,6 @@ function orderWeekdaysForDisplay(segments) {
92
152
  return pair[0];
93
153
  });
94
154
  }
95
- function toFieldNumber(token, numberMap) {
96
- return isNonNegativeInteger(token) ? +token : numberMap[token.toUpperCase()];
97
- }
98
155
 
99
156
  // src/lang/es/dialects.ts
100
157
  var es = {
@@ -121,15 +178,6 @@ function resolveDialect(dialect) {
121
178
  }
122
179
 
123
180
  // src/lang/es/index.ts
124
- function stepSegment(segments) {
125
- return segments[0];
126
- }
127
- function hourSegments(ir) {
128
- return ir.analyses.segments.hour;
129
- }
130
- function fieldSegments(ir, field) {
131
- return ir.analyses.segments[field];
132
- }
133
181
  var numeros = [
134
182
  "cero",
135
183
  "uno",
@@ -182,107 +230,107 @@ function normalizeOptions(options) {
182
230
  years: !!options.years
183
231
  };
184
232
  }
185
- function describe(ir, opts) {
186
- return applyYear(render(ir, ir.plan, opts), ir, opts);
233
+ function describe(schedule, opts) {
234
+ return applyYear(render(schedule, schedule.plan, opts), schedule, opts);
187
235
  }
188
- function render(ir, plan, opts) {
189
- const phrase = renderers[plan.kind](ir, plan, opts);
190
- if (!isDateWeekdayUnion(ir)) {
236
+ function render(schedule, plan, opts) {
237
+ const phrase = renderers[plan.kind](schedule, plan, opts);
238
+ if (!isDateWeekdayUnion(schedule)) {
191
239
  return phrase;
192
240
  }
193
- const lead = unionMonthLeadFull(ir);
194
- return (lead ? lead + " " : "") + phrase + unionYaseaSuffix(ir, opts);
241
+ const lead = unionMonthLeadFull(schedule);
242
+ return (lead ? lead + " " : "") + phrase + unionYaseaSuffix(schedule, opts);
195
243
  }
196
- function renderEverySecond(ir, plan, opts) {
197
- return "cada segundo" + trailingQualifier(ir, opts);
244
+ function renderEverySecond(schedule, plan, opts) {
245
+ return "cada segundo" + trailingQualifier(schedule, opts);
198
246
  }
199
- function renderStandaloneSeconds(ir, plan, opts) {
200
- return secondsLeadClause(ir, opts) + trailingQualifier(ir, opts);
247
+ function renderStandaloneSeconds(schedule, plan, opts) {
248
+ return secondsLeadClause(schedule, opts) + trailingQualifier(schedule, opts);
201
249
  }
202
- function renderSecondPastMinute(ir, plan, opts) {
203
- return "en el segundo " + ir.pattern.second + " de cada minuto" + trailingQualifier(ir, opts);
250
+ function renderSecondPastMinute(schedule, plan, opts) {
251
+ return "en el segundo " + schedule.pattern.second + " de cada minuto" + trailingQualifier(schedule, opts);
204
252
  }
205
- function renderSecondsWithinMinute(ir, plan, opts) {
206
- const minuteField = ir.pattern.minute;
253
+ function renderSecondsWithinMinute(schedule, plan, opts) {
254
+ const minuteField = schedule.pattern.minute;
207
255
  if (plan.singleSecond) {
208
- return "en el minuto " + minuteField + " y el segundo " + ir.pattern.second + " de cada hora" + trailingQualifier(ir, opts);
256
+ return "en el minuto " + minuteField + " y el segundo " + schedule.pattern.second + " de cada hora" + trailingQualifier(schedule, opts);
209
257
  }
210
- return secondsLeadClause(ir, opts) + ", en el minuto " + minuteField + " de cada hora" + trailingQualifier(ir, opts);
258
+ return secondsLeadClause(schedule, opts) + ", en el minuto " + minuteField + " de cada hora" + trailingQualifier(schedule, opts);
211
259
  }
212
- function secondsListAtClock(ir, rest, opts) {
260
+ function secondsListAtClock(schedule, rest, opts) {
213
261
  const clockPhrases = rest.times.map(function clock(time) {
214
262
  return atTime(timePhrase(time.hour, time.minute, null, opts));
215
263
  });
216
264
  const grouped = groupClockTimesByArticle(clockPhrases);
217
265
  const clockList = grouped.startsWith("a ") ? grouped.slice(2) : grouped;
218
- const stride = strideFromSegments(fieldSegments(ir, "second"), "segundo", "", opts);
219
- const secondsPhrase = stride ?? "en los segundos " + joinList(segmentWords(fieldSegments(ir, "second")));
220
- const dayFrame = trailingQualifier(ir, opts);
266
+ const stride = strideFromSegments(segmentsOf(schedule, "second"), "segundo", "", opts);
267
+ const secondsPhrase = stride ?? "en los segundos " + joinList(segmentWords(segmentsOf(schedule, "second")));
268
+ const dayFrame = trailingQualifier(schedule, opts);
221
269
  return (dayFrame ? dayFrame.trimStart() + ", " : "") + secondsPhrase + " de " + clockList;
222
270
  }
223
- function composeHourCadence(ir, plan, opts) {
271
+ function composeHourCadence(schedule, plan, opts) {
224
272
  const clockRest = plan.rest.kind === "clockTimes" || plan.rest.kind === "compactClockTimes";
225
- if (!clockRest || ir.shapes.minute !== "single") {
273
+ if (!clockRest || schedule.shapes.minute !== "single") {
226
274
  return null;
227
275
  }
228
- const minute = +ir.pattern.minute;
229
- return hourCadence(ir, minute, opts) ?? hourRangeCadence(ir, minute, opts);
276
+ const minute = +schedule.pattern.minute;
277
+ return hourCadence(schedule, minute, opts) ?? hourRangeCadence(schedule, minute, opts);
230
278
  }
231
- function isPinnedMinuteSeconds(ir, plan) {
232
- return plan.rest.kind === "clockTimes" && (ir.shapes.second === "wildcard" || ir.shapes.second === "step");
279
+ function isPinnedMinuteSeconds(schedule, plan) {
280
+ return plan.rest.kind === "clockTimes" && (schedule.shapes.second === "wildcard" || schedule.shapes.second === "step");
233
281
  }
234
- function renderComposeSeconds(ir, plan, opts) {
235
- const hourCad = composeHourCadence(ir, plan, opts);
282
+ function renderComposeSeconds(schedule, plan, opts) {
283
+ const hourCad = composeHourCadence(schedule, plan, opts);
236
284
  if (hourCad !== null) {
237
285
  return hourCad;
238
286
  }
239
- if (isPinnedMinuteSeconds(ir, plan)) {
240
- return pinnedMinuteSeconds(ir, plan.rest, opts);
287
+ if (isPinnedMinuteSeconds(schedule, plan)) {
288
+ return pinnedMinuteSeconds(schedule, plan.rest, opts);
241
289
  }
242
- if (plan.rest.kind === "clockTimes" && ir.shapes.second === "list") {
243
- return secondsListAtClock(ir, plan.rest, opts);
290
+ if (plan.rest.kind === "clockTimes" && schedule.shapes.second === "list") {
291
+ return secondsListAtClock(schedule, plan.rest, opts);
244
292
  }
245
- if (plan.rest.kind === "hourRange" && ir.shapes.second === "step" && ir.pattern.weekday !== "*") {
293
+ if (plan.rest.kind === "hourRange" && schedule.shapes.second === "step" && schedule.pattern.weekday !== "*") {
246
294
  const restNode = plan.rest;
247
295
  const window = hourWindow(boundedWindow(restNode), opts);
248
- const dayFrame = weekdayQualifier(ir) + monthScope(ir);
249
- const cadence = "cada " + numero(stepSegment(ir.analyses.segments.second).interval, opts) + " segundos del minuto " + ir.pattern.minute;
296
+ const dayFrame = weekdayQualifier(schedule) + monthScope(schedule);
297
+ const cadence = "cada " + numero(stepSegment(schedule, "second").interval, opts) + " segundos del minuto " + schedule.pattern.minute;
250
298
  return dayFrame + ", " + window + ", " + cadence;
251
299
  }
252
- if (isEveryOtherMinuteSeconds(ir, plan)) {
253
- return secondsLeadClause(ir, opts) + " de " + render(ir, plan.rest, opts);
300
+ if (isEveryOtherMinuteSeconds(schedule, plan)) {
301
+ return secondsLeadClause(schedule, opts) + " de " + render(schedule, plan.rest, opts);
254
302
  }
255
- const restOwnsLead = plan.rest.kind === "compactClockTimes" && ir.analyses.clockSecond;
256
- const lead = restOwnsLead ? "" : secondsLeadClause(ir, opts) + ", ";
257
- return lead + render(ir, plan.rest, opts);
303
+ const restOwnsLead = plan.rest.kind === "compactClockTimes" && schedule.analyses.clockSecond;
304
+ const lead = restOwnsLead ? "" : secondsLeadClause(schedule, opts) + ", ";
305
+ return lead + render(schedule, plan.rest, opts);
258
306
  }
259
- function isEveryOtherMinuteSeconds(ir, plan) {
260
- if (plan.rest.kind !== "minuteFrequency" || ir.shapes.second !== "wildcard" || ir.shapes.hour !== "wildcard") {
307
+ function isEveryOtherMinuteSeconds(schedule, plan) {
308
+ if (plan.rest.kind !== "minuteFrequency" || schedule.shapes.second !== "wildcard" || schedule.shapes.hour !== "wildcard") {
261
309
  return false;
262
310
  }
263
- const minuteStep = stepSegment(ir.analyses.segments.minute);
311
+ const minuteStep = stepSegment(schedule, "minute");
264
312
  return minuteStep.startToken === "*" && minuteStep.interval === 2;
265
313
  }
266
- function pinnedMinuteSeconds(ir, rest, opts) {
267
- const dayTrail = leadingQualifier(ir, opts).trimEnd();
314
+ function pinnedMinuteSeconds(schedule, rest, opts) {
315
+ const dayTrail = leadingQualifier(schedule, opts).trimEnd();
268
316
  const trail = dayTrail ? ", " + dayTrail : "";
269
- if (+rest.times[0].minute === 0 && ir.shapes.minute === "single") {
270
- return secondsLeadClause(ir, opts) + " durante un minuto " + durationHourList(rest.times, opts) + trail;
317
+ if (+rest.times[0].minute === 0 && schedule.shapes.minute === "single") {
318
+ return secondsLeadClause(schedule, opts) + " durante un minuto " + durationHourList(rest.times, opts) + trail;
271
319
  }
272
- return secondsLeadClause(ir, opts) + " de " + explicitClockList(rest.times, opts) + trail;
320
+ return secondsLeadClause(schedule, opts) + " de " + explicitClockList(rest.times, opts) + trail;
273
321
  }
274
- function secondsLeadClause(ir, opts) {
275
- return secondsClause(ir, "minuto", opts);
322
+ function secondsLeadClause(schedule, opts) {
323
+ return secondsClause(schedule, "minuto", opts);
276
324
  }
277
- function secondsClause(ir, anchor, opts) {
278
- const secondField = ir.pattern.second;
279
- const shape = ir.shapes.second;
325
+ function secondsClause(schedule, anchor, opts) {
326
+ const secondField = schedule.pattern.second;
327
+ const shape = schedule.shapes.second;
280
328
  if (secondField === "*") {
281
329
  return "cada segundo";
282
330
  }
283
331
  if (shape === "step") {
284
332
  return stepCycle60(
285
- stepSegment(ir.analyses.segments.second),
333
+ stepSegment(schedule, "second"),
286
334
  "segundo",
287
335
  anchor,
288
336
  opts
@@ -296,31 +344,31 @@ function secondsClause(ir, anchor, opts) {
296
344
  return "en el segundo " + secondField + " de cada " + anchor;
297
345
  }
298
346
  return strideFromSegments(
299
- fieldSegments(ir, "second"),
347
+ segmentsOf(schedule, "second"),
300
348
  "segundo",
301
349
  anchor,
302
350
  opts
303
- ) ?? "en los segundos " + joinList(segmentWords(fieldSegments(ir, "second"))) + " de cada " + anchor;
351
+ ) ?? "en los segundos " + joinList(segmentWords(segmentsOf(schedule, "second"))) + " de cada " + anchor;
304
352
  }
305
- function renderEveryMinute(ir, plan, opts) {
306
- return "cada minuto" + trailingQualifier(ir, opts);
353
+ function renderEveryMinute(schedule, plan, opts) {
354
+ return "cada minuto" + trailingQualifier(schedule, opts);
307
355
  }
308
- function renderSingleMinute(ir, plan, opts) {
309
- return "en el minuto " + ir.pattern.minute + " de cada hora" + trailingQualifier(ir, opts);
356
+ function renderSingleMinute(schedule, plan, opts) {
357
+ return "en el minuto " + schedule.pattern.minute + " de cada hora" + trailingQualifier(schedule, opts);
310
358
  }
311
- function renderRangeOfMinutes(ir, plan, opts) {
312
- return minuteRangeLead(ir.pattern.minute) + " de cada hora" + trailingQualifier(ir, opts);
359
+ function renderRangeOfMinutes(schedule, plan, opts) {
360
+ return minuteRangeLead(schedule.pattern.minute) + " de cada hora" + trailingQualifier(schedule, opts);
313
361
  }
314
- function renderMultipleMinutes(ir, plan, opts) {
315
- return minutesList(ir, opts) + trailingQualifier(ir, opts);
362
+ function renderMultipleMinutes(schedule, plan, opts) {
363
+ return minutesList(schedule, opts) + trailingQualifier(schedule, opts);
316
364
  }
317
- function minutesList(ir, opts) {
365
+ function minutesList(schedule, opts) {
318
366
  return strideFromSegments(
319
- fieldSegments(ir, "minute"),
367
+ segmentsOf(schedule, "minute"),
320
368
  "minuto",
321
369
  "hora",
322
370
  opts
323
- ) ?? "en los minutos " + joinList(segmentWords(fieldSegments(ir, "minute"))) + " de cada hora";
371
+ ) ?? "en los minutos " + joinList(segmentWords(segmentsOf(schedule, "minute"))) + " de cada hora";
324
372
  }
325
373
  function minuteRangeLead(minuteField) {
326
374
  const bounds = minuteField.split("-");
@@ -375,86 +423,86 @@ function spanHours(hours) {
375
423
  return (hour === 1 ? "la " : "las ") + hour;
376
424
  }));
377
425
  }
378
- function renderMinuteFrequency(ir, plan, opts) {
426
+ function renderMinuteFrequency(schedule, plan, opts) {
379
427
  let phrase = stepCycle60(
380
- stepSegment(ir.analyses.segments.minute),
428
+ stepSegment(schedule, "minute"),
381
429
  "minuto",
382
430
  "hora",
383
431
  opts
384
432
  );
385
433
  if (plan.hours.kind === "during") {
386
- const cadence = unevenHourCadence(ir, opts);
434
+ const cadence = unevenHourCadence(schedule, opts);
387
435
  if (cadence) {
388
436
  phrase += ", " + cadence;
389
437
  } else {
390
- phrase += singleHourStep(ir.analyses.segments.hour) ? ", " + stepHourSpan(stepSegment(ir.analyses.segments.hour), opts) : " " + hourSpanFromTimes(ir, plan.hours.times, opts);
438
+ phrase += singleHourStep(schedule.analyses.segments.hour) ? ", " + stepHourSpan(stepSegment(schedule, "hour"), opts) : " " + hourSpanFromTimes(schedule, plan.hours.times, opts);
391
439
  }
392
440
  } else if (plan.hours.kind === "window") {
393
441
  phrase += " " + hourWindow(plan.hours, opts);
394
442
  } else if (plan.hours.kind === "step") {
395
- phrase += ", " + stepHourSpan(stepSegment(ir.analyses.segments.hour), opts);
443
+ phrase += ", " + stepHourSpan(stepSegment(schedule, "hour"), opts);
396
444
  }
397
- return phrase + trailingQualifier(ir, opts);
445
+ return phrase + trailingQualifier(schedule, opts);
398
446
  }
399
- function renderMinuteSpanInHour(ir, plan, opts) {
400
- if (ir.pattern.minute === "*") {
401
- return "cada minuto de la hora " + fromTime(timePhrase(plan.hour, 0, null, opts)) + trailingQualifier(ir, opts);
447
+ function renderMinuteSpanInHour(schedule, plan, opts) {
448
+ if (schedule.pattern.minute === "*") {
449
+ return "cada minuto de la hora " + fromTime(timePhrase(plan.hour, 0, null, opts)) + trailingQualifier(schedule, opts);
402
450
  }
403
451
  return "cada minuto " + timeRange(
404
452
  { hour: plan.hour, minute: plan.span[0] },
405
453
  { hour: plan.hour, minute: plan.span[1] },
406
454
  opts
407
- ) + trailingQualifier(ir, opts);
455
+ ) + trailingQualifier(schedule, opts);
408
456
  }
409
- function renderMinutesAcrossHours(ir, plan, opts) {
410
- const cadence = unevenHourCadence(ir, opts);
457
+ function renderMinutesAcrossHours(schedule, plan, opts) {
458
+ const cadence = unevenHourCadence(schedule, opts);
411
459
  if (plan.form === "wildcard") {
412
460
  if (cadence !== null) {
413
- return "cada minuto, " + cadence + trailingQualifier(ir, opts);
461
+ return "cada minuto, " + cadence + trailingQualifier(schedule, opts);
414
462
  }
415
- if (singleHourStep(ir.analyses.segments.hour)) {
416
- return "cada minuto, " + stepHourSpan(stepSegment(ir.analyses.segments.hour), opts) + trailingQualifier(ir, opts);
463
+ if (singleHourStep(schedule.analyses.segments.hour)) {
464
+ return "cada minuto, " + stepHourSpan(stepSegment(schedule, "hour"), opts) + trailingQualifier(schedule, opts);
417
465
  }
418
- return "cada minuto " + hourSpanFromTimes(ir, plan.times, opts) + trailingQualifier(ir, opts);
466
+ return "cada minuto " + hourSpanFromTimes(schedule, plan.times, opts) + trailingQualifier(schedule, opts);
419
467
  }
420
- const lead = plan.form === "range" ? minuteRangeLead(ir.pattern.minute) : minutesList(ir, opts);
468
+ const lead = plan.form === "range" ? minuteRangeLead(schedule.pattern.minute) : minutesList(schedule, opts);
421
469
  if (cadence !== null) {
422
- return lead + ", " + cadence + trailingQualifier(ir, opts);
470
+ return lead + ", " + cadence + trailingQualifier(schedule, opts);
423
471
  }
424
- return lead + ", " + atHourTimes(ir, plan.times, opts) + trailingQualifier(ir, opts);
472
+ return lead + ", " + atHourTimes(schedule, plan.times, opts) + trailingQualifier(schedule, opts);
425
473
  }
426
- function renderMinuteSpanAcrossHourStep(ir, plan, opts) {
427
- const segment = stepSegment(ir.analyses.segments.hour);
428
- const cadence = unevenHourCadence(ir, opts);
474
+ function renderMinuteSpanAcrossHourStep(schedule, plan, opts) {
475
+ const segment = stepSegment(schedule, "hour");
476
+ const cadence = unevenHourCadence(schedule, opts);
429
477
  if (plan.form === "wildcard") {
430
- return "cada minuto, " + stepHourSpan(segment, opts) + trailingQualifier(ir, opts);
478
+ return "cada minuto, " + stepHourSpan(segment, opts) + trailingQualifier(schedule, opts);
431
479
  }
432
- const lead = plan.form === "list" ? minutesList(ir, opts) : minuteRangeLead(ir.pattern.minute);
433
- return lead + ", " + (cadence ?? stepHours(segment, opts)) + trailingQualifier(ir, opts);
480
+ const lead = plan.form === "list" ? minutesList(schedule, opts) : minuteRangeLead(schedule.pattern.minute);
481
+ return lead + ", " + (cadence ?? stepHours(segment, opts)) + trailingQualifier(schedule, opts);
434
482
  }
435
- function renderEveryHour(ir, plan, opts) {
436
- return "cada hora" + trailingQualifier(ir, opts);
483
+ function renderEveryHour(schedule, plan, opts) {
484
+ return "cada hora" + trailingQualifier(schedule, opts);
437
485
  }
438
- function renderHourRange(ir, plan, opts) {
486
+ function renderHourRange(schedule, plan, opts) {
439
487
  const window = hourWindow(boundedWindow(plan), opts);
440
488
  if (plan.minuteForm === "wildcard") {
441
- return "cada minuto " + window + trailingQualifier(ir, opts);
489
+ return "cada minuto " + window + trailingQualifier(schedule, opts);
442
490
  }
443
491
  if (plan.minuteForm === "range") {
444
- return minuteRangeLead(ir.pattern.minute) + ", " + window + trailingQualifier(ir, opts);
492
+ return minuteRangeLead(schedule.pattern.minute) + ", " + window + trailingQualifier(schedule, opts);
445
493
  }
446
- if (ir.pattern.minute === "0") {
447
- return "cada hora " + window + trailingQualifier(ir, opts);
494
+ if (schedule.pattern.minute === "0") {
495
+ return "cada hora " + window + trailingQualifier(schedule, opts);
448
496
  }
449
- const lead = ir.shapes.minute === "single" ? "en el minuto " + ir.pattern.minute + " de cada hora" : minutesList(ir, opts);
450
- return lead + ", " + window + trailingQualifier(ir, opts);
497
+ const lead = schedule.shapes.minute === "single" ? "en el minuto " + schedule.pattern.minute + " de cada hora" : minutesList(schedule, opts);
498
+ return lead + ", " + window + trailingQualifier(schedule, opts);
451
499
  }
452
- function renderHourStep(ir, plan, opts) {
453
- const cadence = unevenHourCadence(ir, opts);
500
+ function renderHourStep(schedule, plan, opts) {
501
+ const cadence = unevenHourCadence(schedule, opts);
454
502
  if (cadence !== null) {
455
- return cadence + trailingQualifier(ir, opts);
503
+ return cadence + trailingQualifier(schedule, opts);
456
504
  }
457
- return stepHours(stepSegment(ir.analyses.segments.hour), opts) + trailingQualifier(ir, opts);
505
+ return stepHours(stepSegment(schedule, "hour"), opts) + trailingQualifier(schedule, opts);
458
506
  }
459
507
  function boundedWindow(plan) {
460
508
  const last = plan.minuteForm === "wildcard" ? plan.boundMinute ?? 0 : 0;
@@ -467,42 +515,46 @@ function hourWindow(window, opts) {
467
515
  opts
468
516
  );
469
517
  }
470
- function isDateWeekdayUnion(ir) {
471
- return ir.pattern.date !== "*" && ir.pattern.weekday !== "*";
518
+ function isDateWeekdayUnion(schedule) {
519
+ return schedule.pattern.date !== "*" && schedule.pattern.weekday !== "*";
472
520
  }
473
- function unionMonthLeadFull(ir) {
474
- if (ir.pattern.month === "*") {
521
+ function unionMonthLeadFull(schedule) {
522
+ if (schedule.pattern.month === "*") {
475
523
  return "";
476
524
  }
477
- const lead = monthPhrase(ir, monthRanged(ir) ? "de " : "en ");
478
- const segments = flattenSteps(fieldSegments(ir, "month"));
479
- const isEnumeration = !monthRanged(ir) && segments.length >= 2;
525
+ const lead = monthPhrase(schedule, monthRanged(schedule) ? "de " : "en ");
526
+ const segments = flattenSteps(segmentsOf(schedule, "month"));
527
+ const isEnumeration = !monthRanged(schedule) && segments.length >= 2;
480
528
  return isEnumeration ? lead + "," : lead;
481
529
  }
482
- function domArm(ir, opts) {
483
- const date = ir.pattern.date;
530
+ function domArm(schedule, opts) {
531
+ const date = schedule.pattern.date;
484
532
  const quartz = quartzDatePhrase(date);
485
533
  if (quartz) {
486
534
  return quartz;
487
535
  }
536
+ const parity = parityDayPredicate(date);
537
+ if (parity) {
538
+ return parity;
539
+ }
488
540
  if (isOpenStep(date)) {
489
541
  return stepDates(date, opts);
490
542
  }
491
- const segments = fieldSegments(ir, "date");
543
+ const segments = segmentsOf(schedule, "date");
492
544
  if (segments.length === 1 && segments[0].kind === "range") {
493
545
  return "del " + segments[0].bounds[0] + " al " + segments[0].bounds[1] + " del mes";
494
546
  }
495
547
  if (segments.length === 1 && segments[0].kind === "single") {
496
- return ir.pattern.month === "*" ? "el " + segments[0].value + " de cada mes" : "el d\xEDa " + segments[0].value;
548
+ return schedule.pattern.month === "*" ? "el " + segments[0].value + " de cada mes" : "el d\xEDa " + segments[0].value;
497
549
  }
498
550
  return "los d\xEDas " + joinList(segmentWords(segments)) + " del mes";
499
551
  }
500
- function dowArm(ir) {
501
- const quartz = quartzWeekdayPhrase(ir.pattern.weekday);
552
+ function dowArm(schedule) {
553
+ const quartz = quartzWeekdayPhrase(schedule.pattern.weekday);
502
554
  if (quartz) {
503
555
  return quartz;
504
556
  }
505
- const segments = orderWeekdaysForDisplay(fieldSegments(ir, "weekday"));
557
+ const segments = orderWeekdaysForDisplay(segmentsOf(schedule, "weekday"));
506
558
  const allSingles = segments.every(function single(segment) {
507
559
  return segment.kind === "single";
508
560
  });
@@ -515,19 +567,19 @@ function dowArm(ir) {
515
567
  }));
516
568
  }
517
569
  if (segments.length === 1) {
518
- return weekdayRange(segments[0]);
570
+ return "cualquier d\xEDa " + weekdayRange(segments[0]);
519
571
  }
520
572
  return joinList(segments.map(function name(segment) {
521
573
  return segment.kind === "range" ? weekdayRange(segment) : "los " + pluralWeekday(segment.value);
522
574
  }));
523
575
  }
524
- function unionYaseaSuffix(ir, opts) {
525
- return ", ya sea " + domArm(ir, opts) + " o " + dowArm(ir);
576
+ function unionYaseaSuffix(schedule, opts) {
577
+ return ", ya sea " + domArm(schedule, opts) + " o " + dowArm(schedule);
526
578
  }
527
- function renderClockTimes(ir, plan, opts) {
528
- if (ir.shapes.minute === "single") {
529
- const minute = +ir.pattern.minute;
530
- const cadence = hourCadence(ir, minute, opts) ?? hourRangeCadence(ir, minute, opts);
579
+ function renderClockTimes(schedule, plan, opts) {
580
+ if (schedule.shapes.minute === "single") {
581
+ const minute = +schedule.pattern.minute;
582
+ const cadence = hourCadence(schedule, minute, opts) ?? hourRangeCadence(schedule, minute, opts);
531
583
  if (cadence !== null) {
532
584
  return cadence;
533
585
  }
@@ -535,7 +587,7 @@ function renderClockTimes(ir, plan, opts) {
535
587
  const phrases = plan.times.map(function clock(time) {
536
588
  return atTime(timePhrase(time.hour, time.minute, time.second, opts));
537
589
  });
538
- return leadingQualifier(ir, opts) + groupClockTimes(phrases);
590
+ return leadingQualifier(schedule, opts) + groupClockTimes(phrases);
539
591
  }
540
592
  function explicitClockList(times, opts) {
541
593
  const phrases = times.map(function clock(time) {
@@ -711,23 +763,33 @@ function groupClockTimesByArticle(phrases) {
711
763
  const connector = doubleY ? ", " : " y ";
712
764
  return laPart + connector + lasPart;
713
765
  }
714
- function renderCompactClockTimes(ir, plan, opts) {
766
+ function renderCompactClockTimes(schedule, plan, opts) {
715
767
  if (plan.fold) {
716
- const cadence2 = hourCadence(ir, plan.minute, opts) ?? hourRangeCadence(ir, plan.minute, opts);
768
+ const cadence2 = hourCadence(schedule, plan.minute, opts) ?? hourRangeCadence(schedule, plan.minute, opts);
717
769
  if (cadence2 !== null) {
718
770
  return cadence2;
719
771
  }
720
- const ranged = hourSegments(ir).some(function range(segment) {
772
+ const ranged = segmentsOf(schedule, "hour").some(function range(segment) {
721
773
  return segment.kind === "range";
722
774
  });
723
- if (ranged && !ir.analyses.clockSecond) {
724
- return "cada hora " + hourSegmentTimes(ir, plan.minute, ir.analyses.clockSecond, opts) + trailingQualifier(ir, opts);
775
+ if (ranged && !schedule.analyses.clockSecond) {
776
+ return "cada hora " + hourSegmentTimes(
777
+ schedule,
778
+ plan.minute,
779
+ schedule.analyses.clockSecond,
780
+ opts
781
+ ) + trailingQualifier(schedule, opts);
725
782
  }
726
- return leadingQualifier(ir, opts) + hourSegmentTimes(ir, plan.minute, ir.analyses.clockSecond, opts);
783
+ return leadingQualifier(schedule, opts) + hourSegmentTimes(
784
+ schedule,
785
+ plan.minute,
786
+ schedule.analyses.clockSecond,
787
+ opts
788
+ );
727
789
  }
728
- const cadence = unevenHourCadence(ir, opts);
729
- const phrase = cadence ? minutesList(ir, opts) + ", " + cadence + trailingQualifier(ir, opts) : minutesList(ir, opts) + ", " + hourContextTimes(ir, opts) + trailingQualifier(ir, opts);
730
- return ir.analyses.clockSecond ? secondsLeadClause(ir, opts) + ", " + phrase : phrase;
790
+ const cadence = unevenHourCadence(schedule, opts);
791
+ const phrase = cadence ? minutesList(schedule, opts) + ", " + cadence + trailingQualifier(schedule, opts) : minutesList(schedule, opts) + ", " + hourContextTimes(schedule, opts) + trailingQualifier(schedule, opts);
792
+ return schedule.analyses.clockSecond ? secondsLeadClause(schedule, opts) + ", " + phrase : phrase;
731
793
  }
732
794
  var renderers = {
733
795
  clockTimes: renderClockTimes,
@@ -749,18 +811,15 @@ var renderers = {
749
811
  singleMinute: renderSingleMinute,
750
812
  standaloneSeconds: renderStandaloneSeconds
751
813
  };
752
- function renderStride(stride, opts) {
814
+ function renderStride2(stride, opts) {
753
815
  const { interval, start, last, cycle, unit, anchor } = stride;
754
816
  const cadence = "cada " + numero(interval, opts) + " " + unit + "s";
755
- const tiles = cycle % interval === 0;
756
- if (start === 0 && tiles) {
757
- return cadence;
758
- }
759
817
  const tail = anchor ? " de cada " + anchor : "";
760
- if (start < interval && tiles) {
761
- return cadence + " a partir del " + unit + " " + start + tail;
762
- }
763
- return cadence + " del " + unit + " " + start + " al " + last + tail;
818
+ return renderStride({ start, interval, cycle }, {
819
+ bare: () => cadence,
820
+ offset: () => cadence + " a partir del " + unit + " " + start + tail,
821
+ bounded: () => cadence + " del " + unit + " " + start + " al " + last + tail
822
+ });
764
823
  }
765
824
  function stepCycle60(segment, unit, anchor, opts) {
766
825
  if (segment.startToken.indexOf("-") !== -1) {
@@ -770,7 +829,7 @@ function stepCycle60(segment, unit, anchor, opts) {
770
829
  if (start !== 0 && segment.fires.length <= 3) {
771
830
  return "en los " + unit + "s " + joinList(wordList(segment.fires)) + " de cada " + anchor;
772
831
  }
773
- return renderStride({
832
+ return renderStride2({
774
833
  interval: segment.interval,
775
834
  start,
776
835
  last: segment.fires[segment.fires.length - 1],
@@ -782,17 +841,7 @@ function stepCycle60(segment, unit, anchor, opts) {
782
841
  function strideFromSegments(segments, unit, anchor, opts) {
783
842
  const values = singleValues(segments);
784
843
  const step = values && arithmeticStep(values);
785
- return step ? renderStride({ ...step, cycle: 60, unit, anchor }, opts) : null;
786
- }
787
- function singleValues(segments) {
788
- const values = [];
789
- for (const segment of segments) {
790
- if (segment.kind !== "single") {
791
- return null;
792
- }
793
- values.push(+segment.value);
794
- }
795
- return values;
844
+ return step ? renderStride2({ ...step, cycle: 60, unit, anchor }, opts) : null;
796
845
  }
797
846
  function stepHours(segment, opts) {
798
847
  if (segment.startToken.indexOf("-") !== -1) {
@@ -811,45 +860,21 @@ function stepHours(segment, opts) {
811
860
  function hourStrideCadence(stride, opts) {
812
861
  const { start, interval, last } = stride;
813
862
  const cadence = "cada " + numero(interval, opts) + " horas";
814
- const tiles = 24 % interval === 0;
815
- if (start === 0 && tiles) {
816
- return cadence;
817
- }
818
- if (start < interval && tiles) {
819
- return cadence + " a partir de " + timePhrase(start, 0, null, opts);
820
- }
821
- return cadence + " de " + timePhrase(start, 0, null, opts) + " a " + timePhrase(last, 0, null, opts);
822
- }
823
- function offsetCleanStride(stride) {
824
- return stride.start < stride.interval && 24 % stride.interval === 0;
863
+ return renderStride({ start, interval, cycle: 24 }, {
864
+ bare: () => cadence,
865
+ offset: () => cadence + " a partir de " + timePhrase(start, 0, null, opts),
866
+ bounded: () => cadence + " de " + timePhrase(start, 0, null, opts) + " a " + timePhrase(last, 0, null, opts)
867
+ });
825
868
  }
826
- function unevenHourCadence(ir, opts) {
827
- const stride = hourStride(ir);
869
+ function unevenHourCadence(schedule, opts) {
870
+ const stride = hourStride(schedule);
828
871
  if (!stride || offsetCleanStride(stride)) {
829
872
  return null;
830
873
  }
831
874
  return hourStrideCadence(stride, opts);
832
875
  }
833
- function hourListStride(values) {
834
- if (values.length < 2) {
835
- return null;
836
- }
837
- const interval = values[1] - values[0];
838
- if (interval < 2) {
839
- return null;
840
- }
841
- for (let i = 2; i < values.length; i += 1) {
842
- if (values[i] - values[i - 1] !== interval) {
843
- return null;
844
- }
845
- }
846
- if (values[0] !== 0 && values.length < 5) {
847
- return null;
848
- }
849
- return { interval, last: values[values.length - 1], start: values[0] };
850
- }
851
- function hourStride(ir) {
852
- const segments = fieldSegments(ir, "hour");
876
+ function hourStride(schedule) {
877
+ const segments = segmentsOf(schedule, "hour");
853
878
  if (segments.length === 1 && segments[0].kind === "step") {
854
879
  const segment = segments[0];
855
880
  if (segment.fires.length < 2) {
@@ -861,64 +886,64 @@ function hourStride(ir) {
861
886
  const values = singleValues(segments);
862
887
  return values && hourListStride(values);
863
888
  }
864
- function subMinuteSecond(ir) {
865
- return ir.pattern.second === "*" || ir.shapes.second === "step";
889
+ function subMinuteSecond(schedule) {
890
+ return schedule.pattern.second === "*" || schedule.shapes.second === "step";
866
891
  }
867
- function hourCadenceLead(ir, minute, opts) {
892
+ function hourCadenceLead(schedule, minute, opts) {
868
893
  if (minute === 0) {
869
- if (subMinuteSecond(ir)) {
870
- return secondsClause(ir, "minuto", opts) + " durante un minuto";
894
+ if (subMinuteSecond(schedule)) {
895
+ return secondsClause(schedule, "minuto", opts) + " durante un minuto";
871
896
  }
872
- return secondsClause(ir, "hora", opts);
897
+ return secondsClause(schedule, "hora", opts);
873
898
  }
874
899
  const minutePhrase = "en el minuto " + minute;
875
- if (ir.pattern.second === "0") {
900
+ if (schedule.pattern.second === "0") {
876
901
  return minutePhrase;
877
902
  }
878
- return secondsClause(ir, "minuto", opts) + ", " + minutePhrase;
903
+ return secondsClause(schedule, "minuto", opts) + ", " + minutePhrase;
879
904
  }
880
- function hourCadence(ir, minute, opts) {
881
- const stride = hourStride(ir);
905
+ function hourCadence(schedule, minute, opts) {
906
+ const stride = hourStride(schedule);
882
907
  if (!stride) {
883
908
  return null;
884
909
  }
885
910
  const fires = (stride.last - stride.start) / stride.interval + 1;
886
- if (ir.pattern.second === "0" && fires <= maxClockTimes && offsetCleanStride(stride)) {
911
+ if (schedule.pattern.second === "0" && fires <= maxClockTimes && offsetCleanStride(stride)) {
887
912
  return null;
888
913
  }
889
- const confinement = minute === 0 && subMinuteSecond(ir) && cleanStrideSegment(ir);
914
+ const confinement = minute === 0 && subMinuteSecond(schedule) && cleanStrideSegment(schedule);
890
915
  if (confinement) {
891
- return secondsClause(ir, "minuto", opts) + " durante un minuto, " + stepHourSpan(confinement, opts) + trailingQualifier(ir, opts);
916
+ return secondsClause(schedule, "minuto", opts) + " durante un minuto, " + stepHourSpan(confinement, opts) + trailingQualifier(schedule, opts);
892
917
  }
893
- if (minute === 0 && ir.pattern.second === "0") {
894
- return hourStrideCadence(stride, opts) + trailingQualifier(ir, opts);
918
+ if (minute === 0 && schedule.pattern.second === "0") {
919
+ return hourStrideCadence(stride, opts) + trailingQualifier(schedule, opts);
895
920
  }
896
- return hourCadenceLead(ir, minute, opts) + ", " + hourStrideCadence(stride, opts) + trailingQualifier(ir, opts);
921
+ return hourCadenceLead(schedule, minute, opts) + ", " + hourStrideCadence(stride, opts) + trailingQualifier(schedule, opts);
897
922
  }
898
- function cleanStrideSegment(ir) {
899
- const segments = fieldSegments(ir, "hour");
923
+ function cleanStrideSegment(schedule) {
924
+ const segments = segmentsOf(schedule, "hour");
900
925
  const segment = segments.length === 1 && segments[0];
901
926
  if (!segment || segment.kind !== "step" || segment.startToken.indexOf("-") !== -1) {
902
927
  return null;
903
928
  }
904
929
  return segment;
905
930
  }
906
- function hasHourWindow(ir) {
907
- return hourSegments(ir).some(function range(segment) {
931
+ function hasHourWindow(schedule) {
932
+ return segmentsOf(schedule, "hour").some(function range(segment) {
908
933
  return segment.kind === "range";
909
934
  });
910
935
  }
911
- function hourRangeCadence(ir, minute, opts) {
912
- if (minute !== 0 || !hasHourWindow(ir) || ir.pattern.second === "0") {
936
+ function hourRangeCadence(schedule, minute, opts) {
937
+ if (minute !== 0 || !hasHourWindow(schedule) || schedule.pattern.second === "0") {
913
938
  return null;
914
939
  }
915
- if (subMinuteSecond(ir)) {
916
- return secondsClause(ir, "minuto", opts) + " durante un minuto, durante las horas " + hourSegmentTimes(ir, 0, null, opts) + trailingQualifier(ir, opts);
940
+ if (subMinuteSecond(schedule)) {
941
+ return secondsClause(schedule, "minuto", opts) + " durante un minuto, durante las horas " + hourSegmentTimes(schedule, 0, null, opts) + trailingQualifier(schedule, opts);
917
942
  }
918
- return hourCadenceLead(ir, minute, opts) + ", " + hourSegmentTimes(ir, 0, null, opts) + trailingQualifier(ir, opts);
943
+ return hourCadenceLead(schedule, minute, opts) + ", " + hourSegmentTimes(schedule, 0, null, opts) + trailingQualifier(schedule, opts);
919
944
  }
920
- function hourContextTimes(ir, opts) {
921
- const segments = hourSegments(ir);
945
+ function hourContextTimes(schedule, opts) {
946
+ const segments = segmentsOf(schedule, "hour");
922
947
  const points = [];
923
948
  const hasRange = segments.some(function range(segment) {
924
949
  return segment.kind === "range";
@@ -964,25 +989,25 @@ function atTimes(hours, opts) {
964
989
  return atTime(timePhrase(hour, 0, null, opts));
965
990
  });
966
991
  }
967
- function atHourTimes(ir, times, opts) {
992
+ function atHourTimes(schedule, times, opts) {
968
993
  if (times.kind === "fires") {
969
994
  return groupClockTimesByArticle(atTimes(times.fires, opts));
970
995
  }
971
- return hourSegmentTimes(ir, 0, null, opts);
996
+ return hourSegmentTimes(schedule, 0, null, opts);
972
997
  }
973
- function hourSpanFromTimes(ir, times, opts) {
998
+ function hourSpanFromTimes(schedule, times, opts) {
974
999
  if (times.kind === "fires" && times.fires.length > 3) {
975
1000
  return "durante las horas " + hourSpanList(times.fires, opts);
976
1001
  }
977
- return hourWindowsFromTimes(ir, times, opts);
1002
+ return hourWindowsFromTimes(schedule, times, opts);
978
1003
  }
979
- function hourWindowsFromTimes(ir, times, opts) {
1004
+ function hourWindowsFromTimes(schedule, times, opts) {
980
1005
  if (times.kind === "fires") {
981
1006
  return joinList(times.fires.map(function window(hour) {
982
1007
  return hourAsWindow(hour, opts);
983
1008
  }));
984
1009
  }
985
- return joinList(hourSegments(ir).map(function window(segment) {
1010
+ return joinList(segmentsOf(schedule, "hour").map(function window(segment) {
986
1011
  if (segment.kind === "range") {
987
1012
  return timeRange(
988
1013
  { hour: +segment.bounds[0], minute: 0 },
@@ -998,10 +1023,10 @@ function hourWindowsFromTimes(ir, times, opts) {
998
1023
  return hourAsWindow(+segment.value, opts);
999
1024
  }));
1000
1025
  }
1001
- function hourSegmentTimes(ir, minute, second, opts) {
1026
+ function hourSegmentTimes(schedule, minute, second, opts) {
1002
1027
  const pieces = [];
1003
1028
  const fromRange = [];
1004
- hourSegments(ir).forEach(function clock(segment) {
1029
+ segmentsOf(schedule, "hour").forEach(function clock(segment) {
1005
1030
  if (segment.kind === "step") {
1006
1031
  segment.fires.forEach(function each(hour) {
1007
1032
  pieces.push(atTime(timePhrase(hour, minute, second, opts)));
@@ -1113,47 +1138,47 @@ function dayPeriod(hour, opts) {
1113
1138
  }
1114
1139
  return "de la tarde";
1115
1140
  }
1116
- function leadingQualifier(ir, opts) {
1117
- const pattern = ir.pattern;
1141
+ function leadingQualifier(schedule, opts) {
1142
+ const pattern = schedule.pattern;
1118
1143
  if (pattern.date !== "*" && pattern.weekday !== "*") {
1119
1144
  return "";
1120
1145
  }
1121
1146
  if (pattern.date !== "*") {
1122
- return datePhrase(ir, opts) + " ";
1147
+ return datePhrase(schedule, opts) + " ";
1123
1148
  }
1124
1149
  if (pattern.weekday !== "*") {
1125
- return weekdayQualifier(ir) + monthScope(ir) + " ";
1150
+ return weekdayQualifier(schedule) + monthScope(schedule) + " ";
1126
1151
  }
1127
1152
  if (pattern.month !== "*") {
1128
- return "todos los d\xEDas " + monthPhrase(ir, "de ") + " ";
1153
+ return "todos los d\xEDas " + monthPhrase(schedule, "de ") + " ";
1129
1154
  }
1130
1155
  return "todos los d\xEDas ";
1131
1156
  }
1132
- function trailingQualifier(ir, opts) {
1133
- const pattern = ir.pattern;
1157
+ function trailingQualifier(schedule, opts) {
1158
+ const pattern = schedule.pattern;
1134
1159
  if (pattern.date !== "*" && pattern.weekday !== "*") {
1135
1160
  return "";
1136
1161
  }
1137
1162
  if (pattern.date !== "*") {
1138
- return " " + datePhrase(ir, opts);
1163
+ return " " + datePhrase(schedule, opts);
1139
1164
  }
1140
1165
  if (pattern.weekday !== "*") {
1141
- return " " + weekdayQualifier(ir) + monthScope(ir);
1166
+ return " " + weekdayQualifier(schedule) + monthScope(schedule);
1142
1167
  }
1143
1168
  if (pattern.month !== "*") {
1144
- return " " + monthPhrase(ir, "en ");
1169
+ return " " + monthPhrase(schedule, "en ");
1145
1170
  }
1146
1171
  return "";
1147
1172
  }
1148
- function datePhrase(ir, opts) {
1149
- const pattern = ir.pattern;
1173
+ function datePhrase(schedule, opts) {
1174
+ const pattern = schedule.pattern;
1150
1175
  if (quartzDatePhrase(pattern.date) || isOpenStep(pattern.date)) {
1151
- return dateClause(ir, "", opts) + monthScope(ir);
1176
+ return dateClause(schedule, "", opts) + monthScope(schedule);
1152
1177
  }
1153
- return dateClause(ir, dateMonthPart(ir), opts);
1178
+ return dateClause(schedule, dateMonthPart(schedule), opts);
1154
1179
  }
1155
- function dateClause(ir, monthPart, opts) {
1156
- const pattern = ir.pattern;
1180
+ function dateClause(schedule, monthPart, opts) {
1181
+ const pattern = schedule.pattern;
1157
1182
  const quartz = quartzDatePhrase(pattern.date);
1158
1183
  if (quartz) {
1159
1184
  return quartz;
@@ -1161,31 +1186,31 @@ function dateClause(ir, monthPart, opts) {
1161
1186
  if (isOpenStep(pattern.date)) {
1162
1187
  return stepDates(pattern.date, opts);
1163
1188
  }
1164
- const segments = fieldSegments(ir, "date");
1189
+ const segments = segmentsOf(schedule, "date");
1165
1190
  if (segments.length === 1 && segments[0].kind === "range") {
1166
- return "del " + segments[0].bounds[0] + " al " + segments[0].bounds[1] + monthPart + foldedYear(ir);
1191
+ return "del " + segments[0].bounds[0] + " al " + segments[0].bounds[1] + monthPart + foldedYear(schedule);
1167
1192
  }
1168
1193
  if (segments.length === 1 && segments[0].kind === "single") {
1169
- return "el " + segments[0].value + monthPart + foldedYear(ir);
1194
+ return "el " + segments[0].value + monthPart + foldedYear(schedule);
1170
1195
  }
1171
- return "los d\xEDas " + joinList(segmentWords(segments)) + monthPart + foldedYear(ir);
1196
+ return "los d\xEDas " + joinList(segmentWords(segments)) + monthPart + foldedYear(schedule);
1172
1197
  }
1173
- function monthRanged(ir) {
1174
- return ir.pattern.month !== "*" && fieldSegments(ir, "month").some(function range(segment) {
1198
+ function monthRanged(schedule) {
1199
+ return schedule.pattern.month !== "*" && segmentsOf(schedule, "month").some(function range(segment) {
1175
1200
  return segment.kind === "range";
1176
1201
  });
1177
1202
  }
1178
- function dateMonthPart(ir) {
1179
- if (ir.pattern.month === "*") {
1203
+ function dateMonthPart(schedule) {
1204
+ if (schedule.pattern.month === "*") {
1180
1205
  return " de cada mes";
1181
1206
  }
1182
- if (monthRanged(ir)) {
1183
- return " de cada mes, " + monthPhrase(ir, "de ");
1207
+ if (monthRanged(schedule)) {
1208
+ return " de cada mes, " + monthPhrase(schedule, "de ");
1184
1209
  }
1185
- return " " + monthPhrase(ir, "de ");
1210
+ return " " + monthPhrase(schedule, "de ");
1186
1211
  }
1187
- function foldedYear(ir) {
1188
- const yearField = ir.pattern.year;
1212
+ function foldedYear(schedule) {
1213
+ const yearField = schedule.pattern.year;
1189
1214
  if (yearField === "*" || yearField.indexOf("/") !== -1 || yearField.indexOf("-") !== -1 || yearField.indexOf(",") !== -1) {
1190
1215
  return "";
1191
1216
  }
@@ -1216,12 +1241,12 @@ function quartzWeekdayPhrase(weekdayField) {
1216
1241
  return "el \xFAltimo " + weekdayName(weekdayField.slice(0, -1)) + " del mes";
1217
1242
  }
1218
1243
  }
1219
- function weekdayQualifier(ir) {
1220
- const quartz = quartzWeekdayPhrase(ir.pattern.weekday);
1244
+ function weekdayQualifier(schedule) {
1245
+ const quartz = quartzWeekdayPhrase(schedule.pattern.weekday);
1221
1246
  if (quartz) {
1222
1247
  return quartz;
1223
1248
  }
1224
- const segments = orderWeekdaysForDisplay(fieldSegments(ir, "weekday"));
1249
+ const segments = orderWeekdaysForDisplay(segmentsOf(schedule, "weekday"));
1225
1250
  const allSingles = segments.every(function single(segment) {
1226
1251
  return segment.kind === "single";
1227
1252
  });
@@ -1247,8 +1272,8 @@ function flattenSteps(segments) {
1247
1272
  }) : [segment];
1248
1273
  });
1249
1274
  }
1250
- function monthPhrase(ir, lead) {
1251
- const segments = flattenSteps(fieldSegments(ir, "month"));
1275
+ function monthPhrase(schedule, lead) {
1276
+ const segments = flattenSteps(segmentsOf(schedule, "month"));
1252
1277
  const ranged = segments.some(function range(segment) {
1253
1278
  return segment.kind === "range";
1254
1279
  });
@@ -1264,11 +1289,26 @@ function monthPhrase(ir, lead) {
1264
1289
  return lead + monthName(segment.value);
1265
1290
  }));
1266
1291
  }
1267
- function monthScope(ir) {
1268
- if (ir.pattern.month === "*") {
1292
+ function monthScope(schedule) {
1293
+ if (schedule.pattern.month === "*") {
1269
1294
  return "";
1270
1295
  }
1271
- return (monthRanged(ir) ? ", " : " ") + monthPhrase(ir, "de ");
1296
+ return (monthRanged(schedule) ? ", " : " ") + monthPhrase(schedule, "de ");
1297
+ }
1298
+ function parityDayPredicate(dateField) {
1299
+ if (!isOpenStep(dateField)) {
1300
+ return;
1301
+ }
1302
+ const [start, step] = dateField.split("/");
1303
+ if (+step !== 2) {
1304
+ return;
1305
+ }
1306
+ if (start === "*" || start === "1") {
1307
+ return "un d\xEDa impar del mes";
1308
+ }
1309
+ if (start === "2") {
1310
+ return "un d\xEDa par del mes";
1311
+ }
1272
1312
  }
1273
1313
  function stepDates(dateField, opts) {
1274
1314
  const parts = dateField.split("/");
@@ -1278,15 +1318,15 @@ function stepDates(dateField, opts) {
1278
1318
  }
1279
1319
  return phrase;
1280
1320
  }
1281
- function applyYear(description, ir, opts) {
1282
- const yearField = ir.pattern.year;
1321
+ function applyYear(description, schedule, opts) {
1322
+ const yearField = schedule.pattern.year;
1283
1323
  if (yearField === "*") {
1284
1324
  return description;
1285
1325
  }
1286
1326
  if (yearField.indexOf("/") !== -1) {
1287
1327
  return description + " " + stepYears(yearField, opts);
1288
1328
  }
1289
- if (foldedYear(ir) && ir.pattern.date !== "*") {
1329
+ if (foldedYear(schedule) && schedule.pattern.date !== "*") {
1290
1330
  return description;
1291
1331
  }
1292
1332
  if (yearField.indexOf(",") !== -1) {
@@ -1345,9 +1385,6 @@ function pluralWeekday(token) {
1345
1385
  function monthName(token) {
1346
1386
  return monthNames[+token];
1347
1387
  }
1348
- function isOpenStep(field) {
1349
- return field.indexOf("/") !== -1 && field.indexOf("-") === -1 && field.indexOf(",") === -1;
1350
- }
1351
1388
  var es2 = {
1352
1389
  describe,
1353
1390
  fallback: "un patr\xF3n cron irreconocible",