cronli5 0.1.6 → 0.2.0

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.cjs CHANGED
@@ -72,6 +72,26 @@ function arithmeticStep(values) {
72
72
  }
73
73
  return { start: values[0], interval, last: values[values.length - 1] };
74
74
  }
75
+ function weekdayDisplayKey(value) {
76
+ return value === 0 ? 7 : value;
77
+ }
78
+ function orderWeekdaysForDisplay(segments) {
79
+ const flattened = segments.flatMap(function flat(segment) {
80
+ return segment.kind === "step" ? segment.fires.map(function single(value) {
81
+ return { kind: "single", value: "" + value };
82
+ }) : [segment];
83
+ });
84
+ function key(segment) {
85
+ return segment.kind === "range" ? weekdayDisplayKey(+segment.bounds[0]) : weekdayDisplayKey(+segment.value);
86
+ }
87
+ return flattened.map(function index(segment, position) {
88
+ return [segment, position];
89
+ }).sort(function byDisplayKey(a, b) {
90
+ return key(a[0]) - key(b[0]) || a[1] - b[1];
91
+ }).map(function unwrap(pair) {
92
+ return pair[0];
93
+ });
94
+ }
75
95
  function toFieldNumber(token, numberMap) {
76
96
  return isNonNegativeInteger(token) ? +token : numberMap[token.toUpperCase()];
77
97
  }
@@ -224,7 +244,7 @@ function renderComposeSeconds(ir, plan, opts) {
224
244
  }
225
245
  if (plan.rest.kind === "hourRange" && ir.shapes.second === "step" && ir.pattern.weekday !== "*") {
226
246
  const restNode = plan.rest;
227
- const window = hourWindow(restNode, opts);
247
+ const window = hourWindow(boundedWindow(restNode), opts);
228
248
  const dayFrame = weekdayQualifier(ir) + monthScope(ir);
229
249
  const cadence = "cada " + numero(stepSegment(ir.analyses.segments.second).interval, opts) + " segundos del minuto " + ir.pattern.minute;
230
250
  return dayFrame + ", " + window + ", " + cadence;
@@ -437,7 +457,8 @@ function renderHourStep(ir, plan, opts) {
437
457
  return stepHours(stepSegment(ir.analyses.segments.hour), opts) + trailingQualifier(ir, opts);
438
458
  }
439
459
  function boundedWindow(plan) {
440
- return { from: plan.from, last: plan.boundMinute ?? 0, to: plan.to };
460
+ const last = plan.minuteForm === "wildcard" ? plan.boundMinute ?? 0 : 0;
461
+ return { from: plan.from, last, to: plan.to };
441
462
  }
442
463
  function hourWindow(window, opts) {
443
464
  return timeRange(
@@ -481,7 +502,7 @@ function dowArm(ir) {
481
502
  if (quartz) {
482
503
  return quartz;
483
504
  }
484
- const segments = flattenSteps(fieldSegments(ir, "weekday"));
505
+ const segments = orderWeekdaysForDisplay(fieldSegments(ir, "weekday"));
485
506
  const allSingles = segments.every(function single(segment) {
486
507
  return segment.kind === "single";
487
508
  });
@@ -705,7 +726,7 @@ function renderCompactClockTimes(ir, plan, opts) {
705
726
  return leadingQualifier(ir, opts) + hourSegmentTimes(ir, plan.minute, ir.analyses.clockSecond, opts);
706
727
  }
707
728
  const cadence = unevenHourCadence(ir, opts);
708
- const phrase = cadence ? minutesList(ir, opts) + ", " + cadence + trailingQualifier(ir, opts) : minutesList(ir, opts) + ", " + hourSegmentTimes(ir, 0, null, opts) + trailingQualifier(ir, opts);
729
+ const phrase = cadence ? minutesList(ir, opts) + ", " + cadence + trailingQualifier(ir, opts) : minutesList(ir, opts) + ", " + hourContextTimes(ir, opts) + trailingQualifier(ir, opts);
709
730
  return ir.analyses.clockSecond ? secondsLeadClause(ir, opts) + ", " + phrase : phrase;
710
731
  }
711
732
  var renderers = {
@@ -896,6 +917,48 @@ function hourRangeCadence(ir, minute, opts) {
896
917
  }
897
918
  return hourCadenceLead(ir, minute, opts) + ", " + hourSegmentTimes(ir, 0, null, opts) + trailingQualifier(ir, opts);
898
919
  }
920
+ function hourContextTimes(ir, opts) {
921
+ const segments = hourSegments(ir);
922
+ const points = [];
923
+ const hasRange = segments.some(function range(segment) {
924
+ return segment.kind === "range";
925
+ });
926
+ segments.forEach(function collect(segment) {
927
+ if (segment.kind === "step") {
928
+ points.push(...segment.fires);
929
+ } else if (segment.kind === "single") {
930
+ points.push(+segment.value);
931
+ }
932
+ });
933
+ function isWord(hour) {
934
+ return !opts.ampm && (hour === 0 || hour === 12);
935
+ }
936
+ if (!hasRange && points.every(isWord)) {
937
+ return joinList(points.map(function each(hour) {
938
+ return atTime(bareHourPhrase(hour, opts));
939
+ }));
940
+ }
941
+ function wholeHour(hour) {
942
+ return "de la hora " + fromTime(explicitTimePhrase(hour, 0, opts));
943
+ }
944
+ const pieces = [];
945
+ segments.forEach(function place(segment) {
946
+ if (segment.kind === "range") {
947
+ pieces.push(timeRange(
948
+ { hour: +segment.bounds[0], minute: 0 },
949
+ { hour: +segment.bounds[1], minute: 0 },
950
+ opts
951
+ ));
952
+ } else if (segment.kind === "step") {
953
+ segment.fires.forEach(function each(hour) {
954
+ pieces.push(wholeHour(hour));
955
+ });
956
+ } else {
957
+ pieces.push(wholeHour(+segment.value));
958
+ }
959
+ });
960
+ return joinList(pieces);
961
+ }
899
962
  function atTimes(hours, opts) {
900
963
  return hours.map(function each(hour) {
901
964
  return atTime(timePhrase(hour, 0, null, opts));
@@ -1158,7 +1221,7 @@ function weekdayQualifier(ir) {
1158
1221
  if (quartz) {
1159
1222
  return quartz;
1160
1223
  }
1161
- const segments = flattenSteps(fieldSegments(ir, "weekday"));
1224
+ const segments = orderWeekdaysForDisplay(fieldSegments(ir, "weekday"));
1162
1225
  const allSingles = segments.every(function single(segment) {
1163
1226
  return segment.kind === "single";
1164
1227
  });
package/dist/lang/es.js CHANGED
@@ -46,6 +46,26 @@ function arithmeticStep(values) {
46
46
  }
47
47
  return { start: values[0], interval, last: values[values.length - 1] };
48
48
  }
49
+ function weekdayDisplayKey(value) {
50
+ return value === 0 ? 7 : value;
51
+ }
52
+ function orderWeekdaysForDisplay(segments) {
53
+ const flattened = segments.flatMap(function flat(segment) {
54
+ return segment.kind === "step" ? segment.fires.map(function single(value) {
55
+ return { kind: "single", value: "" + value };
56
+ }) : [segment];
57
+ });
58
+ function key(segment) {
59
+ return segment.kind === "range" ? weekdayDisplayKey(+segment.bounds[0]) : weekdayDisplayKey(+segment.value);
60
+ }
61
+ return flattened.map(function index(segment, position) {
62
+ return [segment, position];
63
+ }).sort(function byDisplayKey(a, b) {
64
+ return key(a[0]) - key(b[0]) || a[1] - b[1];
65
+ }).map(function unwrap(pair) {
66
+ return pair[0];
67
+ });
68
+ }
49
69
  function toFieldNumber(token, numberMap) {
50
70
  return isNonNegativeInteger(token) ? +token : numberMap[token.toUpperCase()];
51
71
  }
@@ -198,7 +218,7 @@ function renderComposeSeconds(ir, plan, opts) {
198
218
  }
199
219
  if (plan.rest.kind === "hourRange" && ir.shapes.second === "step" && ir.pattern.weekday !== "*") {
200
220
  const restNode = plan.rest;
201
- const window = hourWindow(restNode, opts);
221
+ const window = hourWindow(boundedWindow(restNode), opts);
202
222
  const dayFrame = weekdayQualifier(ir) + monthScope(ir);
203
223
  const cadence = "cada " + numero(stepSegment(ir.analyses.segments.second).interval, opts) + " segundos del minuto " + ir.pattern.minute;
204
224
  return dayFrame + ", " + window + ", " + cadence;
@@ -411,7 +431,8 @@ function renderHourStep(ir, plan, opts) {
411
431
  return stepHours(stepSegment(ir.analyses.segments.hour), opts) + trailingQualifier(ir, opts);
412
432
  }
413
433
  function boundedWindow(plan) {
414
- return { from: plan.from, last: plan.boundMinute ?? 0, to: plan.to };
434
+ const last = plan.minuteForm === "wildcard" ? plan.boundMinute ?? 0 : 0;
435
+ return { from: plan.from, last, to: plan.to };
415
436
  }
416
437
  function hourWindow(window, opts) {
417
438
  return timeRange(
@@ -455,7 +476,7 @@ function dowArm(ir) {
455
476
  if (quartz) {
456
477
  return quartz;
457
478
  }
458
- const segments = flattenSteps(fieldSegments(ir, "weekday"));
479
+ const segments = orderWeekdaysForDisplay(fieldSegments(ir, "weekday"));
459
480
  const allSingles = segments.every(function single(segment) {
460
481
  return segment.kind === "single";
461
482
  });
@@ -679,7 +700,7 @@ function renderCompactClockTimes(ir, plan, opts) {
679
700
  return leadingQualifier(ir, opts) + hourSegmentTimes(ir, plan.minute, ir.analyses.clockSecond, opts);
680
701
  }
681
702
  const cadence = unevenHourCadence(ir, opts);
682
- const phrase = cadence ? minutesList(ir, opts) + ", " + cadence + trailingQualifier(ir, opts) : minutesList(ir, opts) + ", " + hourSegmentTimes(ir, 0, null, opts) + trailingQualifier(ir, opts);
703
+ const phrase = cadence ? minutesList(ir, opts) + ", " + cadence + trailingQualifier(ir, opts) : minutesList(ir, opts) + ", " + hourContextTimes(ir, opts) + trailingQualifier(ir, opts);
683
704
  return ir.analyses.clockSecond ? secondsLeadClause(ir, opts) + ", " + phrase : phrase;
684
705
  }
685
706
  var renderers = {
@@ -870,6 +891,48 @@ function hourRangeCadence(ir, minute, opts) {
870
891
  }
871
892
  return hourCadenceLead(ir, minute, opts) + ", " + hourSegmentTimes(ir, 0, null, opts) + trailingQualifier(ir, opts);
872
893
  }
894
+ function hourContextTimes(ir, opts) {
895
+ const segments = hourSegments(ir);
896
+ const points = [];
897
+ const hasRange = segments.some(function range(segment) {
898
+ return segment.kind === "range";
899
+ });
900
+ segments.forEach(function collect(segment) {
901
+ if (segment.kind === "step") {
902
+ points.push(...segment.fires);
903
+ } else if (segment.kind === "single") {
904
+ points.push(+segment.value);
905
+ }
906
+ });
907
+ function isWord(hour) {
908
+ return !opts.ampm && (hour === 0 || hour === 12);
909
+ }
910
+ if (!hasRange && points.every(isWord)) {
911
+ return joinList(points.map(function each(hour) {
912
+ return atTime(bareHourPhrase(hour, opts));
913
+ }));
914
+ }
915
+ function wholeHour(hour) {
916
+ return "de la hora " + fromTime(explicitTimePhrase(hour, 0, opts));
917
+ }
918
+ const pieces = [];
919
+ segments.forEach(function place(segment) {
920
+ if (segment.kind === "range") {
921
+ pieces.push(timeRange(
922
+ { hour: +segment.bounds[0], minute: 0 },
923
+ { hour: +segment.bounds[1], minute: 0 },
924
+ opts
925
+ ));
926
+ } else if (segment.kind === "step") {
927
+ segment.fires.forEach(function each(hour) {
928
+ pieces.push(wholeHour(hour));
929
+ });
930
+ } else {
931
+ pieces.push(wholeHour(+segment.value));
932
+ }
933
+ });
934
+ return joinList(pieces);
935
+ }
873
936
  function atTimes(hours, opts) {
874
937
  return hours.map(function each(hour) {
875
938
  return atTime(timePhrase(hour, 0, null, opts));
@@ -1132,7 +1195,7 @@ function weekdayQualifier(ir) {
1132
1195
  if (quartz) {
1133
1196
  return quartz;
1134
1197
  }
1135
- const segments = flattenSteps(fieldSegments(ir, "weekday"));
1198
+ const segments = orderWeekdaysForDisplay(fieldSegments(ir, "weekday"));
1136
1199
  const allSingles = segments.every(function single(segment) {
1137
1200
  return segment.kind === "single";
1138
1201
  });
package/dist/lang/fi.cjs CHANGED
@@ -72,6 +72,26 @@ function arithmeticStep(values) {
72
72
  }
73
73
  return { start: values[0], interval, last: values[values.length - 1] };
74
74
  }
75
+ function weekdayDisplayKey(value) {
76
+ return value === 0 ? 7 : value;
77
+ }
78
+ function orderWeekdaysForDisplay(segments) {
79
+ const flattened = segments.flatMap(function flat(segment) {
80
+ return segment.kind === "step" ? segment.fires.map(function single(value) {
81
+ return { kind: "single", value: "" + value };
82
+ }) : [segment];
83
+ });
84
+ function key(segment) {
85
+ return segment.kind === "range" ? weekdayDisplayKey(+segment.bounds[0]) : weekdayDisplayKey(+segment.value);
86
+ }
87
+ return flattened.map(function index(segment, position) {
88
+ return [segment, position];
89
+ }).sort(function byDisplayKey(a, b) {
90
+ return key(a[0]) - key(b[0]) || a[1] - b[1];
91
+ }).map(function unwrap(pair) {
92
+ return pair[0];
93
+ });
94
+ }
75
95
  function toFieldNumber(token, numberMap) {
76
96
  return isNonNegativeInteger(token) ? +token : numberMap[token.toUpperCase()];
77
97
  }
@@ -965,7 +985,7 @@ function weekdayQualifier(ir) {
965
985
  if (quartz) {
966
986
  return quartz;
967
987
  }
968
- const segments = flattenSteps(ir.analyses.segments.weekday);
988
+ const segments = orderWeekdaysForDisplay(ir.analyses.segments.weekday);
969
989
  return joinList(segments.map(function piece(segment) {
970
990
  if (segment.kind === "range") {
971
991
  return weekdays[weekdayNumber(segment.bounds[0])].ela + " " + weekdays[weekdayNumber(segment.bounds[1])].ill;
package/dist/lang/fi.js CHANGED
@@ -46,6 +46,26 @@ function arithmeticStep(values) {
46
46
  }
47
47
  return { start: values[0], interval, last: values[values.length - 1] };
48
48
  }
49
+ function weekdayDisplayKey(value) {
50
+ return value === 0 ? 7 : value;
51
+ }
52
+ function orderWeekdaysForDisplay(segments) {
53
+ const flattened = segments.flatMap(function flat(segment) {
54
+ return segment.kind === "step" ? segment.fires.map(function single(value) {
55
+ return { kind: "single", value: "" + value };
56
+ }) : [segment];
57
+ });
58
+ function key(segment) {
59
+ return segment.kind === "range" ? weekdayDisplayKey(+segment.bounds[0]) : weekdayDisplayKey(+segment.value);
60
+ }
61
+ return flattened.map(function index(segment, position) {
62
+ return [segment, position];
63
+ }).sort(function byDisplayKey(a, b) {
64
+ return key(a[0]) - key(b[0]) || a[1] - b[1];
65
+ }).map(function unwrap(pair) {
66
+ return pair[0];
67
+ });
68
+ }
49
69
  function toFieldNumber(token, numberMap) {
50
70
  return isNonNegativeInteger(token) ? +token : numberMap[token.toUpperCase()];
51
71
  }
@@ -939,7 +959,7 @@ function weekdayQualifier(ir) {
939
959
  if (quartz) {
940
960
  return quartz;
941
961
  }
942
- const segments = flattenSteps(ir.analyses.segments.weekday);
962
+ const segments = orderWeekdaysForDisplay(ir.analyses.segments.weekday);
943
963
  return joinList(segments.map(function piece(segment) {
944
964
  if (segment.kind === "range") {
945
965
  return weekdays[weekdayNumber(segment.bounds[0])].ela + " " + weekdays[weekdayNumber(segment.bounds[1])].ill;
package/dist/lang/zh.cjs CHANGED
@@ -44,6 +44,26 @@ function arithmeticStep(values) {
44
44
  }
45
45
  return { start: values[0], interval, last: values[values.length - 1] };
46
46
  }
47
+ function weekdayDisplayKey(value) {
48
+ return value === 0 ? 7 : value;
49
+ }
50
+ function orderWeekdaysForDisplay(segments) {
51
+ const flattened = segments.flatMap(function flat(segment) {
52
+ return segment.kind === "step" ? segment.fires.map(function single(value) {
53
+ return { kind: "single", value: "" + value };
54
+ }) : [segment];
55
+ });
56
+ function key(segment) {
57
+ return segment.kind === "range" ? weekdayDisplayKey(+segment.bounds[0]) : weekdayDisplayKey(+segment.value);
58
+ }
59
+ return flattened.map(function index(segment, position) {
60
+ return [segment, position];
61
+ }).sort(function byDisplayKey(a, b) {
62
+ return key(a[0]) - key(b[0]) || a[1] - b[1];
63
+ }).map(function unwrap(pair) {
64
+ return pair[0];
65
+ });
66
+ }
47
67
  function toFieldNumber(token, numberMap) {
48
68
  return isNonNegativeInteger(token) ? +token : numberMap[token.toUpperCase()];
49
69
  }
@@ -384,6 +404,15 @@ function hourCadencePhrase(ir) {
384
404
  anchor: ""
385
405
  });
386
406
  }
407
+ function minuteZeroConfinement(ir, stride, prefix) {
408
+ if (stride.interval === 2 && stride.start === 0) {
409
+ return "\u5728\u5076\u6570\u5C0F\u65F60\u5206" + secondTail(ir);
410
+ }
411
+ if (prefix.indexOf("\u4ECE") !== -1) {
412
+ return prefix + "0\u5206" + secondTail(ir);
413
+ }
414
+ return null;
415
+ }
387
416
  function hourCadence(ir) {
388
417
  const stride = hourStride(ir);
389
418
  if (!stride) {
@@ -400,7 +429,7 @@ function hourCadence(ir) {
400
429
  const minute = +ir.pattern.minute;
401
430
  const subMinute = ir.pattern.second === "*" || ir.shapes.second === "step";
402
431
  if (minute === 0 && subMinute) {
403
- return stride.interval === 2 && stride.start === 0 ? "\u5728\u5076\u6570\u5C0F\u65F60\u5206" + secondTail(ir) : null;
432
+ return minuteZeroConfinement(ir, stride, prefix);
404
433
  }
405
434
  if (minute === 0) {
406
435
  return prefix + "0\u5206" + secondTail(ir);
@@ -634,7 +663,7 @@ function quartzDate(token, monthPrefix) {
634
663
  if (token.startsWith("L-")) {
635
664
  return monthPrefix + "\u6700\u540E\u7B2C" + token.slice(2) + "\u5929";
636
665
  }
637
- return "\u6700\u63A5\u8FD1" + token.slice(0, -1) + "\u65E5\u7684\u5DE5\u4F5C\u65E5";
666
+ return monthPrefix + "\u6700\u63A5\u8FD1" + token.slice(0, -1) + "\u65E5\u7684\u5DE5\u4F5C\u65E5";
638
667
  }
639
668
  function datePhrase(ir) {
640
669
  const month = monthPhrase(ir);
@@ -648,7 +677,11 @@ function datePhrase(ir) {
648
677
  if (ir.shapes.date === "step") {
649
678
  return month + cadence(stepSegment(ir, "date").interval, "\u5929");
650
679
  }
651
- return month ? month + dayList(ir) : "\u6BCF\u6708" + dayList(ir);
680
+ if (!month) {
681
+ return "\u6BCF\u6708" + dayList(ir);
682
+ }
683
+ const monthMulti = ir.shapes.month === "range" || ir.shapes.month === "list";
684
+ return month + (monthMulti ? "\uFF0C" : "") + dayList(ir);
652
685
  }
653
686
  function dateCore(ir, quartzPrefix) {
654
687
  if (ir.shapes.date === "quartz") {
@@ -690,10 +723,8 @@ function weekdayPhrase(ir, orContext, monthPrefix) {
690
723
  return "\u6BCF" + weekdayName(from) + "\u81F3" + weekdayName(to);
691
724
  }
692
725
  const days = [];
693
- segs.forEach(function expand(seg) {
694
- if (seg.kind === "step") {
695
- days.push(...seg.fires);
696
- } else if (seg.kind === "single") {
726
+ orderWeekdaysForDisplay(segs).forEach(function expand(seg) {
727
+ if (seg.kind === "single") {
697
728
  days.push(toFieldNumber(seg.value, weekdayNumbers));
698
729
  }
699
730
  });
package/dist/lang/zh.js CHANGED
@@ -18,6 +18,26 @@ function arithmeticStep(values) {
18
18
  }
19
19
  return { start: values[0], interval, last: values[values.length - 1] };
20
20
  }
21
+ function weekdayDisplayKey(value) {
22
+ return value === 0 ? 7 : value;
23
+ }
24
+ function orderWeekdaysForDisplay(segments) {
25
+ const flattened = segments.flatMap(function flat(segment) {
26
+ return segment.kind === "step" ? segment.fires.map(function single(value) {
27
+ return { kind: "single", value: "" + value };
28
+ }) : [segment];
29
+ });
30
+ function key(segment) {
31
+ return segment.kind === "range" ? weekdayDisplayKey(+segment.bounds[0]) : weekdayDisplayKey(+segment.value);
32
+ }
33
+ return flattened.map(function index(segment, position) {
34
+ return [segment, position];
35
+ }).sort(function byDisplayKey(a, b) {
36
+ return key(a[0]) - key(b[0]) || a[1] - b[1];
37
+ }).map(function unwrap(pair) {
38
+ return pair[0];
39
+ });
40
+ }
21
41
  function toFieldNumber(token, numberMap) {
22
42
  return isNonNegativeInteger(token) ? +token : numberMap[token.toUpperCase()];
23
43
  }
@@ -358,6 +378,15 @@ function hourCadencePhrase(ir) {
358
378
  anchor: ""
359
379
  });
360
380
  }
381
+ function minuteZeroConfinement(ir, stride, prefix) {
382
+ if (stride.interval === 2 && stride.start === 0) {
383
+ return "\u5728\u5076\u6570\u5C0F\u65F60\u5206" + secondTail(ir);
384
+ }
385
+ if (prefix.indexOf("\u4ECE") !== -1) {
386
+ return prefix + "0\u5206" + secondTail(ir);
387
+ }
388
+ return null;
389
+ }
361
390
  function hourCadence(ir) {
362
391
  const stride = hourStride(ir);
363
392
  if (!stride) {
@@ -374,7 +403,7 @@ function hourCadence(ir) {
374
403
  const minute = +ir.pattern.minute;
375
404
  const subMinute = ir.pattern.second === "*" || ir.shapes.second === "step";
376
405
  if (minute === 0 && subMinute) {
377
- return stride.interval === 2 && stride.start === 0 ? "\u5728\u5076\u6570\u5C0F\u65F60\u5206" + secondTail(ir) : null;
406
+ return minuteZeroConfinement(ir, stride, prefix);
378
407
  }
379
408
  if (minute === 0) {
380
409
  return prefix + "0\u5206" + secondTail(ir);
@@ -608,7 +637,7 @@ function quartzDate(token, monthPrefix) {
608
637
  if (token.startsWith("L-")) {
609
638
  return monthPrefix + "\u6700\u540E\u7B2C" + token.slice(2) + "\u5929";
610
639
  }
611
- return "\u6700\u63A5\u8FD1" + token.slice(0, -1) + "\u65E5\u7684\u5DE5\u4F5C\u65E5";
640
+ return monthPrefix + "\u6700\u63A5\u8FD1" + token.slice(0, -1) + "\u65E5\u7684\u5DE5\u4F5C\u65E5";
612
641
  }
613
642
  function datePhrase(ir) {
614
643
  const month = monthPhrase(ir);
@@ -622,7 +651,11 @@ function datePhrase(ir) {
622
651
  if (ir.shapes.date === "step") {
623
652
  return month + cadence(stepSegment(ir, "date").interval, "\u5929");
624
653
  }
625
- return month ? month + dayList(ir) : "\u6BCF\u6708" + dayList(ir);
654
+ if (!month) {
655
+ return "\u6BCF\u6708" + dayList(ir);
656
+ }
657
+ const monthMulti = ir.shapes.month === "range" || ir.shapes.month === "list";
658
+ return month + (monthMulti ? "\uFF0C" : "") + dayList(ir);
626
659
  }
627
660
  function dateCore(ir, quartzPrefix) {
628
661
  if (ir.shapes.date === "quartz") {
@@ -664,10 +697,8 @@ function weekdayPhrase(ir, orContext, monthPrefix) {
664
697
  return "\u6BCF" + weekdayName(from) + "\u81F3" + weekdayName(to);
665
698
  }
666
699
  const days = [];
667
- segs.forEach(function expand(seg) {
668
- if (seg.kind === "step") {
669
- days.push(...seg.fires);
670
- } else if (seg.kind === "single") {
700
+ orderWeekdaysForDisplay(segs).forEach(function expand(seg) {
701
+ if (seg.kind === "single") {
671
702
  days.push(toFieldNumber(seg.value, weekdayNumbers));
672
703
  }
673
704
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cronli5",
3
- "version": "0.1.6",
3
+ "version": "0.2.0",
4
4
  "description": "Cron Like I'm Five: A Cron to English Utility",
5
5
  "repository": {
6
6
  "type": "git",
package/src/core/ir.ts CHANGED
@@ -132,6 +132,11 @@ export interface DialectStyle {
132
132
  sep: string;
133
133
  serialComma: boolean;
134
134
  through: string;
135
+ // Whether a contiguous hour range reads as an up-to-but-not-including
136
+ // window ("from 9 a.m. until 6 p.m.") rather than a "through <last fire>"
137
+ // span. Set only on the default English dialect; other dialects and custom
138
+ // styles keep the "through" span.
139
+ untilWindow?: boolean;
135
140
  }
136
141
 
137
142
  /**
package/src/core/util.ts CHANGED
@@ -1,5 +1,7 @@
1
1
  // Small shared utilities for the core.
2
2
 
3
+ import type {Segment} from './ir.js';
4
+
3
5
  function includes(str: string | number, sub: string): boolean {
4
6
  return ('' + str).indexOf(sub) !== -1;
5
7
  }
@@ -44,6 +46,54 @@ function arithmeticStep(values: number[]):
44
46
  return {start: values[0], interval, last: values[values.length - 1]};
45
47
  }
46
48
 
49
+ // The display sort key for a canonical weekday number: Monday (1) first,
50
+ // Sunday (0) last. The IR keeps Sunday=0 canonical; this is display-only.
51
+ function weekdayDisplayKey(value: number): number {
52
+ return value === 0 ? 7 : value;
53
+ }
54
+
55
+ // A weekday display segment: a single day or a (possibly wrap) range. Steps
56
+ // are flattened away into singles before sorting, so the result is only these
57
+ // two kinds; each renderer turns them into names exactly as it does today.
58
+ type WeekdaySegment =
59
+ | {kind: 'single'; value: string}
60
+ | {kind: 'range'; bounds: [string, string]};
61
+
62
+ // Reorder weekday segments Monday-first (Sunday last) for display, so a weekend
63
+ // list reads "Saturday and Sunday" rather than the canonical Sunday-first
64
+ // "Sunday and Saturday". Display-only: the IR / canonical order is unchanged (a
65
+ // fresh array is returned). A step expands to its fires as singles so the days
66
+ // sort into the list; a range stays one unit and keeps its own bounds order (a
67
+ // wrap range is not reordered into a list), sorting by its opening bound — so a
68
+ // lone range sorts to a one-element list and is unchanged. The sort is stable,
69
+ // so equal opening days keep input order.
70
+ function orderWeekdaysForDisplay(segments: Segment[]): WeekdaySegment[] {
71
+ const flattened: WeekdaySegment[] = segments.flatMap(function flat(segment) {
72
+ return segment.kind === 'step' ?
73
+ segment.fires.map(function single(value): WeekdaySegment {
74
+ return {kind: 'single', value: '' + value};
75
+ }) :
76
+ [segment];
77
+ });
78
+
79
+ function key(segment: WeekdaySegment): number {
80
+ return segment.kind === 'range' ?
81
+ weekdayDisplayKey(+segment.bounds[0]) :
82
+ weekdayDisplayKey(+segment.value);
83
+ }
84
+
85
+ return flattened
86
+ .map(function index(segment, position): [WeekdaySegment, number] {
87
+ return [segment, position];
88
+ })
89
+ .sort(function byDisplayKey(a, b): number {
90
+ return key(a[0]) - key(b[0]) || a[1] - b[1];
91
+ })
92
+ .map(function unwrap(pair): WeekdaySegment {
93
+ return pair[0];
94
+ });
95
+ }
96
+
47
97
  // Resolve a numeric or named field token (e.g. '5' or 'FRI') to its number.
48
98
  function toFieldNumber(
49
99
  token: string,
@@ -54,5 +104,6 @@ function toFieldNumber(
54
104
  return isNonNegativeInteger(token) ? +token : numberMap![token.toUpperCase()];
55
105
  }
56
106
  export {
57
- arithmeticStep, includes, isNonNegativeInteger, toFieldNumber, unique
107
+ arithmeticStep, includes, isNonNegativeInteger, orderWeekdaysForDisplay,
108
+ toFieldNumber, unique
58
109
  };