cronli5 0.1.0 → 0.1.2

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.
@@ -62,7 +62,6 @@ interface UnitForms {
62
62
  anchor: string;
63
63
  ela: string;
64
64
  gen: string;
65
- restart: string;
66
65
  }
67
66
 
68
67
  // Genitive numerals for the "N <unit>in välein" construction, spelled
@@ -179,15 +178,13 @@ const units: {minute: UnitForms; second: UnitForms} = {
179
178
  mark: 'joka tunti',
180
179
  anchor: 'jokaisen tunnin',
181
180
  ela: 'minuutista',
182
- gen: 'minuutin',
183
- restart: 'tasatunnista alkaen'
181
+ gen: 'minuutin'
184
182
  },
185
183
  second: {
186
184
  mark: 'joka minuutti',
187
185
  anchor: 'jokaisen minuutin',
188
186
  ela: 'sekunnista',
189
- gen: 'sekunnin',
190
- restart: 'joka minuutti'
187
+ gen: 'sekunnin'
191
188
  }
192
189
  };
193
190
 
@@ -686,7 +683,7 @@ function renderHourRange(
686
683
  plan: Extract<PlanNode, {kind: 'hourRange'}>,
687
684
  opts: NormalizedOptions
688
685
  ): string {
689
- const window = hourWindow(plan, opts);
686
+ const window = hourWindow(boundedWindow(plan), opts);
690
687
 
691
688
  if (plan.minuteForm === 'wildcard') {
692
689
  return 'joka minuutti ' + window + trailingQualifier(ir, opts);
@@ -726,6 +723,16 @@ function renderHourStep(
726
723
  trailingQualifier(ir, opts);
727
724
  }
728
725
 
726
+ // The hour-range plan as a window whose closing minute honors `boundMinute`:
727
+ // a bare close (`null`) lands on the top of the final hour (minute 0), so
728
+ // `kloRange` renders the bare "klo 9–17" form, with the minutes stated
729
+ // separately; a single fire or wildcard names an exact closing minute.
730
+ function boundedWindow(
731
+ plan: Extract<PlanNode, {kind: 'hourRange'}>
732
+ ): HourWindow {
733
+ return {from: plan.from, last: plan.boundMinute ?? 0, to: plan.to};
734
+ }
735
+
729
736
  // "klo 9.00–17.45": a window from the top of the first hour to the
730
737
  // minute field's last fire within the final hour.
731
738
  function hourWindow(window: HourWindow, opts: NormalizedOptions): string {
@@ -848,15 +855,9 @@ function stepCycle60(
848
855
  ' alkaen';
849
856
  }
850
857
 
851
- if (60 % interval === 0) {
852
- return cadence;
853
- }
854
-
855
- if (segment.fires.length <= 2) {
856
- return atMarks(joinList(wordList(segment.fires)), unit, true);
857
- }
858
-
859
- return cadence + ' ' + unit.restart;
858
+ // A clean stride from the top of the cycle is the bare cadence. (An uneven
859
+ // stride is rewritten to its fires upstream and never reaches here.)
860
+ return cadence;
860
861
  }
861
862
 
862
863
  // "kahden tunnin välein", "klo 0, 10 ja 20", or "viiden tunnin välein
@@ -870,7 +871,9 @@ function stepHours(segment: StepSegment, opts: NormalizedOptions): string {
870
871
  const interval = segment.interval;
871
872
  const cadence = genitive(interval, opts) + ' tunnin välein';
872
873
 
873
- if (start === 0 && 24 % interval === 0) {
874
+ // A clean stride from midnight is the bare cadence. (An uneven stride is
875
+ // rewritten to its fires upstream and never reaches here.)
876
+ if (start === 0) {
874
877
  return cadence;
875
878
  }
876
879
 
@@ -878,10 +881,6 @@ function stepHours(segment: StepSegment, opts: NormalizedOptions): string {
878
881
  return kloList(segment.fires, opts);
879
882
  }
880
883
 
881
- if (start === 0) {
882
- return cadence + ' keskiyöstä alkaen';
883
- }
884
-
885
884
  return cadence + ' klo ' + hourElatives[start] + ' alkaen';
886
885
  }
887
886
 
@@ -217,7 +217,12 @@ function hourFrame(ir: IR): string {
217
217
 
218
218
  // A repeating minute step, optionally confined to active hours.
219
219
  function renderMinuteFrequency(ir: IR, plan: PlanNode): string {
220
- const base = cadence(stepSegment(ir, 'minute').interval, UNITS.minute);
220
+ const minuteStep = stepSegment(ir, 'minute');
221
+ // A "每N分钟" cadence is only faithful from the top of the hour; an offset
222
+ // step (5/6 fires at :05,:11,…) enumerates its fires instead.
223
+ const base = minuteStep.startToken === '*' ?
224
+ cadence(minuteStep.interval, UNITS.minute) :
225
+ renderMinutePast(ir);
221
226
  const {hours} = plan as Extract<PlanNode, {kind: 'minuteFrequency'}>;
222
227
 
223
228
  if (hours.kind === 'step') {
@@ -323,8 +328,9 @@ function renderHourRange(ir: IR, plan: PlanNode): string {
323
328
  range.last + '分之间,每分钟';
324
329
  }
325
330
 
326
- // A stepped hour field: "每2小时", or "从凌晨0点起,每5小时" when the step does not
327
- // divide 24 (the cadence wraps), or its discrete fires as clock words.
331
+ // A stepped hour field: "每2小时", or its two fires as clock words when the
332
+ // stride fires only twice. An uneven stride (one that does not divide 24) is
333
+ // rewritten to its fire list upstream and never reaches here.
328
334
  function renderHourStep(ir: IR): string {
329
335
  const segment = stepSegment(ir, 'hour');
330
336
 
@@ -332,16 +338,11 @@ function renderHourStep(ir: IR): string {
332
338
  return hourList(ir);
333
339
  }
334
340
 
335
- // A step that fires only twice reads as two clock times ("凌晨0点和13点").
341
+ // A step that fires only twice reads as two clock times ("凌晨0点和正午").
336
342
  if (segment.fires.length <= 2) {
337
343
  return joinAnd(segment.fires.map(hourWord));
338
344
  }
339
345
 
340
- if (24 % segment.interval !== 0) {
341
- return '从' + hourWord(segment.fires[0]) + '起,' +
342
- cadence(segment.interval, UNITS.hour);
343
- }
344
-
345
346
  return cadence(segment.interval, UNITS.hour);
346
347
  }
347
348
 
@@ -423,19 +424,17 @@ function composeSecondsOnHour(ir: IR, plan: PlanNode, opts: Opts): string {
423
424
  const {rest} = plan as Extract<PlanNode, {kind: 'composeSeconds'}>;
424
425
  const restText = render(ir, rest, opts);
425
426
 
426
- if (rest.kind === 'everyHour') {
427
- return sec + ',每小时';
428
- }
429
-
430
- if (rest.kind === 'hourStep') {
431
- return sec + ',' + restText;
432
- }
433
-
434
427
  if ((rest.kind === 'clockTimes' || rest.kind === 'compactClockTimes') &&
435
428
  isDaily(ir)) {
436
429
  return '每天' + restText + sec;
437
430
  }
438
431
 
432
+ // A stated minute (e.g. minute 0 under a sub-minute second) takes the same
433
+ // "," connector the listed-minute path uses.
434
+ if (rest.kind === 'singleMinute') {
435
+ return restText + ',' + sec;
436
+ }
437
+
439
438
  return restText + sec;
440
439
  }
441
440
 
@@ -460,10 +459,12 @@ function composeSecondsCadence(ir: IR): string {
460
459
  }
461
460
 
462
461
  // Listed/ranged minute: "每小时<minutes>,每秒", confined by any hour frame.
462
+ // A minute list or range under an hour range closes on the bare hour frame
463
+ // ("在9点至17点之间"), stating its minutes separately, rather than gluing its
464
+ // last fire onto the window end ("…17点30分") and reading as a continuous span.
463
465
  function composeSecondsListed(ir: IR): string {
464
466
  const sec = secondClause(ir);
465
467
  const minutes = '每小时' + valueList(fieldSegments(ir, 'minute'), '分');
466
- const minuteSegs = fieldSegments(ir, 'minute');
467
468
 
468
469
  if (ir.shapes.hour === 'wildcard') {
469
470
  return minutes + ',' + sec;
@@ -474,16 +475,6 @@ function composeSecondsListed(ir: IR): string {
474
475
  minutes + ',' + sec;
475
476
  }
476
477
 
477
- // A minute range under an hour range folds into the window end ("…17点30分").
478
- if (ir.shapes.hour === 'range' && minuteSegs.length === 1 &&
479
- minuteSegs[0].kind === 'range') {
480
- const [from, to] = (fieldSegments(ir, 'hour')[0] as
481
- Extract<Segment, {kind: 'range'}>).bounds;
482
-
483
- return '在' + hourWord(+from) + '至' + to + '点' +
484
- minuteSegs[0].bounds[1] + '分之间,' + sec;
485
- }
486
-
487
478
  return hourFrame(ir) + minutes + ',' + sec;
488
479
  }
489
480
 
@@ -101,6 +101,7 @@ export type PlanNode = {
101
101
  from: number;
102
102
  to: number;
103
103
  last: number;
104
+ boundMinute: number | null;
104
105
  minuteForm: 'lead' | 'wildcard' | 'range';
105
106
  } | {
106
107
  kind: 'hourStep';