cronli5 0.1.1 → 0.1.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.
package/dist/lang/es.js CHANGED
@@ -14,6 +14,26 @@ function clockDigits(time, { sep, pad: padHour, lean }) {
14
14
  return head + sep + pad(time.minute) + (time.second ? sep + pad(time.second) : "");
15
15
  }
16
16
 
17
+ // src/core/specs.ts
18
+ var weekdayNumbers = {
19
+ SUN: 0,
20
+ MON: 1,
21
+ TUE: 2,
22
+ WED: 3,
23
+ THU: 4,
24
+ FRI: 5,
25
+ SAT: 6
26
+ };
27
+
28
+ // src/core/util.ts
29
+ function isNonNegativeInteger(value) {
30
+ const digits = /^\d+$/;
31
+ return digits.test(value);
32
+ }
33
+ function toFieldNumber(token, numberMap) {
34
+ return isNonNegativeInteger(token) ? +token : numberMap[token.toUpperCase()];
35
+ }
36
+
17
37
  // src/lang/es/dialects.ts
18
38
  var es = {
19
39
  ampm: false,
@@ -85,29 +105,6 @@ var weekdayNames = [
85
105
  "viernes",
86
106
  "s\xE1bado"
87
107
  ];
88
- var monthTokens = {
89
- JAN: 1,
90
- FEB: 2,
91
- MAR: 3,
92
- APR: 4,
93
- MAY: 5,
94
- JUN: 6,
95
- JUL: 7,
96
- AUG: 8,
97
- SEP: 9,
98
- OCT: 10,
99
- NOV: 11,
100
- DEC: 12
101
- };
102
- var weekdayTokens = {
103
- SUN: 0,
104
- MON: 1,
105
- TUE: 2,
106
- WED: 3,
107
- THU: 4,
108
- FRI: 5,
109
- SAT: 6
110
- };
111
108
  var nthWeekdayNames = [null, "primer", "segundo", "tercer", "cuarto", "quinto"];
112
109
  function normalizeOptions(options) {
113
110
  options = options || {};
@@ -151,6 +148,9 @@ function renderSecondsWithinMinute(ir, plan, opts) {
151
148
  return secondsLeadClause(ir, opts) + ", en el minuto " + minuteField + " de cada hora" + trailingQualifier(ir, opts);
152
149
  }
153
150
  function renderComposeSeconds(ir, plan, opts) {
151
+ if (plan.rest.kind === "clockTimes" && (ir.shapes.second === "wildcard" || ir.shapes.second === "step")) {
152
+ return pinnedMinuteSeconds(ir, plan.rest, opts);
153
+ }
154
154
  if (plan.rest.kind === "clockTimes" && ir.shapes.second === "list") {
155
155
  const clockPhrases = plan.rest.times.map(function clock(time) {
156
156
  return atTime(timePhrase(time.hour, time.minute, null, opts));
@@ -170,6 +170,14 @@ function renderComposeSeconds(ir, plan, opts) {
170
170
  }
171
171
  return secondsLeadClause(ir, opts) + ", " + render(ir, plan.rest, opts);
172
172
  }
173
+ function pinnedMinuteSeconds(ir, rest, opts) {
174
+ const dayTrail = leadingQualifier(ir, opts).trimEnd();
175
+ const trail = dayTrail ? ", " + dayTrail : "";
176
+ if (+rest.times[0].minute === 0) {
177
+ return secondsLeadClause(ir, opts) + " durante un minuto " + durationHourList(rest.times, opts) + trail;
178
+ }
179
+ return secondsLeadClause(ir, opts) + " de " + explicitClockList(rest.times, opts) + trail;
180
+ }
173
181
  function secondsLeadClause(ir, opts) {
174
182
  const secondField = ir.pattern.second;
175
183
  const shape = ir.shapes.second;
@@ -278,6 +286,9 @@ function renderMinuteFrequency(ir, plan, opts) {
278
286
  return phrase + trailingQualifier(ir, opts);
279
287
  }
280
288
  function renderMinuteSpanInHour(ir, plan, opts) {
289
+ if (ir.pattern.minute === "*") {
290
+ return "cada minuto de la hora " + fromTime(timePhrase(plan.hour, 0, null, opts)) + trailingQualifier(ir, opts);
291
+ }
281
292
  return "cada minuto " + timeRange(
282
293
  { hour: plan.hour, minute: plan.span[0] },
283
294
  { hour: plan.hour, minute: plan.span[1] },
@@ -394,6 +405,45 @@ function renderClockTimes(ir, plan, opts) {
394
405
  });
395
406
  return leadingQualifier(ir, opts) + groupClockTimes(phrases);
396
407
  }
408
+ function explicitClockList(times, opts) {
409
+ const phrases = times.map(function clock(time) {
410
+ return atTime(explicitTimePhrase(time.hour, time.minute, opts));
411
+ });
412
+ const grouped = groupClockTimes(phrases);
413
+ return grouped.startsWith("a ") ? grouped.slice(2) : grouped;
414
+ }
415
+ function durationHourList(times, opts) {
416
+ const phrases = times.map(function clock(time) {
417
+ return atTime(bareHourPhrase(time.hour, opts));
418
+ });
419
+ return groupClockTimes(phrases);
420
+ }
421
+ function bareHourPhrase(hour, opts) {
422
+ if (opts.ampm) {
423
+ return timePhrase(hour, 0, null, opts);
424
+ }
425
+ if (+hour === 0) {
426
+ return "medianoche";
427
+ }
428
+ if (+hour === 12) {
429
+ return "mediod\xEDa";
430
+ }
431
+ return (+hour === 1 ? "la " : "las ") + hour;
432
+ }
433
+ function explicitTimePhrase(hour, minute, opts) {
434
+ if (!opts.ampm) {
435
+ const article = +hour === 1 ? "la " : "las ";
436
+ const suffix = opts.style.hSuffix ? " h" : "";
437
+ return article + clockDigits(
438
+ { hour, minute, second: 0 },
439
+ { pad: true, sep: opts.style.sep }
440
+ ) + suffix;
441
+ }
442
+ const display = hour % 12 || 12;
443
+ const time = (display === 1 ? "la " : "las ") + clockDigits({ hour: display, minute, second: 0 }, { sep: opts.style.sep });
444
+ const period = opts.style.meridiem === "english" ? meridiemMark(hour) : dayPeriod(hour, opts);
445
+ return time + " " + period;
446
+ }
397
447
  function groupClockTimes(phrases) {
398
448
  if (phrases.length < 2) {
399
449
  return joinList(phrases);
@@ -574,13 +624,7 @@ function stepCycle60(segment, unit, anchor, opts) {
574
624
  }
575
625
  return "cada " + numero(interval, opts) + " " + unit + "s a partir del " + unit + " " + start + " de cada " + anchor;
576
626
  }
577
- if (60 % interval === 0) {
578
- return "cada " + numero(interval, opts) + " " + unit + "s";
579
- }
580
- if (segment.fires.length <= 2) {
581
- return "en los " + unit + "s " + joinList(wordList(segment.fires)) + " de cada " + anchor;
582
- }
583
- return "cada " + numero(interval, opts) + " " + unit + "s de cada " + anchor;
627
+ return "cada " + numero(interval, opts) + " " + unit + "s";
584
628
  }
585
629
  function stepHours(segment, opts) {
586
630
  if (segment.startToken.indexOf("-") !== -1) {
@@ -588,15 +632,12 @@ function stepHours(segment, opts) {
588
632
  }
589
633
  const start = segment.startToken === "*" ? 0 : +segment.startToken;
590
634
  const interval = segment.interval;
591
- if (start === 0 && 24 % interval === 0) {
635
+ if (start === 0) {
592
636
  return "cada " + numero(interval, opts) + " horas";
593
637
  }
594
638
  if (segment.fires.length <= 3) {
595
639
  return groupClockTimesByArticle(atTimes(segment.fires, opts));
596
640
  }
597
- if (start === 0) {
598
- return "cada " + numero(interval, opts) + " horas desde medianoche";
599
- }
600
641
  return "cada " + numero(interval, opts) + " horas a partir de " + timePhrase(start, 0, null, opts);
601
642
  }
602
643
  function atTimes(hours, opts) {
@@ -975,17 +1016,15 @@ function numero(n, opts) {
975
1016
  return numeral(n, numeros, opts);
976
1017
  }
977
1018
  function weekdayName(token) {
978
- if (token === "7" || token === 7) {
979
- return weekdayNames[0];
980
- }
981
- return weekdayNames[token] || weekdayNames[weekdayTokens[token]];
1019
+ const number = toFieldNumber("" + token, weekdayNumbers);
1020
+ return weekdayNames[number === 7 ? 0 : number];
982
1021
  }
983
1022
  function pluralWeekday(token) {
984
1023
  const name = weekdayName(token);
985
1024
  return name.endsWith("s") ? name : name + "s";
986
1025
  }
987
1026
  function monthName(token) {
988
- return monthNames[token] || monthNames[monthTokens[token]];
1027
+ return monthNames[+token];
989
1028
  }
990
1029
  function isOpenStep(field) {
991
1030
  return field.indexOf("/") !== -1 && field.indexOf("-") === -1 && field.indexOf(",") === -1;
@@ -995,7 +1034,9 @@ var es2 = {
995
1034
  fallback: "un patr\xF3n cron irreconocible",
996
1035
  options: normalizeOptions,
997
1036
  reboot: "al arrancar el sistema",
998
- sentence: (description) => "Se ejecuta " + description + "."
1037
+ // A description ending in a period already carries it, so closing the
1038
+ // sentence must not double it.
1039
+ sentence: (description) => "Se ejecuta " + description + (description.endsWith(".") ? "" : ".")
999
1040
  };
1000
1041
  var index_default = es2;
1001
1042
  export {
package/dist/lang/fi.cjs CHANGED
@@ -40,6 +40,26 @@ function clockDigits(time, { sep, pad: padHour, lean }) {
40
40
  return head + sep + pad(time.minute) + (time.second ? sep + pad(time.second) : "");
41
41
  }
42
42
 
43
+ // src/core/specs.ts
44
+ var weekdayNumbers = {
45
+ SUN: 0,
46
+ MON: 1,
47
+ TUE: 2,
48
+ WED: 3,
49
+ THU: 4,
50
+ FRI: 5,
51
+ SAT: 6
52
+ };
53
+
54
+ // src/core/util.ts
55
+ function isNonNegativeInteger(value) {
56
+ const digits = /^\d+$/;
57
+ return digits.test(value);
58
+ }
59
+ function toFieldNumber(token, numberMap) {
60
+ return isNonNegativeInteger(token) ? +token : numberMap[token.toUpperCase()];
61
+ }
62
+
43
63
  // src/lang/fi/dialects.ts
44
64
  var dialects = {
45
65
  fi: {
@@ -166,43 +186,18 @@ var monthStems = [
166
186
  "marras",
167
187
  "joulu"
168
188
  ];
169
- var monthTokens = {
170
- JAN: 1,
171
- FEB: 2,
172
- MAR: 3,
173
- APR: 4,
174
- MAY: 5,
175
- JUN: 6,
176
- JUL: 7,
177
- AUG: 8,
178
- SEP: 9,
179
- OCT: 10,
180
- NOV: 11,
181
- DEC: 12
182
- };
183
- var weekdayTokens = {
184
- SUN: 0,
185
- MON: 1,
186
- TUE: 2,
187
- WED: 3,
188
- THU: 4,
189
- FRI: 5,
190
- SAT: 6
191
- };
192
189
  var units = {
193
190
  minute: {
194
191
  mark: "joka tunti",
195
192
  anchor: "jokaisen tunnin",
196
193
  ela: "minuutista",
197
- gen: "minuutin",
198
- restart: "tasatunnista alkaen"
194
+ gen: "minuutin"
199
195
  },
200
196
  second: {
201
197
  mark: "joka minuutti",
202
198
  anchor: "jokaisen minuutin",
203
199
  ela: "sekunnista",
204
- gen: "sekunnin",
205
- restart: "joka minuutti"
200
+ gen: "sekunnin"
206
201
  }
207
202
  };
208
203
  function atMarks(values, unit, withMark) {
@@ -275,8 +270,22 @@ function renderComposeSeconds(ir, plan, opts) {
275
270
  }
276
271
  return stepPhrase + ", " + secondsLeadClause(ir, opts) + hourClause + trailingQualifier(ir, opts);
277
272
  }
273
+ if (plan.rest.kind === "clockTimes" && plan.rest.times.every((time) => +time.minute === 0)) {
274
+ return composeMinuteZero(ir, plan.rest, opts);
275
+ }
278
276
  return secondsLeadClause(ir, opts) + ", " + render(ir, plan.rest, opts);
279
277
  }
278
+ function composeMinuteZero(ir, rest, opts) {
279
+ const clocks = rest.times.map(function clock(time) {
280
+ return clockDigits(
281
+ { hour: time.hour, minute: time.minute },
282
+ { sep: opts.style.sep }
283
+ );
284
+ });
285
+ const frame = clocks.length === 1 ? "minuutin " + clocks[0] : "minuuttien " + joinList(clocks);
286
+ const dayTrail = leadingQualifier(ir, opts).trimEnd();
287
+ return secondsLeadClause(ir, opts) + " " + frame + " aikana" + (dayTrail ? ", " + dayTrail : "");
288
+ }
280
289
  function secondsLeadClause(ir, opts) {
281
290
  const secondField = ir.pattern.second;
282
291
  const shape = ir.shapes.second;
@@ -387,6 +396,9 @@ function renderMinuteFrequency(ir, plan, opts) {
387
396
  return phrase + trailingQualifier(ir, opts);
388
397
  }
389
398
  function renderMinuteSpanInHour(ir, plan, opts) {
399
+ if (ir.pattern.minute === "*") {
400
+ return "joka minuutti kello " + plan.hour + " aikana" + trailingQualifier(ir, opts);
401
+ }
390
402
  return "joka minuutti " + kloRange(
391
403
  { hour: plan.hour, minute: plan.span[0] },
392
404
  { hour: plan.hour, minute: plan.span[1] },
@@ -561,13 +573,7 @@ function stepCycle60(segment, unit, opts) {
561
573
  }
562
574
  return cadence + " " + unit.anchor + " " + unit.ela + " " + start + " alkaen";
563
575
  }
564
- if (60 % interval === 0) {
565
- return cadence;
566
- }
567
- if (segment.fires.length <= 2) {
568
- return atMarks(joinList(wordList(segment.fires)), unit, true);
569
- }
570
- return cadence + " " + unit.restart;
576
+ return cadence;
571
577
  }
572
578
  function stepHours(segment, opts) {
573
579
  if (segment.startToken.indexOf("-") !== -1) {
@@ -576,15 +582,12 @@ function stepHours(segment, opts) {
576
582
  const start = segment.startToken === "*" ? 0 : +segment.startToken;
577
583
  const interval = segment.interval;
578
584
  const cadence = genitive(interval, opts) + " tunnin v\xE4lein";
579
- if (start === 0 && 24 % interval === 0) {
585
+ if (start === 0) {
580
586
  return cadence;
581
587
  }
582
588
  if (segment.fires.length <= 3) {
583
589
  return kloList(segment.fires, opts);
584
590
  }
585
- if (start === 0) {
586
- return cadence + " keskiy\xF6st\xE4 alkaen";
587
- }
588
591
  return cadence + " klo " + hourElatives[start] + " alkaen";
589
592
  }
590
593
  function kloList(hours, opts) {
@@ -851,13 +854,10 @@ function quartzWeekdayPhrase(weekdayField) {
851
854
  }
852
855
  }
853
856
  function weekdayNumber(token) {
854
- if (token in weekdayTokens) {
855
- return weekdayTokens[token];
856
- }
857
- return +token % 7;
857
+ return toFieldNumber("" + token, weekdayNumbers) % 7;
858
858
  }
859
859
  function monthNumber(token) {
860
- return monthTokens[token] || +token;
860
+ return +token;
861
861
  }
862
862
  function applyYear(description, ir, opts) {
863
863
  const yearField = ir.pattern.year;
@@ -939,7 +939,9 @@ var fi = {
939
939
  fallback: "tunnistamaton cron-lauseke",
940
940
  options: normalizeOptions,
941
941
  reboot: "j\xE4rjestelm\xE4n k\xE4ynnistyess\xE4",
942
- sentence: (description) => "Suoritetaan " + description + "."
942
+ // A description ending in a period already carries it, so closing the
943
+ // sentence must not double it.
944
+ sentence: (description) => "Suoritetaan " + description + (description.endsWith(".") ? "" : ".")
943
945
  };
944
946
  var index_default = fi;
945
947
  module.exports = module.exports.default;
package/dist/lang/fi.js CHANGED
@@ -14,6 +14,26 @@ function clockDigits(time, { sep, pad: padHour, lean }) {
14
14
  return head + sep + pad(time.minute) + (time.second ? sep + pad(time.second) : "");
15
15
  }
16
16
 
17
+ // src/core/specs.ts
18
+ var weekdayNumbers = {
19
+ SUN: 0,
20
+ MON: 1,
21
+ TUE: 2,
22
+ WED: 3,
23
+ THU: 4,
24
+ FRI: 5,
25
+ SAT: 6
26
+ };
27
+
28
+ // src/core/util.ts
29
+ function isNonNegativeInteger(value) {
30
+ const digits = /^\d+$/;
31
+ return digits.test(value);
32
+ }
33
+ function toFieldNumber(token, numberMap) {
34
+ return isNonNegativeInteger(token) ? +token : numberMap[token.toUpperCase()];
35
+ }
36
+
17
37
  // src/lang/fi/dialects.ts
18
38
  var dialects = {
19
39
  fi: {
@@ -140,43 +160,18 @@ var monthStems = [
140
160
  "marras",
141
161
  "joulu"
142
162
  ];
143
- var monthTokens = {
144
- JAN: 1,
145
- FEB: 2,
146
- MAR: 3,
147
- APR: 4,
148
- MAY: 5,
149
- JUN: 6,
150
- JUL: 7,
151
- AUG: 8,
152
- SEP: 9,
153
- OCT: 10,
154
- NOV: 11,
155
- DEC: 12
156
- };
157
- var weekdayTokens = {
158
- SUN: 0,
159
- MON: 1,
160
- TUE: 2,
161
- WED: 3,
162
- THU: 4,
163
- FRI: 5,
164
- SAT: 6
165
- };
166
163
  var units = {
167
164
  minute: {
168
165
  mark: "joka tunti",
169
166
  anchor: "jokaisen tunnin",
170
167
  ela: "minuutista",
171
- gen: "minuutin",
172
- restart: "tasatunnista alkaen"
168
+ gen: "minuutin"
173
169
  },
174
170
  second: {
175
171
  mark: "joka minuutti",
176
172
  anchor: "jokaisen minuutin",
177
173
  ela: "sekunnista",
178
- gen: "sekunnin",
179
- restart: "joka minuutti"
174
+ gen: "sekunnin"
180
175
  }
181
176
  };
182
177
  function atMarks(values, unit, withMark) {
@@ -249,8 +244,22 @@ function renderComposeSeconds(ir, plan, opts) {
249
244
  }
250
245
  return stepPhrase + ", " + secondsLeadClause(ir, opts) + hourClause + trailingQualifier(ir, opts);
251
246
  }
247
+ if (plan.rest.kind === "clockTimes" && plan.rest.times.every((time) => +time.minute === 0)) {
248
+ return composeMinuteZero(ir, plan.rest, opts);
249
+ }
252
250
  return secondsLeadClause(ir, opts) + ", " + render(ir, plan.rest, opts);
253
251
  }
252
+ function composeMinuteZero(ir, rest, opts) {
253
+ const clocks = rest.times.map(function clock(time) {
254
+ return clockDigits(
255
+ { hour: time.hour, minute: time.minute },
256
+ { sep: opts.style.sep }
257
+ );
258
+ });
259
+ const frame = clocks.length === 1 ? "minuutin " + clocks[0] : "minuuttien " + joinList(clocks);
260
+ const dayTrail = leadingQualifier(ir, opts).trimEnd();
261
+ return secondsLeadClause(ir, opts) + " " + frame + " aikana" + (dayTrail ? ", " + dayTrail : "");
262
+ }
254
263
  function secondsLeadClause(ir, opts) {
255
264
  const secondField = ir.pattern.second;
256
265
  const shape = ir.shapes.second;
@@ -361,6 +370,9 @@ function renderMinuteFrequency(ir, plan, opts) {
361
370
  return phrase + trailingQualifier(ir, opts);
362
371
  }
363
372
  function renderMinuteSpanInHour(ir, plan, opts) {
373
+ if (ir.pattern.minute === "*") {
374
+ return "joka minuutti kello " + plan.hour + " aikana" + trailingQualifier(ir, opts);
375
+ }
364
376
  return "joka minuutti " + kloRange(
365
377
  { hour: plan.hour, minute: plan.span[0] },
366
378
  { hour: plan.hour, minute: plan.span[1] },
@@ -535,13 +547,7 @@ function stepCycle60(segment, unit, opts) {
535
547
  }
536
548
  return cadence + " " + unit.anchor + " " + unit.ela + " " + start + " alkaen";
537
549
  }
538
- if (60 % interval === 0) {
539
- return cadence;
540
- }
541
- if (segment.fires.length <= 2) {
542
- return atMarks(joinList(wordList(segment.fires)), unit, true);
543
- }
544
- return cadence + " " + unit.restart;
550
+ return cadence;
545
551
  }
546
552
  function stepHours(segment, opts) {
547
553
  if (segment.startToken.indexOf("-") !== -1) {
@@ -550,15 +556,12 @@ function stepHours(segment, opts) {
550
556
  const start = segment.startToken === "*" ? 0 : +segment.startToken;
551
557
  const interval = segment.interval;
552
558
  const cadence = genitive(interval, opts) + " tunnin v\xE4lein";
553
- if (start === 0 && 24 % interval === 0) {
559
+ if (start === 0) {
554
560
  return cadence;
555
561
  }
556
562
  if (segment.fires.length <= 3) {
557
563
  return kloList(segment.fires, opts);
558
564
  }
559
- if (start === 0) {
560
- return cadence + " keskiy\xF6st\xE4 alkaen";
561
- }
562
565
  return cadence + " klo " + hourElatives[start] + " alkaen";
563
566
  }
564
567
  function kloList(hours, opts) {
@@ -825,13 +828,10 @@ function quartzWeekdayPhrase(weekdayField) {
825
828
  }
826
829
  }
827
830
  function weekdayNumber(token) {
828
- if (token in weekdayTokens) {
829
- return weekdayTokens[token];
830
- }
831
- return +token % 7;
831
+ return toFieldNumber("" + token, weekdayNumbers) % 7;
832
832
  }
833
833
  function monthNumber(token) {
834
- return monthTokens[token] || +token;
834
+ return +token;
835
835
  }
836
836
  function applyYear(description, ir, opts) {
837
837
  const yearField = ir.pattern.year;
@@ -913,7 +913,9 @@ var fi = {
913
913
  fallback: "tunnistamaton cron-lauseke",
914
914
  options: normalizeOptions,
915
915
  reboot: "j\xE4rjestelm\xE4n k\xE4ynnistyess\xE4",
916
- sentence: (description) => "Suoritetaan " + description + "."
916
+ // A description ending in a period already carries it, so closing the
917
+ // sentence must not double it.
918
+ sentence: (description) => "Suoritetaan " + description + (description.endsWith(".") ? "" : ".")
917
919
  };
918
920
  var index_default = fi;
919
921
  export {
package/dist/lang/zh.cjs CHANGED
@@ -197,10 +197,12 @@ function hourFrame(ir) {
197
197
  return "\u5728" + hourList(ir) + "\uFF0C";
198
198
  }
199
199
  function renderMinuteFrequency(ir, plan) {
200
- const base = cadence(stepSegment(ir, "minute").interval, UNITS.minute);
200
+ const minuteStep = stepSegment(ir, "minute");
201
+ const base = minuteStep.startToken === "*" ? cadence(minuteStep.interval, UNITS.minute) : renderMinutePast(ir);
201
202
  const { hours } = plan;
202
203
  if (hours.kind === "step") {
203
- return cadence(stepSegment(ir, "hour").interval, UNITS.hour) + base;
204
+ const hourStep = stepSegment(ir, "hour");
205
+ return hourStep.startToken === "*" ? cadence(hourStep.interval, UNITS.hour) + base : "\u5728" + hourList(ir) + "\uFF0C" + base;
204
206
  }
205
207
  if (hours.kind === "single" || hours.kind === "window" && hours.from === hours.to) {
206
208
  return "\u5728" + hourWord(hours.from) + "\u81F3" + hours.from + "\u70B9" + hours.last + "\u5206\u4E4B\u95F4\uFF0C" + base;
@@ -215,6 +217,9 @@ function renderMinuteFrequency(ir, plan) {
215
217
  }
216
218
  function renderMinuteSpanInHour(ir, plan) {
217
219
  const span = plan;
220
+ if (ir.pattern.minute === "*") {
221
+ return hourWord(span.hour) + "\u7684\u6BCF\u4E00\u5206\u949F";
222
+ }
218
223
  return "\u5728" + hourWord(span.hour) + "\u81F3" + span.hour + "\u70B9" + span.span[1] + "\u5206\u4E4B\u95F4\uFF0C\u6BCF\u5206\u949F";
219
224
  }
220
225
  function renderMinutesAcrossHours(ir, plan) {
@@ -225,12 +230,17 @@ function renderMinutesAcrossHours(ir, plan) {
225
230
  return hourList(ir) + "\uFF0C\u6BCF\u5C0F\u65F6" + valueList(fieldSegments(ir, "minute"), "\u5206") + "\uFF0C\u6BCF\u5206\u949F";
226
231
  }
227
232
  function renderMinuteSpanAcrossHourStep(ir, plan) {
228
- const cad = cadence(stepSegment(ir, "hour").interval, UNITS.hour);
233
+ const hourStep = stepSegment(ir, "hour");
229
234
  const { form } = plan;
230
- if (form === "wildcard") {
231
- return cad + "\u5185\uFF0C\u6BCF\u5206\u949F";
235
+ const minuteTail = form === "wildcard" ? "\u6BCF\u5206\u949F" : "\u6BCF\u5C0F\u65F6" + valueList(fieldSegments(ir, "minute"), "\u5206") + "\uFF0C\u6BCF\u5206\u949F";
236
+ if (hourStep.startToken !== "*") {
237
+ return form === "wildcard" ? "\u5728" + hourList(ir) + "\uFF0C" + minuteTail : hourList(ir) + "\uFF0C" + minuteTail;
232
238
  }
233
- return cad + "\uFF0C\u6BCF\u5C0F\u65F6" + valueList(fieldSegments(ir, "minute"), "\u5206") + "\uFF0C\u6BCF\u5206\u949F";
239
+ if (hourStep.interval === 2 && form === "wildcard") {
240
+ return "\u5728\u5076\u6570\u5C0F\u65F6\uFF0C" + minuteTail;
241
+ }
242
+ const cad = cadence(hourStep.interval, UNITS.hour);
243
+ return form === "wildcard" ? cad + "\u5185\uFF0C" + minuteTail : cad + "\uFF0C" + minuteTail;
234
244
  }
235
245
  function renderClockTimes(ir, plan, opts) {
236
246
  const { times } = plan;
@@ -265,9 +275,6 @@ function renderHourStep(ir) {
265
275
  if (segment.fires.length <= 2) {
266
276
  return joinAnd(segment.fires.map(hourWord));
267
277
  }
268
- if (24 % segment.interval !== 0) {
269
- return "\u4ECE" + hourWord(segment.fires[0]) + "\u8D77\uFF0C" + cadence(segment.interval, UNITS.hour);
270
- }
271
278
  return cadence(segment.interval, UNITS.hour);
272
279
  }
273
280
  function renderRangeOfMinutes(ir) {
@@ -319,9 +326,19 @@ function isHourCadence(ir) {
319
326
  function composeSecondsOnHour(ir, plan, opts) {
320
327
  const sec = secondClause(ir);
321
328
  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;
336
+ }
322
337
  const restText = render(ir, rest, opts);
323
- if ((rest.kind === "clockTimes" || rest.kind === "compactClockTimes") && isDaily(ir)) {
324
- return "\u6BCF\u5929" + restText + sec;
338
+ if (rest.kind === "clockTimes" || rest.kind === "compactClockTimes") {
339
+ if (isDaily(ir)) {
340
+ return "\u6BCF\u5929" + restText + sec;
341
+ }
325
342
  }
326
343
  if (rest.kind === "singleMinute") {
327
344
  return restText + "\uFF0C" + sec;
@@ -345,6 +362,9 @@ function composeSecondsCadence(ir) {
345
362
  function composeSecondsListed(ir) {
346
363
  const sec = secondClause(ir);
347
364
  const minutes = "\u6BCF\u5C0F\u65F6" + valueList(fieldSegments(ir, "minute"), "\u5206");
365
+ if (ir.shapes.hour === "single" && sec === "\u6BCF\u79D2") {
366
+ return hourWord(hourFires(ir)[0]) + valueList(fieldSegments(ir, "minute"), "\u5206") + "\u7684\u6BCF\u4E00\u79D2";
367
+ }
348
368
  if (ir.shapes.hour === "wildcard") {
349
369
  return minutes + "\uFF0C" + sec;
350
370
  }
@@ -354,10 +374,13 @@ function composeSecondsListed(ir) {
354
374
  return hourFrame(ir) + minutes + "\uFF0C" + sec;
355
375
  }
356
376
  function renderComposeSeconds(ir, plan, opts) {
357
- if (ir.pattern.minute === "0") {
377
+ const { rest } = plan;
378
+ const composedClock = rest.kind === "clockTimes" || rest.kind === "compactClockTimes";
379
+ if (ir.pattern.minute === "0" || composedClock && ir.shapes.minute === "single") {
358
380
  return composeSecondsOnHour(ir, plan, opts);
359
381
  }
360
- if (ir.pattern.minute === "*" || ir.shapes.minute === "step") {
382
+ const minuteCadence = ir.pattern.minute === "*" || ir.shapes.minute === "step" && stepSegment(ir, "minute").startToken === "*";
383
+ if (minuteCadence) {
361
384
  return composeSecondsCadence(ir);
362
385
  }
363
386
  return composeSecondsListed(ir);