cronli5 0.1.4 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/lang/zh.cjs CHANGED
@@ -29,6 +29,21 @@ function isNonNegativeInteger(value) {
29
29
  const digits = /^\d+$/;
30
30
  return digits.test(value);
31
31
  }
32
+ function arithmeticStep(values) {
33
+ if (values.length < 5) {
34
+ return null;
35
+ }
36
+ const interval = values[1] - values[0];
37
+ if (interval < 2) {
38
+ return null;
39
+ }
40
+ for (let i = 2; i < values.length; i += 1) {
41
+ if (values[i] - values[i - 1] !== interval) {
42
+ return null;
43
+ }
44
+ }
45
+ return { start: values[0], interval, last: values[values.length - 1] };
46
+ }
32
47
  function toFieldNumber(token, numberMap) {
33
48
  return isNonNegativeInteger(token) ? +token : numberMap[token.toUpperCase()];
34
49
  }
@@ -57,6 +72,7 @@ var monthNumbers = {
57
72
  NOV: 11,
58
73
  DEC: 12
59
74
  };
75
+ var maxClockTimes = 6;
60
76
 
61
77
  // src/lang/zh/dialects.ts
62
78
  var zh = { variant: "Hans" };
@@ -87,6 +103,46 @@ function stepSegment(ir, field) {
87
103
  function cadence(interval, unit) {
88
104
  return interval === 1 ? "\u6BCF" + unit : "\u6BCF" + interval + unit;
89
105
  }
106
+ function renderStride(stride) {
107
+ const { interval, start, last, cycle, unit, mark, anchor } = stride;
108
+ const tiles = cycle % interval === 0;
109
+ if (start === 0 && tiles) {
110
+ return cadence(interval, unit);
111
+ }
112
+ const lead = anchor + "\u4ECE" + start + mark + "\u8D77" + cadence(interval, unit);
113
+ return start < interval && tiles ? lead : lead + "\uFF0C\u81F3" + last + mark;
114
+ }
115
+ function singleValues(segments) {
116
+ const values = [];
117
+ for (const segment of segments) {
118
+ if (segment.kind !== "single") {
119
+ return null;
120
+ }
121
+ values.push(+segment.value);
122
+ }
123
+ return values;
124
+ }
125
+ function strideFromSegments(segments, unit, mark, anchor) {
126
+ const values = singleValues(segments);
127
+ const step = values && arithmeticStep(values);
128
+ return step ? renderStride({ ...step, cycle: 60, unit, mark, anchor }) : null;
129
+ }
130
+ function stepClause(segment, unit, mark, anchor) {
131
+ const start = segment.startToken === "*" ? 0 : +segment.startToken;
132
+ const short = start !== 0 && segment.fires.length <= 3;
133
+ if (segment.startToken.indexOf("-") !== -1 || short) {
134
+ return anchor + segment.fires.join("\u3001") + mark;
135
+ }
136
+ return renderStride({
137
+ interval: segment.interval,
138
+ start,
139
+ last: segment.fires[segment.fires.length - 1],
140
+ cycle: 60,
141
+ unit,
142
+ mark,
143
+ anchor
144
+ });
145
+ }
90
146
  function dayPeriod(hour) {
91
147
  if (hour < 6) {
92
148
  return "\u51CC\u6668";
@@ -183,11 +239,28 @@ function renderEveryMinute() {
183
239
  function renderEveryHour() {
184
240
  return "\u6BCF\u5C0F\u65F6";
185
241
  }
242
+ function minuteHourClause(ir) {
243
+ const segments = fieldSegments(ir, "minute");
244
+ if (ir.shapes.minute === "step") {
245
+ return stepClause(stepSegment(ir, "minute"), "\u5206\u949F", "\u5206", "\u6BCF\u5C0F\u65F6");
246
+ }
247
+ return strideFromSegments(segments, "\u5206\u949F", "\u5206", "\u6BCF\u5C0F\u65F6") ?? "\u6BCF\u5C0F\u65F6" + valueList(segments, "\u5206");
248
+ }
186
249
  function renderMinutePast(ir) {
187
- return "\u6BCF\u5C0F\u65F6" + valueList(fieldSegments(ir, "minute"), "\u5206");
250
+ return minuteHourClause(ir);
251
+ }
252
+ function hourSegmentWords(segment) {
253
+ if (segment.kind === "range") {
254
+ return [hourWord(+segment.bounds[0]) + "\u81F3" + hourWord(+segment.bounds[1])];
255
+ }
256
+ if (segment.kind === "step") {
257
+ return segment.fires.map(hourWord);
258
+ }
259
+ return [hourWord(+segment.value)];
188
260
  }
189
261
  function hourList(ir) {
190
- return joinAnd(hourFires(ir).map(hourWord));
262
+ const words = fieldSegments(ir, "hour").flatMap(hourSegmentWords);
263
+ return joinAnd(words);
191
264
  }
192
265
  function hourFrame(ir) {
193
266
  if (ir.shapes.hour === "range") {
@@ -198,11 +271,13 @@ function hourFrame(ir) {
198
271
  }
199
272
  function renderMinuteFrequency(ir, plan) {
200
273
  const minuteStep = stepSegment(ir, "minute");
201
- const base = minuteStep.startToken === "*" ? cadence(minuteStep.interval, UNITS.minute) : renderMinutePast(ir);
274
+ const base = stepClause(minuteStep, UNITS.minute, "\u5206", "\u6BCF\u5C0F\u65F6");
202
275
  const { hours } = plan;
203
- if (hours.kind === "step") {
204
- const hourStep = stepSegment(ir, "hour");
205
- return hourStep.startToken === "*" ? cadence(hourStep.interval, UNITS.hour) + base : "\u5728" + hourList(ir) + "\uFF0C" + base;
276
+ if (hours.kind === "step" || hours.kind === "during") {
277
+ const hourCad = hourCadencePhrase(ir);
278
+ if (hourCad !== null) {
279
+ return hourCad + (hourCad.indexOf("\u81F3") === -1 ? "" : "\uFF0C") + base;
280
+ }
206
281
  }
207
282
  if (hours.kind === "single" || hours.kind === "window" && hours.from === hours.to) {
208
283
  return "\u5728" + hourWord(hours.from) + "\u81F3" + hours.from + "\u70B9" + hours.last + "\u5206\u4E4B\u95F4\uFF0C" + base;
@@ -224,17 +299,21 @@ function renderMinuteSpanInHour(ir, plan) {
224
299
  }
225
300
  function renderMinutesAcrossHours(ir, plan) {
226
301
  const { form } = plan;
302
+ const hourCad = hourCadencePhrase(ir);
227
303
  if (form === "wildcard") {
228
- return "\u5728" + hourList(ir) + "\uFF0C\u6BCF\u5206\u949F";
304
+ return hourCad === null ? "\u5728" + hourList(ir) + "\uFF0C\u6BCF\u5206\u949F" : hourCad + "\uFF0C\u6BCF\u5206\u949F";
229
305
  }
230
- return hourList(ir) + "\uFF0C\u6BCF\u5C0F\u65F6" + valueList(fieldSegments(ir, "minute"), "\u5206") + "\uFF0C\u6BCF\u5206\u949F";
306
+ return (hourCad ?? hourList(ir)) + "\uFF0C" + minuteHourClause(ir) + "\uFF0C\u6BCF\u5206\u949F";
231
307
  }
232
308
  function renderMinuteSpanAcrossHourStep(ir, plan) {
233
309
  const hourStep = stepSegment(ir, "hour");
234
310
  const { form } = plan;
235
- const minuteTail = form === "wildcard" ? "\u6BCF\u5206\u949F" : "\u6BCF\u5C0F\u65F6" + valueList(fieldSegments(ir, "minute"), "\u5206") + "\uFF0C\u6BCF\u5206\u949F";
311
+ if (form === "list") {
312
+ return hourCadencePhrase(ir) + "\uFF0C" + renderMinutePast(ir);
313
+ }
314
+ const minuteTail = form === "wildcard" ? "\u6BCF\u5206\u949F" : minuteHourClause(ir) + "\uFF0C\u6BCF\u5206\u949F";
236
315
  if (hourStep.startToken !== "*") {
237
- return form === "wildcard" ? "\u5728" + hourList(ir) + "\uFF0C" + minuteTail : hourList(ir) + "\uFF0C" + minuteTail;
316
+ return hourCadencePhrase(ir) + "\uFF0C" + minuteTail;
238
317
  }
239
318
  if (hourStep.interval === 2 && form === "wildcard") {
240
319
  return "\u5728\u5076\u6570\u5C0F\u65F6\uFF0C" + minuteTail;
@@ -243,15 +322,27 @@ function renderMinuteSpanAcrossHourStep(ir, plan) {
243
322
  return form === "wildcard" ? cad + "\u5185\uFF0C" + minuteTail : cad + "\uFF0C" + minuteTail;
244
323
  }
245
324
  function renderClockTimes(ir, plan, opts) {
325
+ const cad = hourCadenceText(ir);
326
+ if (cad !== null) {
327
+ return cad;
328
+ }
246
329
  const { times } = plan;
247
330
  return joinAnd(times.map((t) => clockTime(t.hour, t.minute, t.second, opts)));
248
331
  }
249
332
  function renderCompactClockTimes(ir, plan) {
250
- const { minute } = plan;
333
+ const cad = hourCadenceText(ir);
334
+ if (cad !== null) {
335
+ return cad;
336
+ }
337
+ const compact = plan;
251
338
  const secs = fieldSegments(ir, "second");
252
339
  const tail = secs.length && ir.pattern.second !== "0" ? "\uFF0C\u7B2C" + valueText(secs) + "\u79D2" : "";
253
- if (minute > 0) {
254
- return "\u6BCF\u5C0F\u65F6" + valueList(fieldSegments(ir, "minute"), "\u5206") + "\uFF0C\u5728" + hourList(ir) + tail;
340
+ if (!compact.fold) {
341
+ const hourCad = hourCadencePhrase(ir);
342
+ return hourCad === null ? minuteHourClause(ir) + "\uFF0C\u5728" + hourList(ir) + tail : hourCad + "\uFF0C" + minuteHourClause(ir) + tail;
343
+ }
344
+ if (compact.minute > 0) {
345
+ return minuteHourClause(ir) + "\uFF0C\u5728" + hourList(ir) + tail;
255
346
  }
256
347
  return hourList(ir) + tail;
257
348
  }
@@ -259,7 +350,7 @@ function renderHourRange(ir, plan) {
259
350
  const range = plan;
260
351
  if (range.minuteForm === "lead") {
261
352
  const minuteSegs = fieldSegments(ir, "minute");
262
- const past = minuteSegs.length && ir.pattern.minute !== "0" ? "\u6BCF\u5C0F\u65F6" + valueList(minuteSegs, "\u5206") : "\u6BCF\u5C0F\u65F6";
353
+ const past = minuteSegs.length && ir.pattern.minute !== "0" ? minuteHourClause(ir) : "\u6BCF\u5C0F\u65F6";
263
354
  return "\u5728" + hourWord(range.from) + "\u81F3" + hourWord(range.to) + "\u4E4B\u95F4\uFF0C" + past;
264
355
  }
265
356
  if (range.minuteForm === "range") {
@@ -269,16 +360,68 @@ function renderHourRange(ir, plan) {
269
360
  }
270
361
  function renderHourStep(ir) {
271
362
  const segment = stepSegment(ir, "hour");
272
- if (segment.startToken !== "*") {
273
- return hourList(ir);
274
- }
275
363
  if (segment.fires.length <= 2) {
276
364
  return joinAnd(segment.fires.map(hourWord));
277
365
  }
278
- return cadence(segment.interval, UNITS.hour);
366
+ return hourCadencePhrase(ir);
367
+ }
368
+ function hourStride(ir) {
369
+ const segments = fieldSegments(ir, "hour");
370
+ if (segments.length === 1 && segments[0].kind === "step") {
371
+ const { fires, interval } = segments[0];
372
+ return { interval, start: fires[0], last: fires[fires.length - 1] };
373
+ }
374
+ const values = singleValues(segments);
375
+ return values && arithmeticStep(values);
376
+ }
377
+ function hourCadencePhrase(ir) {
378
+ const stride = hourStride(ir);
379
+ return stride && renderStride({
380
+ ...stride,
381
+ cycle: 24,
382
+ unit: UNITS.hour,
383
+ mark: "\u70B9",
384
+ anchor: ""
385
+ });
386
+ }
387
+ function hourCadence(ir) {
388
+ const stride = hourStride(ir);
389
+ if (!stride) {
390
+ return null;
391
+ }
392
+ const fires = (stride.last - stride.start) / stride.interval + 1;
393
+ if (ir.pattern.second === "0" && fires <= maxClockTimes) {
394
+ return null;
395
+ }
396
+ const prefix = hourCadencePhrase(ir);
397
+ if (prefix.indexOf("\u81F3") !== -1) {
398
+ return null;
399
+ }
400
+ const minute = +ir.pattern.minute;
401
+ const subMinute = ir.pattern.second === "*" || ir.shapes.second === "step";
402
+ if (minute === 0 && subMinute) {
403
+ return stride.interval === 2 && stride.start === 0 ? "\u5728\u5076\u6570\u5C0F\u65F60\u5206" + secondTail(ir) : null;
404
+ }
405
+ if (minute === 0) {
406
+ return prefix + "0\u5206" + secondTail(ir);
407
+ }
408
+ return ir.pattern.second === "0" ? prefix + minute + "\u5206" : prefix + minute + "\u5206" + secondTail(ir);
409
+ }
410
+ function hourCadenceText(ir) {
411
+ if (ir.shapes.minute !== "single") {
412
+ return null;
413
+ }
414
+ if (+ir.pattern.minute === 0 && ir.pattern.second === "0") {
415
+ return hourCadencePhrase(ir);
416
+ }
417
+ return hourCadence(ir);
418
+ }
419
+ function secondTail(ir) {
420
+ const sec = secondClause(ir);
421
+ return sec === "\u6BCF\u79D2" ? "\u7684\u6BCF\u4E00\u79D2" : "\u7684" + sec;
279
422
  }
280
423
  function renderRangeOfMinutes(ir) {
281
- return "\u6BCF\u5C0F\u65F6" + valueList(fieldSegments(ir, "minute"), "\u5206") + "\uFF0C\u6BCF\u5206\u949F";
424
+ return minuteHourClause(ir) + "\uFF0C\u6BCF\u5206\u949F";
282
425
  }
283
426
  function renderStandaloneSeconds(ir) {
284
427
  const segs = fieldSegments(ir, "second");
@@ -286,7 +429,7 @@ function renderStandaloneSeconds(ir) {
286
429
  if (segs.length === 1 && first.kind === "step" && first.startToken === "*") {
287
430
  return cadence(first.interval, UNITS.second);
288
431
  }
289
- return "\u6BCF\u5206\u949F\u7B2C" + valueText(segs) + "\u79D2";
432
+ return strideFromSegments(segs, "\u79D2", "\u79D2", "\u6BCF\u5206\u949F") ?? "\u6BCF\u5206\u949F\u7B2C" + valueText(segs) + "\u79D2";
290
433
  }
291
434
  function renderSecondPastMinute(ir) {
292
435
  return "\u6BCF\u5206\u949F\u7B2C" + valueText(fieldSegments(ir, "second")) + "\u79D2";
@@ -309,7 +452,7 @@ function secondClause(ir) {
309
452
  if (segs.length === 1 && first.kind === "step" && first.startToken === "*") {
310
453
  return cadence(first.interval, UNITS.second);
311
454
  }
312
- return "\u7B2C" + valueText(segs) + "\u79D2";
455
+ return strideFromSegments(segs, "\u79D2", "\u79D2", "\u6BCF\u5206\u949F") ?? "\u7B2C" + valueText(segs) + "\u79D2";
313
456
  }
314
457
  function minuteClause(ir) {
315
458
  if (ir.pattern.minute === "*") {
@@ -320,56 +463,91 @@ function minuteClause(ir) {
320
463
  }
321
464
  return valueList(fieldSegments(ir, "minute"), "\u5206");
322
465
  }
323
- function isHourCadence(ir) {
324
- return ir.shapes.hour === "step" && stepSegment(ir, "hour").startToken === "*";
466
+ function clockRestCarriesSecond(rest) {
467
+ return rest.kind === "clockTimes" && rest.times.some((time) => Boolean(time.second));
325
468
  }
326
469
  function composeSecondsOnHour(ir, plan, opts) {
327
470
  const sec = secondClause(ir);
328
471
  const { rest } = plan;
329
- if ((rest.kind === "clockTimes" || rest.kind === "compactClockTimes") && ir.pattern.minute === "0") {
330
- const clocks = hourFires(ir).map(function clock(hour) {
331
- return hourWord(hour) + "0\u5206";
332
- });
333
- const tail = sec === "\u6BCF\u79D2" ? "\u7684\u6BCF\u4E00\u79D2" : "\u7684" + sec;
334
- const core = joinAnd(clocks) + tail;
335
- return isDaily(ir) ? "\u6BCF\u5929" + core : core;
472
+ const composedClock = rest.kind === "clockTimes" || rest.kind === "compactClockTimes";
473
+ if (composedClock) {
474
+ const hourCad = hourCadence(ir);
475
+ if (hourCad !== null) {
476
+ return hourCad;
477
+ }
478
+ }
479
+ if (composedClock && ir.pattern.minute === "0") {
480
+ return composeMinuteZeroClocks(ir, sec);
336
481
  }
337
482
  const restText = render(ir, rest, opts);
338
- if (rest.kind === "clockTimes" || rest.kind === "compactClockTimes") {
339
- if (isDaily(ir)) {
340
- return "\u6BCF\u5929" + restText + sec;
341
- }
483
+ const secTail = clockRestCarriesSecond(rest) ? "" : sec;
484
+ if (composedClock && isDaily(ir)) {
485
+ return "\u6BCF\u5929" + restText + secTail;
342
486
  }
343
487
  if (rest.kind === "singleMinute") {
344
488
  return restText + "\uFF0C" + sec;
345
489
  }
346
- return restText + sec;
490
+ return restText + secTail;
491
+ }
492
+ function composeMinuteZeroClocks(ir, sec) {
493
+ if (hasHourWindow(ir)) {
494
+ return isDaily(ir) ? "\u6BCF\u5929" + hourRangeWindow(ir, sec) : hourRangeWindow(ir, sec);
495
+ }
496
+ const clocks = hourFires(ir).map(function clock(hour) {
497
+ return hour === 12 ? "\u6B63\u5348" : hourWord(hour) + "0\u5206";
498
+ });
499
+ const nested = strideFromSegments(fieldSegments(ir, "second"), "\u79D2", "\u79D2", "");
500
+ const tail = sec === "\u6BCF\u79D2" ? "\u7684\u6BCF\u4E00\u79D2" : "\u7684" + (nested ?? sec);
501
+ const core = joinAnd(clocks) + tail;
502
+ return isDaily(ir) ? "\u6BCF\u5929" + core : core;
503
+ }
504
+ function hasHourWindow(ir) {
505
+ return fieldSegments(ir, "hour").some(function range(segment) {
506
+ return segment.kind === "range";
507
+ });
508
+ }
509
+ function hourRangeWindow(ir, sec) {
510
+ const span = hourList(ir);
511
+ if (ir.pattern.second === "*" || ir.shapes.second === "step") {
512
+ return span + "0\u5206" + (sec === "\u6BCF\u79D2" ? "\u7684\u6BCF\u4E00\u79D2" : "\u7684" + sec);
513
+ }
514
+ return span + "\uFF0C" + sec;
347
515
  }
348
516
  function composeSecondsCadence(ir) {
349
517
  const sec = secondClause(ir);
350
518
  const tail = minuteClause(ir) + sec;
351
- if (isHourCadence(ir)) {
352
- return cadence(stepSegment(ir, "hour").interval, UNITS.hour) + "\u7684" + tail;
519
+ const hourCad = hourCadencePhrase(ir);
520
+ if (hourCad !== null) {
521
+ return hourCad + (hourCad.indexOf("\u81F3") === -1 ? "\u7684" : "\uFF0C") + tail;
353
522
  }
354
523
  if (ir.shapes.hour === "single") {
355
524
  return hourWord(hourFires(ir)[0]) + "\u7684" + tail;
356
525
  }
357
526
  if (ir.shapes.hour === "wildcard") {
527
+ if (ir.shapes.minute === "step" && sec === "\u6BCF\u79D2") {
528
+ const minuteStep = stepSegment(ir, "minute");
529
+ if (minuteStep.startToken === "*" && minuteStep.interval === 2) {
530
+ return "\u6BCF\u5076\u6570\u5206\u949F\u7684\u6BCF\u4E00\u79D2";
531
+ }
532
+ }
358
533
  return sec + "\uFF0C" + minuteClause(ir);
359
534
  }
360
535
  return hourFrame(ir) + tail;
361
536
  }
362
537
  function composeSecondsListed(ir) {
363
538
  const sec = secondClause(ir);
364
- const minutes = "\u6BCF\u5C0F\u65F6" + valueList(fieldSegments(ir, "minute"), "\u5206");
539
+ const minutes = minuteHourClause(ir);
365
540
  if (ir.shapes.hour === "single" && sec === "\u6BCF\u79D2") {
366
- return hourWord(hourFires(ir)[0]) + valueList(fieldSegments(ir, "minute"), "\u5206") + "\u7684\u6BCF\u4E00\u79D2";
541
+ const minuteSegs = fieldSegments(ir, "minute");
542
+ const minuteCad = strideFromSegments(minuteSegs, "\u5206\u949F", "\u5206", "") ?? valueList(minuteSegs, "\u5206");
543
+ return hourWord(hourFires(ir)[0]) + minuteCad + "\u7684\u6BCF\u4E00\u79D2";
367
544
  }
368
545
  if (ir.shapes.hour === "wildcard") {
369
546
  return minutes + "\uFF0C" + sec;
370
547
  }
371
- if (isHourCadence(ir)) {
372
- return cadence(stepSegment(ir, "hour").interval, UNITS.hour) + "\uFF0C" + minutes + "\uFF0C" + sec;
548
+ const hourCad = hourCadencePhrase(ir);
549
+ if (hourCad !== null) {
550
+ return hourCad + "\uFF0C" + minutes + "\uFF0C" + sec;
373
551
  }
374
552
  return hourFrame(ir) + minutes + "\uFF0C" + sec;
375
553
  }
@@ -580,11 +758,16 @@ function composeCadence(ir, core) {
580
758
  function composeWindow(ir, core) {
581
759
  return qualifier(ir) + core;
582
760
  }
761
+ function hourCadenceApplies(ir) {
762
+ return hourCadenceText(ir) !== null;
763
+ }
583
764
  function describe(ir, opts) {
584
765
  const { kind } = ir.plan;
585
766
  const core = render(ir, ir.plan, opts);
586
767
  let composed = core;
587
- if (kind === "clockTimes" || kind === "compactClockTimes" && ir.pattern.minute === "0") {
768
+ if (hourCadenceApplies(ir)) {
769
+ composed = composeCadence(ir, core);
770
+ } else if (kind === "clockTimes" || kind === "compactClockTimes" && ir.pattern.minute === "0") {
588
771
  composed = composePoint(ir, core);
589
772
  } else if (kind === "hourStep" || kind === "minuteFrequency" || kind === "minuteSpanAcrossHourStep" || kind === "compactClockTimes") {
590
773
  composed = composeCadence(ir, core);