cronli5 0.1.2 → 0.1.5
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/CHANGELOG.md +89 -0
- package/cli.js +9 -0
- package/cronli5.min.js +2 -2
- package/dist/cronli5.cjs +280 -64
- package/dist/cronli5.js +280 -64
- package/dist/lang/de.cjs +227 -42
- package/dist/lang/de.js +227 -42
- package/dist/lang/en.cjs +216 -50
- package/dist/lang/en.js +216 -50
- package/dist/lang/es.cjs +259 -54
- package/dist/lang/es.js +259 -54
- package/dist/lang/fi.cjs +230 -69
- package/dist/lang/fi.js +230 -69
- package/dist/lang/zh.cjs +190 -19
- package/dist/lang/zh.js +190 -19
- package/package.json +3 -1
- package/src/core/analyze.ts +7 -0
- package/src/core/ir.ts +1 -1
- package/src/core/normalize.ts +94 -4
- package/src/core/util.ts +31 -1
- package/src/lang/de/index.ts +449 -46
- package/src/lang/en/index.ts +433 -63
- package/src/lang/es/index.ts +505 -63
- package/src/lang/fi/index.ts +455 -89
- package/src/lang/zh/index.ts +393 -30
- package/types/core/ir.d.ts +1 -1
- package/types/core/util.d.ts +6 -1
package/dist/lang/de.js
CHANGED
|
@@ -4,6 +4,42 @@ function pad(n) {
|
|
|
4
4
|
return n.length < 2 ? "0" + n : n;
|
|
5
5
|
}
|
|
6
6
|
|
|
7
|
+
// src/core/specs.ts
|
|
8
|
+
var weekdayNumbers = {
|
|
9
|
+
SUN: 0,
|
|
10
|
+
MON: 1,
|
|
11
|
+
TUE: 2,
|
|
12
|
+
WED: 3,
|
|
13
|
+
THU: 4,
|
|
14
|
+
FRI: 5,
|
|
15
|
+
SAT: 6
|
|
16
|
+
};
|
|
17
|
+
var maxClockTimes = 6;
|
|
18
|
+
|
|
19
|
+
// src/core/util.ts
|
|
20
|
+
function isNonNegativeInteger(value) {
|
|
21
|
+
const digits = /^\d+$/;
|
|
22
|
+
return digits.test(value);
|
|
23
|
+
}
|
|
24
|
+
function arithmeticStep(values) {
|
|
25
|
+
if (values.length < 5) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
const interval = values[1] - values[0];
|
|
29
|
+
if (interval < 2) {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
for (let i = 2; i < values.length; i += 1) {
|
|
33
|
+
if (values[i] - values[i - 1] !== interval) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return { start: values[0], interval, last: values[values.length - 1] };
|
|
38
|
+
}
|
|
39
|
+
function toFieldNumber(token, numberMap) {
|
|
40
|
+
return isNonNegativeInteger(token) ? +token : numberMap[token.toUpperCase()];
|
|
41
|
+
}
|
|
42
|
+
|
|
7
43
|
// src/lang/de/dialects.ts
|
|
8
44
|
var months = [
|
|
9
45
|
null,
|
|
@@ -66,6 +102,49 @@ function stepSegment(segments) {
|
|
|
66
102
|
function cleanStep(segment, cycle) {
|
|
67
103
|
return (segment.startToken === "*" || +segment.startToken === 0) && cycle % segment.interval === 0;
|
|
68
104
|
}
|
|
105
|
+
function renderStride(stride) {
|
|
106
|
+
const { interval, start, last, cycle, unit, anchor } = stride;
|
|
107
|
+
const cadence = everyN(interval, unit);
|
|
108
|
+
const tiles = cycle % interval === 0;
|
|
109
|
+
if (start === 0 && tiles) {
|
|
110
|
+
return cadence;
|
|
111
|
+
}
|
|
112
|
+
const tail = anchor ? " " + anchor : "";
|
|
113
|
+
if (start < interval && tiles) {
|
|
114
|
+
return cadence + " ab " + unit.singular + " " + start + tail;
|
|
115
|
+
}
|
|
116
|
+
return cadence + " von " + unit.singular + " " + start + " bis " + last + tail;
|
|
117
|
+
}
|
|
118
|
+
function stepClause(segment, unit, anchor) {
|
|
119
|
+
const start = segment.startToken === "*" ? 0 : +segment.startToken;
|
|
120
|
+
const short = start !== 0 && segment.fires.length <= 3;
|
|
121
|
+
if (segment.startToken.indexOf("-") !== -1 || short) {
|
|
122
|
+
return "in den " + unit.plural + " " + joinList(segment.fires.map(String)) + " " + anchor;
|
|
123
|
+
}
|
|
124
|
+
return renderStride({
|
|
125
|
+
interval: segment.interval,
|
|
126
|
+
start,
|
|
127
|
+
last: segment.fires[segment.fires.length - 1],
|
|
128
|
+
cycle: 60,
|
|
129
|
+
unit,
|
|
130
|
+
anchor
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
function singleValues(segments) {
|
|
134
|
+
const values = [];
|
|
135
|
+
for (const segment of segments) {
|
|
136
|
+
if (segment.kind !== "single") {
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
values.push(+segment.value);
|
|
140
|
+
}
|
|
141
|
+
return values;
|
|
142
|
+
}
|
|
143
|
+
function strideFromSegments(segments, unit, anchor) {
|
|
144
|
+
const values = singleValues(segments);
|
|
145
|
+
const step = values && arithmeticStep(values);
|
|
146
|
+
return step ? renderStride({ ...step, cycle: 60, unit, anchor }) : null;
|
|
147
|
+
}
|
|
69
148
|
var weekdayNames = [
|
|
70
149
|
"sonntags",
|
|
71
150
|
"montags",
|
|
@@ -75,15 +154,6 @@ var weekdayNames = [
|
|
|
75
154
|
"freitags",
|
|
76
155
|
"samstags"
|
|
77
156
|
];
|
|
78
|
-
var weekdayTokens = {
|
|
79
|
-
SUN: 0,
|
|
80
|
-
MON: 1,
|
|
81
|
-
TUE: 2,
|
|
82
|
-
WED: 3,
|
|
83
|
-
THU: 4,
|
|
84
|
-
FRI: 5,
|
|
85
|
-
SAT: 6
|
|
86
|
-
};
|
|
87
157
|
function fieldSegments(ir, field) {
|
|
88
158
|
return ir.analyses.segments[field];
|
|
89
159
|
}
|
|
@@ -104,10 +174,7 @@ function joinList(items) {
|
|
|
104
174
|
return items.slice(0, -1).join(", ") + " und " + items[items.length - 1];
|
|
105
175
|
}
|
|
106
176
|
function weekdayName(token) {
|
|
107
|
-
|
|
108
|
-
return weekdayNames[0];
|
|
109
|
-
}
|
|
110
|
-
return weekdayNames[token] || weekdayNames[weekdayTokens[token]];
|
|
177
|
+
return weekdayNames[+token];
|
|
111
178
|
}
|
|
112
179
|
function weekdayRange(bounds) {
|
|
113
180
|
return weekdayName(bounds[0]) + " bis " + weekdayName(bounds[1]);
|
|
@@ -144,11 +211,15 @@ function everyNthHour(segment) {
|
|
|
144
211
|
const start = segment.startToken === "*" ? 0 : +segment.startToken;
|
|
145
212
|
return start === 0 ? base : base + " ab " + start + " Uhr";
|
|
146
213
|
}
|
|
147
|
-
function
|
|
148
|
-
if (
|
|
149
|
-
return
|
|
214
|
+
function confinedHourStride(segment) {
|
|
215
|
+
if (segment.startToken.indexOf("-") !== -1) {
|
|
216
|
+
return false;
|
|
150
217
|
}
|
|
151
|
-
|
|
218
|
+
const start = segment.startToken === "*" ? 0 : +segment.startToken;
|
|
219
|
+
return 24 % segment.interval === 0 && start < segment.interval;
|
|
220
|
+
}
|
|
221
|
+
function weekdayNoun(token) {
|
|
222
|
+
return weekdayNouns[toFieldNumber(token, weekdayNumbers)];
|
|
152
223
|
}
|
|
153
224
|
function quartzWeekday(field) {
|
|
154
225
|
if (field.indexOf("#") !== -1) {
|
|
@@ -172,22 +243,8 @@ function quartzDate(field) {
|
|
|
172
243
|
}
|
|
173
244
|
return null;
|
|
174
245
|
}
|
|
175
|
-
var monthTokens = {
|
|
176
|
-
JAN: 1,
|
|
177
|
-
FEB: 2,
|
|
178
|
-
MAR: 3,
|
|
179
|
-
APR: 4,
|
|
180
|
-
MAY: 5,
|
|
181
|
-
JUN: 6,
|
|
182
|
-
JUL: 7,
|
|
183
|
-
AUG: 8,
|
|
184
|
-
SEP: 9,
|
|
185
|
-
OCT: 10,
|
|
186
|
-
NOV: 11,
|
|
187
|
-
DEC: 12
|
|
188
|
-
};
|
|
189
246
|
function monthName(token, months2) {
|
|
190
|
-
return months2[token]
|
|
247
|
+
return months2[+token];
|
|
191
248
|
}
|
|
192
249
|
function monthRange(bounds, months2) {
|
|
193
250
|
return "von " + monthName(bounds[0], months2) + " bis " + monthName(bounds[1], months2);
|
|
@@ -264,14 +321,17 @@ function countedPhrase(ir, field, singular, plural) {
|
|
|
264
321
|
return "in den " + plural + " " + joinList(fieldValues(ir, field));
|
|
265
322
|
}
|
|
266
323
|
function secondsLead(ir) {
|
|
324
|
+
return secondsClause(ir, "jeder Minute");
|
|
325
|
+
}
|
|
326
|
+
function secondsClause(ir, anchor) {
|
|
267
327
|
if (ir.pattern.second === "*") {
|
|
268
328
|
return "jede Sekunde";
|
|
269
329
|
}
|
|
270
330
|
const segments = ir.analyses.segments.second;
|
|
271
|
-
if (ir.shapes.second === "step"
|
|
272
|
-
return
|
|
331
|
+
if (ir.shapes.second === "step") {
|
|
332
|
+
return stepClause(stepSegment(segments), UNITS.second, anchor);
|
|
273
333
|
}
|
|
274
|
-
return countedPhrase(ir, "second", "Sekunde", "Sekunden") + "
|
|
334
|
+
return strideFromSegments(segments, UNITS.second, anchor) ?? countedPhrase(ir, "second", "Sekunde", "Sekunden") + " " + anchor;
|
|
275
335
|
}
|
|
276
336
|
function spanTime(hour, minute, sep) {
|
|
277
337
|
return hour + sep + pad(minute);
|
|
@@ -340,8 +400,15 @@ function renderEveryHour() {
|
|
|
340
400
|
function renderSeconds(ir) {
|
|
341
401
|
return secondsLead(ir);
|
|
342
402
|
}
|
|
403
|
+
function minutePastClause(ir) {
|
|
404
|
+
return strideFromSegments(
|
|
405
|
+
fieldSegments(ir, "minute"),
|
|
406
|
+
UNITS.minute,
|
|
407
|
+
"jeder Stunde"
|
|
408
|
+
) ?? countedPhrase(ir, "minute", "Minute", "Minuten") + " jeder Stunde";
|
|
409
|
+
}
|
|
343
410
|
function renderMinutePast(ir) {
|
|
344
|
-
return
|
|
411
|
+
return minutePastClause(ir);
|
|
345
412
|
}
|
|
346
413
|
function renderSecondsWithinMinute(ir, plan) {
|
|
347
414
|
if (plan.singleSecond) {
|
|
@@ -349,42 +416,84 @@ function renderSecondsWithinMinute(ir, plan) {
|
|
|
349
416
|
}
|
|
350
417
|
return secondsLead(ir) + ", in Minute " + ir.pattern.minute + " jeder Stunde";
|
|
351
418
|
}
|
|
419
|
+
function wholeHour(hour) {
|
|
420
|
+
if (hour === 0) {
|
|
421
|
+
return "der Mitternachtsstunde";
|
|
422
|
+
}
|
|
423
|
+
if (hour === 12) {
|
|
424
|
+
return "der Mittagsstunde";
|
|
425
|
+
}
|
|
426
|
+
return "der " + hour + "-Uhr-Stunde";
|
|
427
|
+
}
|
|
352
428
|
function renderMinuteSpanInHour(ir, plan, opts) {
|
|
429
|
+
if (ir.pattern.minute === "*") {
|
|
430
|
+
return "jede Minute " + wholeHour(plan.hour);
|
|
431
|
+
}
|
|
353
432
|
const sep = opts.style.sep;
|
|
354
433
|
return "jede Minute von " + spanTime(plan.hour, plan.span[0], sep) + " bis " + spanTime(plan.hour, plan.span[1], sep) + " Uhr";
|
|
355
434
|
}
|
|
356
435
|
function renderComposeSeconds(ir, plan, opts) {
|
|
436
|
+
if ((plan.rest.kind === "clockTimes" || plan.rest.kind === "compactClockTimes") && ir.shapes.minute === "single") {
|
|
437
|
+
const cadence = hourCadence(ir, +ir.pattern.minute);
|
|
438
|
+
if (cadence !== null) {
|
|
439
|
+
return cadence;
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
if (composeMinuteZero(ir, plan)) {
|
|
443
|
+
return secondsLead(ir) + " " + clockMinuteGenitive(plan.rest.times, opts.style.sep);
|
|
444
|
+
}
|
|
445
|
+
if (plan.rest.kind === "minuteFrequency" && ir.shapes.second === "wildcard" && ir.shapes.hour === "wildcard") {
|
|
446
|
+
const minuteStep = stepSegment(ir.analyses.segments.minute);
|
|
447
|
+
if (minuteStep.startToken === "*" && minuteStep.interval === 2) {
|
|
448
|
+
return secondsLead(ir) + " jeder zweiten Minute";
|
|
449
|
+
}
|
|
450
|
+
}
|
|
357
451
|
return secondsLead(ir) + ", " + render(ir, plan.rest, opts);
|
|
358
452
|
}
|
|
453
|
+
function composeMinuteZero(ir, plan) {
|
|
454
|
+
return plan.rest.kind === "clockTimes" && plan.rest.times.every((time) => +time.minute === 0);
|
|
455
|
+
}
|
|
456
|
+
function clockMinuteGenitive(times, sep) {
|
|
457
|
+
const clocks = times.map(function clock(time) {
|
|
458
|
+
return time.hour + sep + pad(time.minute);
|
|
459
|
+
});
|
|
460
|
+
return clocks.length === 1 ? "der Minute " + clocks[0] : "der Minuten " + joinList(clocks);
|
|
461
|
+
}
|
|
359
462
|
function renderMinutesAcrossHours(ir, plan, opts) {
|
|
360
463
|
const sep = opts.style.sep;
|
|
361
464
|
if (plan.form === "wildcard") {
|
|
362
465
|
return "jede Minute " + duringHours(ir, plan.times, sep);
|
|
363
466
|
}
|
|
364
467
|
const hours = plan.times.kind === "fires" ? atHours(plan.times.fires) : joinList(hourSegmentParts(ir, 0, 0, sep));
|
|
365
|
-
return countedPhrase(ir, "minute", "Minute", "Minuten") + ", " + hours;
|
|
468
|
+
return (strideFromSegments(fieldSegments(ir, "minute"), UNITS.minute, "") ?? countedPhrase(ir, "minute", "Minute", "Minuten")) + ", " + hours;
|
|
366
469
|
}
|
|
367
470
|
function renderMinuteSpanAcrossHourStep(ir, plan) {
|
|
368
471
|
if (plan.form === "wildcard") {
|
|
369
472
|
return "jede Minute " + everyNthHour(stepSegment(ir.analyses.segments.hour));
|
|
370
473
|
}
|
|
371
|
-
|
|
474
|
+
const segment = stepSegment(ir.analyses.segments.hour);
|
|
475
|
+
const hours = confinedHourStride(segment) ? everyNthHour(segment) : atHours(segment.fires);
|
|
476
|
+
return (strideFromSegments(fieldSegments(ir, "minute"), UNITS.minute, "") ?? countedPhrase(ir, "minute", "Minute", "Minuten")) + ", " + hours;
|
|
372
477
|
}
|
|
373
478
|
function renderCompactClockTimes(ir, plan, opts) {
|
|
374
479
|
const sep = opts.style.sep;
|
|
375
480
|
if (plan.fold) {
|
|
481
|
+
const cadence = hourCadence(ir, plan.minute);
|
|
482
|
+
if (cadence !== null) {
|
|
483
|
+
return cadence;
|
|
484
|
+
}
|
|
376
485
|
const hourly = fieldSegments(ir, "hour").some((segment) => segment.kind === "range");
|
|
377
486
|
return (hourly ? "st\xFCndlich " : "t\xE4glich ") + joinList(hourSegmentParts(ir, plan.minute, ir.analyses.clockSecond, sep));
|
|
378
487
|
}
|
|
379
488
|
const hours = fieldSegments(ir, "hour").some((segment) => segment.kind === "range") ? joinList(hourSegmentParts(ir, 0, 0, sep)) : atHours(hourFires(ir));
|
|
380
489
|
const lead = ir.analyses.clockSecond ? countedPhrase(ir, "second", "Sekunde", "Sekunden") + ", " : "";
|
|
381
|
-
return lead + countedPhrase(ir, "minute", "Minute", "Minuten") + ", " + hours;
|
|
490
|
+
return lead + (strideFromSegments(fieldSegments(ir, "minute"), UNITS.minute, "") ?? countedPhrase(ir, "minute", "Minute", "Minuten")) + ", " + hours;
|
|
382
491
|
}
|
|
383
492
|
function renderMinuteFrequency(ir, plan, opts) {
|
|
384
493
|
const segment = stepSegment(ir.analyses.segments.minute);
|
|
385
494
|
const sep = opts.style.sep;
|
|
386
495
|
const clean = cleanStep(segment, 60);
|
|
387
|
-
const base =
|
|
496
|
+
const base = stepClause(segment, UNITS.minute, "jeder Stunde");
|
|
388
497
|
if (plan.hours.kind === "window") {
|
|
389
498
|
const window = hourWindow(
|
|
390
499
|
plan.hours.from,
|
|
@@ -406,6 +515,67 @@ function hourStepPhrase(ir) {
|
|
|
406
515
|
const segment = stepSegment(ir.analyses.segments.hour);
|
|
407
516
|
return cleanStep(segment, 24) ? everyN(segment.interval, UNITS.hour) : atHours(segment.fires);
|
|
408
517
|
}
|
|
518
|
+
function hourStrideCadence(stride) {
|
|
519
|
+
const { start, interval, last } = stride;
|
|
520
|
+
const cadence = everyN(interval, UNITS.hour);
|
|
521
|
+
const tiles = 24 % interval === 0;
|
|
522
|
+
if (start === 0 && tiles) {
|
|
523
|
+
return cadence;
|
|
524
|
+
}
|
|
525
|
+
if (start < interval && tiles) {
|
|
526
|
+
return cadence + " ab " + start + " Uhr";
|
|
527
|
+
}
|
|
528
|
+
return cadence + " von " + start + " bis " + last + " Uhr";
|
|
529
|
+
}
|
|
530
|
+
function hourStride(ir) {
|
|
531
|
+
const segments = fieldSegments(ir, "hour");
|
|
532
|
+
if (!segments) {
|
|
533
|
+
return null;
|
|
534
|
+
}
|
|
535
|
+
if (segments.length === 1 && segments[0].kind === "step") {
|
|
536
|
+
const segment = segments[0];
|
|
537
|
+
const start = segment.startToken === "*" ? 0 : +segment.startToken.split("-")[0];
|
|
538
|
+
return { interval: segment.interval, last: segment.fires[segment.fires.length - 1], start };
|
|
539
|
+
}
|
|
540
|
+
const values = singleValues(segments);
|
|
541
|
+
const step = values && arithmeticStep(values);
|
|
542
|
+
return step || null;
|
|
543
|
+
}
|
|
544
|
+
function subMinuteSecond(ir) {
|
|
545
|
+
return ir.pattern.second === "*" || ir.shapes.second === "step";
|
|
546
|
+
}
|
|
547
|
+
function hourCadenceLead(ir, minute) {
|
|
548
|
+
if (minute === 0) {
|
|
549
|
+
if (subMinuteSecond(ir)) {
|
|
550
|
+
return secondsClause(ir, "jeder Minute") + " f\xFCr eine Minute";
|
|
551
|
+
}
|
|
552
|
+
return secondsClause(ir, "jeder Stunde");
|
|
553
|
+
}
|
|
554
|
+
const minutePhrase = "in Minute " + minute;
|
|
555
|
+
if (ir.pattern.second === "0") {
|
|
556
|
+
return minutePhrase;
|
|
557
|
+
}
|
|
558
|
+
return secondsClause(ir, "jeder Minute") + ", " + minutePhrase;
|
|
559
|
+
}
|
|
560
|
+
function hourCadence(ir, minute) {
|
|
561
|
+
const stride = hourStride(ir);
|
|
562
|
+
if (!stride) {
|
|
563
|
+
return null;
|
|
564
|
+
}
|
|
565
|
+
const fires = (stride.last - stride.start) / stride.interval + 1;
|
|
566
|
+
if (ir.pattern.second === "0" && fires <= maxClockTimes) {
|
|
567
|
+
return null;
|
|
568
|
+
}
|
|
569
|
+
const segment = fieldSegments(ir, "hour")[0];
|
|
570
|
+
const confined = minute === 0 && subMinuteSecond(ir) && fieldSegments(ir, "hour").length === 1 && segment.kind === "step" && confinedHourStride(segment);
|
|
571
|
+
if (confined) {
|
|
572
|
+
return secondsClause(ir, "jeder Minute") + " f\xFCr eine Minute " + everyNthHour(segment);
|
|
573
|
+
}
|
|
574
|
+
return hourCadenceLead(ir, minute) + ", " + hourStrideCadence(stride);
|
|
575
|
+
}
|
|
576
|
+
function hourCadenceApplies(ir) {
|
|
577
|
+
return ir.shapes.minute === "single" && hourCadence(ir, +ir.pattern.minute) !== null;
|
|
578
|
+
}
|
|
409
579
|
function renderHourRange(ir, plan, opts) {
|
|
410
580
|
const window = hourWindow(
|
|
411
581
|
plan.from,
|
|
@@ -422,6 +592,12 @@ function renderHourRange(ir, plan, opts) {
|
|
|
422
592
|
return countedPhrase(ir, "minute", "Minute", "Minuten") + " jeder Stunde, " + window;
|
|
423
593
|
}
|
|
424
594
|
function renderClockTimes(ir, plan, opts) {
|
|
595
|
+
if (ir.shapes.minute === "single") {
|
|
596
|
+
const cadence = hourCadence(ir, +ir.pattern.minute);
|
|
597
|
+
if (cadence !== null) {
|
|
598
|
+
return cadence;
|
|
599
|
+
}
|
|
600
|
+
}
|
|
425
601
|
return "um " + timesPhrase(plan.times, opts.style.sep);
|
|
426
602
|
}
|
|
427
603
|
var renderers = {
|
|
@@ -464,8 +640,17 @@ function qualifier(ir, months2) {
|
|
|
464
640
|
return "";
|
|
465
641
|
}
|
|
466
642
|
var LEADING_PLANS = /* @__PURE__ */ new Set(["clockTimes"]);
|
|
643
|
+
function leadsQualifier(ir) {
|
|
644
|
+
return LEADING_PLANS.has(ir.plan.kind) || isComposeMinuteZero(ir);
|
|
645
|
+
}
|
|
646
|
+
function isComposeMinuteZero(ir) {
|
|
647
|
+
return ir.plan.kind === "composeSeconds" && composeMinuteZero(ir, ir.plan);
|
|
648
|
+
}
|
|
467
649
|
function needsDailyFrame(ir) {
|
|
468
|
-
if (ir
|
|
650
|
+
if (hourCadenceApplies(ir)) {
|
|
651
|
+
return false;
|
|
652
|
+
}
|
|
653
|
+
if (ir.plan.kind === "clockTimes" || isComposeMinuteZero(ir)) {
|
|
469
654
|
return true;
|
|
470
655
|
}
|
|
471
656
|
return ir.plan.kind === "hourStep" && !cleanStep(stepSegment(ir.analyses.segments.hour), 24);
|
|
@@ -508,7 +693,7 @@ function describe(ir, opts) {
|
|
|
508
693
|
const qual = qualifier(ir, opts.style.months);
|
|
509
694
|
let base = core;
|
|
510
695
|
if (qual) {
|
|
511
|
-
base =
|
|
696
|
+
base = leadsQualifier(ir) ? qual + " " + core : core + " " + qual;
|
|
512
697
|
} else if (needsDailyFrame(ir)) {
|
|
513
698
|
base = "t\xE4glich " + core;
|
|
514
699
|
}
|