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.cjs
CHANGED
|
@@ -30,6 +30,42 @@ function pad(n) {
|
|
|
30
30
|
return n.length < 2 ? "0" + n : n;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
// src/core/specs.ts
|
|
34
|
+
var weekdayNumbers = {
|
|
35
|
+
SUN: 0,
|
|
36
|
+
MON: 1,
|
|
37
|
+
TUE: 2,
|
|
38
|
+
WED: 3,
|
|
39
|
+
THU: 4,
|
|
40
|
+
FRI: 5,
|
|
41
|
+
SAT: 6
|
|
42
|
+
};
|
|
43
|
+
var maxClockTimes = 6;
|
|
44
|
+
|
|
45
|
+
// src/core/util.ts
|
|
46
|
+
function isNonNegativeInteger(value) {
|
|
47
|
+
const digits = /^\d+$/;
|
|
48
|
+
return digits.test(value);
|
|
49
|
+
}
|
|
50
|
+
function arithmeticStep(values) {
|
|
51
|
+
if (values.length < 5) {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
const interval = values[1] - values[0];
|
|
55
|
+
if (interval < 2) {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
for (let i = 2; i < values.length; i += 1) {
|
|
59
|
+
if (values[i] - values[i - 1] !== interval) {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return { start: values[0], interval, last: values[values.length - 1] };
|
|
64
|
+
}
|
|
65
|
+
function toFieldNumber(token, numberMap) {
|
|
66
|
+
return isNonNegativeInteger(token) ? +token : numberMap[token.toUpperCase()];
|
|
67
|
+
}
|
|
68
|
+
|
|
33
69
|
// src/lang/de/dialects.ts
|
|
34
70
|
var months = [
|
|
35
71
|
null,
|
|
@@ -92,6 +128,49 @@ function stepSegment(segments) {
|
|
|
92
128
|
function cleanStep(segment, cycle) {
|
|
93
129
|
return (segment.startToken === "*" || +segment.startToken === 0) && cycle % segment.interval === 0;
|
|
94
130
|
}
|
|
131
|
+
function renderStride(stride) {
|
|
132
|
+
const { interval, start, last, cycle, unit, anchor } = stride;
|
|
133
|
+
const cadence = everyN(interval, unit);
|
|
134
|
+
const tiles = cycle % interval === 0;
|
|
135
|
+
if (start === 0 && tiles) {
|
|
136
|
+
return cadence;
|
|
137
|
+
}
|
|
138
|
+
const tail = anchor ? " " + anchor : "";
|
|
139
|
+
if (start < interval && tiles) {
|
|
140
|
+
return cadence + " ab " + unit.singular + " " + start + tail;
|
|
141
|
+
}
|
|
142
|
+
return cadence + " von " + unit.singular + " " + start + " bis " + last + tail;
|
|
143
|
+
}
|
|
144
|
+
function stepClause(segment, unit, anchor) {
|
|
145
|
+
const start = segment.startToken === "*" ? 0 : +segment.startToken;
|
|
146
|
+
const short = start !== 0 && segment.fires.length <= 3;
|
|
147
|
+
if (segment.startToken.indexOf("-") !== -1 || short) {
|
|
148
|
+
return "in den " + unit.plural + " " + joinList(segment.fires.map(String)) + " " + anchor;
|
|
149
|
+
}
|
|
150
|
+
return renderStride({
|
|
151
|
+
interval: segment.interval,
|
|
152
|
+
start,
|
|
153
|
+
last: segment.fires[segment.fires.length - 1],
|
|
154
|
+
cycle: 60,
|
|
155
|
+
unit,
|
|
156
|
+
anchor
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
function singleValues(segments) {
|
|
160
|
+
const values = [];
|
|
161
|
+
for (const segment of segments) {
|
|
162
|
+
if (segment.kind !== "single") {
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
values.push(+segment.value);
|
|
166
|
+
}
|
|
167
|
+
return values;
|
|
168
|
+
}
|
|
169
|
+
function strideFromSegments(segments, unit, anchor) {
|
|
170
|
+
const values = singleValues(segments);
|
|
171
|
+
const step = values && arithmeticStep(values);
|
|
172
|
+
return step ? renderStride({ ...step, cycle: 60, unit, anchor }) : null;
|
|
173
|
+
}
|
|
95
174
|
var weekdayNames = [
|
|
96
175
|
"sonntags",
|
|
97
176
|
"montags",
|
|
@@ -101,15 +180,6 @@ var weekdayNames = [
|
|
|
101
180
|
"freitags",
|
|
102
181
|
"samstags"
|
|
103
182
|
];
|
|
104
|
-
var weekdayTokens = {
|
|
105
|
-
SUN: 0,
|
|
106
|
-
MON: 1,
|
|
107
|
-
TUE: 2,
|
|
108
|
-
WED: 3,
|
|
109
|
-
THU: 4,
|
|
110
|
-
FRI: 5,
|
|
111
|
-
SAT: 6
|
|
112
|
-
};
|
|
113
183
|
function fieldSegments(ir, field) {
|
|
114
184
|
return ir.analyses.segments[field];
|
|
115
185
|
}
|
|
@@ -130,10 +200,7 @@ function joinList(items) {
|
|
|
130
200
|
return items.slice(0, -1).join(", ") + " und " + items[items.length - 1];
|
|
131
201
|
}
|
|
132
202
|
function weekdayName(token) {
|
|
133
|
-
|
|
134
|
-
return weekdayNames[0];
|
|
135
|
-
}
|
|
136
|
-
return weekdayNames[token] || weekdayNames[weekdayTokens[token]];
|
|
203
|
+
return weekdayNames[+token];
|
|
137
204
|
}
|
|
138
205
|
function weekdayRange(bounds) {
|
|
139
206
|
return weekdayName(bounds[0]) + " bis " + weekdayName(bounds[1]);
|
|
@@ -170,11 +237,15 @@ function everyNthHour(segment) {
|
|
|
170
237
|
const start = segment.startToken === "*" ? 0 : +segment.startToken;
|
|
171
238
|
return start === 0 ? base : base + " ab " + start + " Uhr";
|
|
172
239
|
}
|
|
173
|
-
function
|
|
174
|
-
if (
|
|
175
|
-
return
|
|
240
|
+
function confinedHourStride(segment) {
|
|
241
|
+
if (segment.startToken.indexOf("-") !== -1) {
|
|
242
|
+
return false;
|
|
176
243
|
}
|
|
177
|
-
|
|
244
|
+
const start = segment.startToken === "*" ? 0 : +segment.startToken;
|
|
245
|
+
return 24 % segment.interval === 0 && start < segment.interval;
|
|
246
|
+
}
|
|
247
|
+
function weekdayNoun(token) {
|
|
248
|
+
return weekdayNouns[toFieldNumber(token, weekdayNumbers)];
|
|
178
249
|
}
|
|
179
250
|
function quartzWeekday(field) {
|
|
180
251
|
if (field.indexOf("#") !== -1) {
|
|
@@ -198,22 +269,8 @@ function quartzDate(field) {
|
|
|
198
269
|
}
|
|
199
270
|
return null;
|
|
200
271
|
}
|
|
201
|
-
var monthTokens = {
|
|
202
|
-
JAN: 1,
|
|
203
|
-
FEB: 2,
|
|
204
|
-
MAR: 3,
|
|
205
|
-
APR: 4,
|
|
206
|
-
MAY: 5,
|
|
207
|
-
JUN: 6,
|
|
208
|
-
JUL: 7,
|
|
209
|
-
AUG: 8,
|
|
210
|
-
SEP: 9,
|
|
211
|
-
OCT: 10,
|
|
212
|
-
NOV: 11,
|
|
213
|
-
DEC: 12
|
|
214
|
-
};
|
|
215
272
|
function monthName(token, months2) {
|
|
216
|
-
return months2[token]
|
|
273
|
+
return months2[+token];
|
|
217
274
|
}
|
|
218
275
|
function monthRange(bounds, months2) {
|
|
219
276
|
return "von " + monthName(bounds[0], months2) + " bis " + monthName(bounds[1], months2);
|
|
@@ -290,14 +347,17 @@ function countedPhrase(ir, field, singular, plural) {
|
|
|
290
347
|
return "in den " + plural + " " + joinList(fieldValues(ir, field));
|
|
291
348
|
}
|
|
292
349
|
function secondsLead(ir) {
|
|
350
|
+
return secondsClause(ir, "jeder Minute");
|
|
351
|
+
}
|
|
352
|
+
function secondsClause(ir, anchor) {
|
|
293
353
|
if (ir.pattern.second === "*") {
|
|
294
354
|
return "jede Sekunde";
|
|
295
355
|
}
|
|
296
356
|
const segments = ir.analyses.segments.second;
|
|
297
|
-
if (ir.shapes.second === "step"
|
|
298
|
-
return
|
|
357
|
+
if (ir.shapes.second === "step") {
|
|
358
|
+
return stepClause(stepSegment(segments), UNITS.second, anchor);
|
|
299
359
|
}
|
|
300
|
-
return countedPhrase(ir, "second", "Sekunde", "Sekunden") + "
|
|
360
|
+
return strideFromSegments(segments, UNITS.second, anchor) ?? countedPhrase(ir, "second", "Sekunde", "Sekunden") + " " + anchor;
|
|
301
361
|
}
|
|
302
362
|
function spanTime(hour, minute, sep) {
|
|
303
363
|
return hour + sep + pad(minute);
|
|
@@ -366,8 +426,15 @@ function renderEveryHour() {
|
|
|
366
426
|
function renderSeconds(ir) {
|
|
367
427
|
return secondsLead(ir);
|
|
368
428
|
}
|
|
429
|
+
function minutePastClause(ir) {
|
|
430
|
+
return strideFromSegments(
|
|
431
|
+
fieldSegments(ir, "minute"),
|
|
432
|
+
UNITS.minute,
|
|
433
|
+
"jeder Stunde"
|
|
434
|
+
) ?? countedPhrase(ir, "minute", "Minute", "Minuten") + " jeder Stunde";
|
|
435
|
+
}
|
|
369
436
|
function renderMinutePast(ir) {
|
|
370
|
-
return
|
|
437
|
+
return minutePastClause(ir);
|
|
371
438
|
}
|
|
372
439
|
function renderSecondsWithinMinute(ir, plan) {
|
|
373
440
|
if (plan.singleSecond) {
|
|
@@ -375,42 +442,84 @@ function renderSecondsWithinMinute(ir, plan) {
|
|
|
375
442
|
}
|
|
376
443
|
return secondsLead(ir) + ", in Minute " + ir.pattern.minute + " jeder Stunde";
|
|
377
444
|
}
|
|
445
|
+
function wholeHour(hour) {
|
|
446
|
+
if (hour === 0) {
|
|
447
|
+
return "der Mitternachtsstunde";
|
|
448
|
+
}
|
|
449
|
+
if (hour === 12) {
|
|
450
|
+
return "der Mittagsstunde";
|
|
451
|
+
}
|
|
452
|
+
return "der " + hour + "-Uhr-Stunde";
|
|
453
|
+
}
|
|
378
454
|
function renderMinuteSpanInHour(ir, plan, opts) {
|
|
455
|
+
if (ir.pattern.minute === "*") {
|
|
456
|
+
return "jede Minute " + wholeHour(plan.hour);
|
|
457
|
+
}
|
|
379
458
|
const sep = opts.style.sep;
|
|
380
459
|
return "jede Minute von " + spanTime(plan.hour, plan.span[0], sep) + " bis " + spanTime(plan.hour, plan.span[1], sep) + " Uhr";
|
|
381
460
|
}
|
|
382
461
|
function renderComposeSeconds(ir, plan, opts) {
|
|
462
|
+
if ((plan.rest.kind === "clockTimes" || plan.rest.kind === "compactClockTimes") && ir.shapes.minute === "single") {
|
|
463
|
+
const cadence = hourCadence(ir, +ir.pattern.minute);
|
|
464
|
+
if (cadence !== null) {
|
|
465
|
+
return cadence;
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
if (composeMinuteZero(ir, plan)) {
|
|
469
|
+
return secondsLead(ir) + " " + clockMinuteGenitive(plan.rest.times, opts.style.sep);
|
|
470
|
+
}
|
|
471
|
+
if (plan.rest.kind === "minuteFrequency" && ir.shapes.second === "wildcard" && ir.shapes.hour === "wildcard") {
|
|
472
|
+
const minuteStep = stepSegment(ir.analyses.segments.minute);
|
|
473
|
+
if (minuteStep.startToken === "*" && minuteStep.interval === 2) {
|
|
474
|
+
return secondsLead(ir) + " jeder zweiten Minute";
|
|
475
|
+
}
|
|
476
|
+
}
|
|
383
477
|
return secondsLead(ir) + ", " + render(ir, plan.rest, opts);
|
|
384
478
|
}
|
|
479
|
+
function composeMinuteZero(ir, plan) {
|
|
480
|
+
return plan.rest.kind === "clockTimes" && plan.rest.times.every((time) => +time.minute === 0);
|
|
481
|
+
}
|
|
482
|
+
function clockMinuteGenitive(times, sep) {
|
|
483
|
+
const clocks = times.map(function clock(time) {
|
|
484
|
+
return time.hour + sep + pad(time.minute);
|
|
485
|
+
});
|
|
486
|
+
return clocks.length === 1 ? "der Minute " + clocks[0] : "der Minuten " + joinList(clocks);
|
|
487
|
+
}
|
|
385
488
|
function renderMinutesAcrossHours(ir, plan, opts) {
|
|
386
489
|
const sep = opts.style.sep;
|
|
387
490
|
if (plan.form === "wildcard") {
|
|
388
491
|
return "jede Minute " + duringHours(ir, plan.times, sep);
|
|
389
492
|
}
|
|
390
493
|
const hours = plan.times.kind === "fires" ? atHours(plan.times.fires) : joinList(hourSegmentParts(ir, 0, 0, sep));
|
|
391
|
-
return countedPhrase(ir, "minute", "Minute", "Minuten") + ", " + hours;
|
|
494
|
+
return (strideFromSegments(fieldSegments(ir, "minute"), UNITS.minute, "") ?? countedPhrase(ir, "minute", "Minute", "Minuten")) + ", " + hours;
|
|
392
495
|
}
|
|
393
496
|
function renderMinuteSpanAcrossHourStep(ir, plan) {
|
|
394
497
|
if (plan.form === "wildcard") {
|
|
395
498
|
return "jede Minute " + everyNthHour(stepSegment(ir.analyses.segments.hour));
|
|
396
499
|
}
|
|
397
|
-
|
|
500
|
+
const segment = stepSegment(ir.analyses.segments.hour);
|
|
501
|
+
const hours = confinedHourStride(segment) ? everyNthHour(segment) : atHours(segment.fires);
|
|
502
|
+
return (strideFromSegments(fieldSegments(ir, "minute"), UNITS.minute, "") ?? countedPhrase(ir, "minute", "Minute", "Minuten")) + ", " + hours;
|
|
398
503
|
}
|
|
399
504
|
function renderCompactClockTimes(ir, plan, opts) {
|
|
400
505
|
const sep = opts.style.sep;
|
|
401
506
|
if (plan.fold) {
|
|
507
|
+
const cadence = hourCadence(ir, plan.minute);
|
|
508
|
+
if (cadence !== null) {
|
|
509
|
+
return cadence;
|
|
510
|
+
}
|
|
402
511
|
const hourly = fieldSegments(ir, "hour").some((segment) => segment.kind === "range");
|
|
403
512
|
return (hourly ? "st\xFCndlich " : "t\xE4glich ") + joinList(hourSegmentParts(ir, plan.minute, ir.analyses.clockSecond, sep));
|
|
404
513
|
}
|
|
405
514
|
const hours = fieldSegments(ir, "hour").some((segment) => segment.kind === "range") ? joinList(hourSegmentParts(ir, 0, 0, sep)) : atHours(hourFires(ir));
|
|
406
515
|
const lead = ir.analyses.clockSecond ? countedPhrase(ir, "second", "Sekunde", "Sekunden") + ", " : "";
|
|
407
|
-
return lead + countedPhrase(ir, "minute", "Minute", "Minuten") + ", " + hours;
|
|
516
|
+
return lead + (strideFromSegments(fieldSegments(ir, "minute"), UNITS.minute, "") ?? countedPhrase(ir, "minute", "Minute", "Minuten")) + ", " + hours;
|
|
408
517
|
}
|
|
409
518
|
function renderMinuteFrequency(ir, plan, opts) {
|
|
410
519
|
const segment = stepSegment(ir.analyses.segments.minute);
|
|
411
520
|
const sep = opts.style.sep;
|
|
412
521
|
const clean = cleanStep(segment, 60);
|
|
413
|
-
const base =
|
|
522
|
+
const base = stepClause(segment, UNITS.minute, "jeder Stunde");
|
|
414
523
|
if (plan.hours.kind === "window") {
|
|
415
524
|
const window = hourWindow(
|
|
416
525
|
plan.hours.from,
|
|
@@ -432,6 +541,67 @@ function hourStepPhrase(ir) {
|
|
|
432
541
|
const segment = stepSegment(ir.analyses.segments.hour);
|
|
433
542
|
return cleanStep(segment, 24) ? everyN(segment.interval, UNITS.hour) : atHours(segment.fires);
|
|
434
543
|
}
|
|
544
|
+
function hourStrideCadence(stride) {
|
|
545
|
+
const { start, interval, last } = stride;
|
|
546
|
+
const cadence = everyN(interval, UNITS.hour);
|
|
547
|
+
const tiles = 24 % interval === 0;
|
|
548
|
+
if (start === 0 && tiles) {
|
|
549
|
+
return cadence;
|
|
550
|
+
}
|
|
551
|
+
if (start < interval && tiles) {
|
|
552
|
+
return cadence + " ab " + start + " Uhr";
|
|
553
|
+
}
|
|
554
|
+
return cadence + " von " + start + " bis " + last + " Uhr";
|
|
555
|
+
}
|
|
556
|
+
function hourStride(ir) {
|
|
557
|
+
const segments = fieldSegments(ir, "hour");
|
|
558
|
+
if (!segments) {
|
|
559
|
+
return null;
|
|
560
|
+
}
|
|
561
|
+
if (segments.length === 1 && segments[0].kind === "step") {
|
|
562
|
+
const segment = segments[0];
|
|
563
|
+
const start = segment.startToken === "*" ? 0 : +segment.startToken.split("-")[0];
|
|
564
|
+
return { interval: segment.interval, last: segment.fires[segment.fires.length - 1], start };
|
|
565
|
+
}
|
|
566
|
+
const values = singleValues(segments);
|
|
567
|
+
const step = values && arithmeticStep(values);
|
|
568
|
+
return step || null;
|
|
569
|
+
}
|
|
570
|
+
function subMinuteSecond(ir) {
|
|
571
|
+
return ir.pattern.second === "*" || ir.shapes.second === "step";
|
|
572
|
+
}
|
|
573
|
+
function hourCadenceLead(ir, minute) {
|
|
574
|
+
if (minute === 0) {
|
|
575
|
+
if (subMinuteSecond(ir)) {
|
|
576
|
+
return secondsClause(ir, "jeder Minute") + " f\xFCr eine Minute";
|
|
577
|
+
}
|
|
578
|
+
return secondsClause(ir, "jeder Stunde");
|
|
579
|
+
}
|
|
580
|
+
const minutePhrase = "in Minute " + minute;
|
|
581
|
+
if (ir.pattern.second === "0") {
|
|
582
|
+
return minutePhrase;
|
|
583
|
+
}
|
|
584
|
+
return secondsClause(ir, "jeder Minute") + ", " + minutePhrase;
|
|
585
|
+
}
|
|
586
|
+
function hourCadence(ir, minute) {
|
|
587
|
+
const stride = hourStride(ir);
|
|
588
|
+
if (!stride) {
|
|
589
|
+
return null;
|
|
590
|
+
}
|
|
591
|
+
const fires = (stride.last - stride.start) / stride.interval + 1;
|
|
592
|
+
if (ir.pattern.second === "0" && fires <= maxClockTimes) {
|
|
593
|
+
return null;
|
|
594
|
+
}
|
|
595
|
+
const segment = fieldSegments(ir, "hour")[0];
|
|
596
|
+
const confined = minute === 0 && subMinuteSecond(ir) && fieldSegments(ir, "hour").length === 1 && segment.kind === "step" && confinedHourStride(segment);
|
|
597
|
+
if (confined) {
|
|
598
|
+
return secondsClause(ir, "jeder Minute") + " f\xFCr eine Minute " + everyNthHour(segment);
|
|
599
|
+
}
|
|
600
|
+
return hourCadenceLead(ir, minute) + ", " + hourStrideCadence(stride);
|
|
601
|
+
}
|
|
602
|
+
function hourCadenceApplies(ir) {
|
|
603
|
+
return ir.shapes.minute === "single" && hourCadence(ir, +ir.pattern.minute) !== null;
|
|
604
|
+
}
|
|
435
605
|
function renderHourRange(ir, plan, opts) {
|
|
436
606
|
const window = hourWindow(
|
|
437
607
|
plan.from,
|
|
@@ -448,6 +618,12 @@ function renderHourRange(ir, plan, opts) {
|
|
|
448
618
|
return countedPhrase(ir, "minute", "Minute", "Minuten") + " jeder Stunde, " + window;
|
|
449
619
|
}
|
|
450
620
|
function renderClockTimes(ir, plan, opts) {
|
|
621
|
+
if (ir.shapes.minute === "single") {
|
|
622
|
+
const cadence = hourCadence(ir, +ir.pattern.minute);
|
|
623
|
+
if (cadence !== null) {
|
|
624
|
+
return cadence;
|
|
625
|
+
}
|
|
626
|
+
}
|
|
451
627
|
return "um " + timesPhrase(plan.times, opts.style.sep);
|
|
452
628
|
}
|
|
453
629
|
var renderers = {
|
|
@@ -490,8 +666,17 @@ function qualifier(ir, months2) {
|
|
|
490
666
|
return "";
|
|
491
667
|
}
|
|
492
668
|
var LEADING_PLANS = /* @__PURE__ */ new Set(["clockTimes"]);
|
|
669
|
+
function leadsQualifier(ir) {
|
|
670
|
+
return LEADING_PLANS.has(ir.plan.kind) || isComposeMinuteZero(ir);
|
|
671
|
+
}
|
|
672
|
+
function isComposeMinuteZero(ir) {
|
|
673
|
+
return ir.plan.kind === "composeSeconds" && composeMinuteZero(ir, ir.plan);
|
|
674
|
+
}
|
|
493
675
|
function needsDailyFrame(ir) {
|
|
494
|
-
if (ir
|
|
676
|
+
if (hourCadenceApplies(ir)) {
|
|
677
|
+
return false;
|
|
678
|
+
}
|
|
679
|
+
if (ir.plan.kind === "clockTimes" || isComposeMinuteZero(ir)) {
|
|
495
680
|
return true;
|
|
496
681
|
}
|
|
497
682
|
return ir.plan.kind === "hourStep" && !cleanStep(stepSegment(ir.analyses.segments.hour), 24);
|
|
@@ -534,7 +719,7 @@ function describe(ir, opts) {
|
|
|
534
719
|
const qual = qualifier(ir, opts.style.months);
|
|
535
720
|
let base = core;
|
|
536
721
|
if (qual) {
|
|
537
|
-
base =
|
|
722
|
+
base = leadsQualifier(ir) ? qual + " " + core : core + " " + qual;
|
|
538
723
|
} else if (needsDailyFrame(ir)) {
|
|
539
724
|
base = "t\xE4glich " + core;
|
|
540
725
|
}
|