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/fi.js
CHANGED
|
@@ -14,6 +14,42 @@ 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
|
+
var maxClockTimes = 6;
|
|
28
|
+
|
|
29
|
+
// src/core/util.ts
|
|
30
|
+
function isNonNegativeInteger(value) {
|
|
31
|
+
const digits = /^\d+$/;
|
|
32
|
+
return digits.test(value);
|
|
33
|
+
}
|
|
34
|
+
function arithmeticStep(values) {
|
|
35
|
+
if (values.length < 5) {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
const interval = values[1] - values[0];
|
|
39
|
+
if (interval < 2) {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
for (let i = 2; i < values.length; i += 1) {
|
|
43
|
+
if (values[i] - values[i - 1] !== interval) {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return { start: values[0], interval, last: values[values.length - 1] };
|
|
48
|
+
}
|
|
49
|
+
function toFieldNumber(token, numberMap) {
|
|
50
|
+
return isNonNegativeInteger(token) ? +token : numberMap[token.toUpperCase()];
|
|
51
|
+
}
|
|
52
|
+
|
|
17
53
|
// src/lang/fi/dialects.ts
|
|
18
54
|
var dialects = {
|
|
19
55
|
fi: {
|
|
@@ -140,40 +176,19 @@ var monthStems = [
|
|
|
140
176
|
"marras",
|
|
141
177
|
"joulu"
|
|
142
178
|
];
|
|
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
179
|
var units = {
|
|
167
180
|
minute: {
|
|
168
181
|
mark: "joka tunti",
|
|
169
182
|
anchor: "jokaisen tunnin",
|
|
170
183
|
ela: "minuutista",
|
|
184
|
+
ill: "minuuttiin",
|
|
171
185
|
gen: "minuutin"
|
|
172
186
|
},
|
|
173
187
|
second: {
|
|
174
188
|
mark: "joka minuutti",
|
|
175
189
|
anchor: "jokaisen minuutin",
|
|
176
190
|
ela: "sekunnista",
|
|
191
|
+
ill: "sekuntiin",
|
|
177
192
|
gen: "sekunnin"
|
|
178
193
|
}
|
|
179
194
|
};
|
|
@@ -229,26 +244,61 @@ function renderSecondsWithinMinute(ir, plan, opts) {
|
|
|
229
244
|
}
|
|
230
245
|
return secondsLeadClause(ir, opts) + ", " + atMarks(minuteField, units.minute, true) + trailingQualifier(ir, opts);
|
|
231
246
|
}
|
|
247
|
+
function composeSecondsOverMinuteStep(ir, freq, opts) {
|
|
248
|
+
const seg = stepSegment(ir.analyses.segments.minute);
|
|
249
|
+
const stepPhrase = stepCycle60(seg, units.minute, opts);
|
|
250
|
+
if (freq.hours.kind === "during" && minuteStepIsAnchored(seg)) {
|
|
251
|
+
const bareHours = kloFromTimes(ir, freq.hours.times, opts);
|
|
252
|
+
return hoursFirstMinutes(bareHours, ir, opts) + ", " + secondsLeadClause(ir, opts) + trailingQualifier(ir, opts);
|
|
253
|
+
}
|
|
254
|
+
let hourClause = "";
|
|
255
|
+
if (freq.hours.kind === "during") {
|
|
256
|
+
hourClause = " " + hourWindowsFromTimes(ir, freq.hours.times, opts);
|
|
257
|
+
} else if (freq.hours.kind === "window") {
|
|
258
|
+
hourClause = " " + hourWindow(freq.hours, opts);
|
|
259
|
+
} else if (freq.hours.kind === "step") {
|
|
260
|
+
hourClause = " " + everyNthHour(stepSegment(ir.analyses.segments.hour), opts);
|
|
261
|
+
}
|
|
262
|
+
return stepPhrase + ", " + secondsLeadClause(ir, opts) + hourClause + trailingQualifier(ir, opts);
|
|
263
|
+
}
|
|
264
|
+
function composeHourCadence(ir, plan, opts) {
|
|
265
|
+
const clockRest = plan.rest.kind === "clockTimes" || plan.rest.kind === "compactClockTimes";
|
|
266
|
+
return clockRest && ir.shapes.minute === "single" ? hourCadence(ir, +ir.pattern.minute, opts) : null;
|
|
267
|
+
}
|
|
232
268
|
function renderComposeSeconds(ir, plan, opts) {
|
|
269
|
+
const cadence = composeHourCadence(ir, plan, opts);
|
|
270
|
+
if (cadence !== null) {
|
|
271
|
+
return cadence;
|
|
272
|
+
}
|
|
233
273
|
if (plan.rest.kind === "minuteFrequency" && ir.pattern.second !== "*") {
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
} else if (freq.hours.kind === "during" && !minuteStepIsAnchored(seg)) {
|
|
242
|
-
hourClause = " " + hourWindowsFromTimes(ir, freq.hours.times, opts);
|
|
243
|
-
} else if (freq.hours.kind === "window") {
|
|
244
|
-
hourClause = " " + hourWindow(freq.hours, opts);
|
|
245
|
-
} else if (freq.hours.kind === "step") {
|
|
246
|
-
hourClause = " " + everyNthHour(stepSegment(ir.analyses.segments.hour), opts);
|
|
247
|
-
}
|
|
248
|
-
return stepPhrase + ", " + secondsLeadClause(ir, opts) + hourClause + trailingQualifier(ir, opts);
|
|
274
|
+
return composeSecondsOverMinuteStep(ir, plan.rest, opts);
|
|
275
|
+
}
|
|
276
|
+
if (plan.rest.kind === "clockTimes" && plan.rest.times.every((time) => +time.minute === 0)) {
|
|
277
|
+
return composeMinuteZero(ir, plan.rest, opts);
|
|
278
|
+
}
|
|
279
|
+
if (isEveryOtherMinuteSeconds(ir, plan)) {
|
|
280
|
+
return secondsLeadClause(ir, opts) + " joka toisena minuuttina";
|
|
249
281
|
}
|
|
250
282
|
return secondsLeadClause(ir, opts) + ", " + render(ir, plan.rest, opts);
|
|
251
283
|
}
|
|
284
|
+
function isEveryOtherMinuteSeconds(ir, plan) {
|
|
285
|
+
if (plan.rest.kind !== "minuteFrequency" || ir.pattern.second !== "*" || ir.shapes.hour !== "wildcard") {
|
|
286
|
+
return false;
|
|
287
|
+
}
|
|
288
|
+
const seg = stepSegment(ir.analyses.segments.minute);
|
|
289
|
+
return seg.startToken === "*" && seg.interval === 2;
|
|
290
|
+
}
|
|
291
|
+
function composeMinuteZero(ir, rest, opts) {
|
|
292
|
+
const clocks = rest.times.map(function clock(time) {
|
|
293
|
+
return clockDigits(
|
|
294
|
+
{ hour: time.hour, minute: time.minute },
|
|
295
|
+
{ sep: opts.style.sep }
|
|
296
|
+
);
|
|
297
|
+
});
|
|
298
|
+
const frame = clocks.length === 1 ? "minuutin " + clocks[0] : "minuuttien " + joinList(clocks);
|
|
299
|
+
const dayTrail = leadingQualifier(ir, opts).trimEnd();
|
|
300
|
+
return secondsLeadClause(ir, opts) + " " + frame + " aikana" + (dayTrail ? ", " + dayTrail : "");
|
|
301
|
+
}
|
|
252
302
|
function secondsLeadClause(ir, opts) {
|
|
253
303
|
const secondField = ir.pattern.second;
|
|
254
304
|
const shape = ir.shapes.second;
|
|
@@ -266,7 +316,7 @@ function secondsLeadClause(ir, opts) {
|
|
|
266
316
|
if (shape === "single") {
|
|
267
317
|
return atMarks(secondField, units.second, marked);
|
|
268
318
|
}
|
|
269
|
-
return atMarks(
|
|
319
|
+
return strideFromSegments(ir.analyses.segments.second, units.second, opts) ?? atMarks(
|
|
270
320
|
joinList(segmentWords(ir.analyses.segments.second)),
|
|
271
321
|
units.second,
|
|
272
322
|
marked
|
|
@@ -279,20 +329,20 @@ function renderSingleMinute(ir, plan, opts) {
|
|
|
279
329
|
return atMarks(ir.pattern.minute, units.minute, true) + trailingQualifier(ir, opts);
|
|
280
330
|
}
|
|
281
331
|
function renderRangeOfMinutes(ir, plan, opts) {
|
|
282
|
-
return minutesList(ir) + trailingQualifier(ir, opts);
|
|
332
|
+
return minutesList(ir, opts) + trailingQualifier(ir, opts);
|
|
283
333
|
}
|
|
284
334
|
function renderMultipleMinutes(ir, plan, opts) {
|
|
285
|
-
return minutesList(ir) + trailingQualifier(ir, opts);
|
|
335
|
+
return minutesList(ir, opts) + trailingQualifier(ir, opts);
|
|
286
336
|
}
|
|
287
|
-
function minutesList(ir) {
|
|
288
|
-
return atMarks(
|
|
337
|
+
function minutesList(ir, opts) {
|
|
338
|
+
return strideFromSegments(ir.analyses.segments.minute, units.minute, opts) ?? atMarks(
|
|
289
339
|
joinList(segmentWords(ir.analyses.segments.minute)),
|
|
290
340
|
units.minute,
|
|
291
341
|
true
|
|
292
342
|
);
|
|
293
343
|
}
|
|
294
|
-
function bareMinutes(ir) {
|
|
295
|
-
return atMarks(
|
|
344
|
+
function bareMinutes(ir, opts) {
|
|
345
|
+
return strideFromSegments(ir.analyses.segments.minute, units.minute, opts) ?? atMarks(
|
|
296
346
|
joinList(segmentWords(ir.analyses.segments.minute)),
|
|
297
347
|
units.minute,
|
|
298
348
|
false
|
|
@@ -323,7 +373,11 @@ function hoursAreRangeIsolated(segments) {
|
|
|
323
373
|
}
|
|
324
374
|
return hasRange && hasSingle;
|
|
325
375
|
}
|
|
326
|
-
function hoursFirstMinutes(hoursStr, ir) {
|
|
376
|
+
function hoursFirstMinutes(hoursStr, ir, opts) {
|
|
377
|
+
const stride = strideFromSegments(ir.analyses.segments.minute, units.minute, opts);
|
|
378
|
+
if (stride) {
|
|
379
|
+
return hoursStr + " aina " + stride;
|
|
380
|
+
}
|
|
327
381
|
return hoursStr + " aina minuuttien " + joinList(segmentWords(ir.analyses.segments.minute)) + " kohdalla";
|
|
328
382
|
}
|
|
329
383
|
function hourSegmentTimesWithSeka(ir, minute, second, opts) {
|
|
@@ -346,7 +400,7 @@ function renderMinuteFrequency(ir, plan, opts) {
|
|
|
346
400
|
if (plan.hours.kind === "during") {
|
|
347
401
|
if (minuteStepIsAnchored(seg)) {
|
|
348
402
|
const bareHours = kloFromTimes(ir, plan.hours.times, opts);
|
|
349
|
-
return hoursFirstMinutes(bareHours, ir) + trailingQualifier(ir, opts);
|
|
403
|
+
return hoursFirstMinutes(bareHours, ir, opts) + trailingQualifier(ir, opts);
|
|
350
404
|
}
|
|
351
405
|
return stepCycle60(seg, units.minute, opts) + " " + hourWindowsFromTimes(ir, plan.hours.times, opts) + trailingQualifier(ir, opts);
|
|
352
406
|
}
|
|
@@ -359,6 +413,9 @@ function renderMinuteFrequency(ir, plan, opts) {
|
|
|
359
413
|
return phrase + trailingQualifier(ir, opts);
|
|
360
414
|
}
|
|
361
415
|
function renderMinuteSpanInHour(ir, plan, opts) {
|
|
416
|
+
if (ir.pattern.minute === "*") {
|
|
417
|
+
return "joka minuutti kello " + plan.hour + " aikana" + trailingQualifier(ir, opts);
|
|
418
|
+
}
|
|
362
419
|
return "joka minuutti " + kloRange(
|
|
363
420
|
{ hour: plan.hour, minute: plan.span[0] },
|
|
364
421
|
{ hour: plan.hour, minute: plan.span[1] },
|
|
@@ -370,10 +427,10 @@ function renderMinutesAcrossHours(ir, plan, opts) {
|
|
|
370
427
|
return "joka minuutti " + hourWindowsFromTimes(ir, plan.times, opts) + trailingQualifier(ir, opts);
|
|
371
428
|
}
|
|
372
429
|
if (hoursAreRangeIsolated(ir.analyses.segments.hour)) {
|
|
373
|
-
return bareMinutes(ir) + " " + hourSegmentTimesWithSeka(ir, 0, null, opts) + trailingQualifier(ir, opts);
|
|
430
|
+
return bareMinutes(ir, opts) + " " + hourSegmentTimesWithSeka(ir, 0, null, opts) + trailingQualifier(ir, opts);
|
|
374
431
|
}
|
|
375
432
|
const hoursStr = kloFromTimes(ir, plan.times, opts);
|
|
376
|
-
return hoursFirstMinutes(hoursStr, ir) + trailingQualifier(ir, opts);
|
|
433
|
+
return hoursFirstMinutes(hoursStr, ir, opts) + trailingQualifier(ir, opts);
|
|
377
434
|
}
|
|
378
435
|
function renderMinuteSpanAcrossHourStep(ir, plan, opts) {
|
|
379
436
|
const segment = stepSegment(ir.analyses.segments.hour);
|
|
@@ -382,9 +439,9 @@ function renderMinuteSpanAcrossHourStep(ir, plan, opts) {
|
|
|
382
439
|
}
|
|
383
440
|
if (segment.startToken.indexOf("-") !== -1) {
|
|
384
441
|
const hoursStr = kloList(segment.fires, opts);
|
|
385
|
-
return hoursFirstMinutes(hoursStr, ir) + trailingQualifier(ir, opts);
|
|
442
|
+
return hoursFirstMinutes(hoursStr, ir, opts) + trailingQualifier(ir, opts);
|
|
386
443
|
}
|
|
387
|
-
return bareMinutes(ir) + hourStepTail(segment, opts) + trailingQualifier(ir, opts);
|
|
444
|
+
return bareMinutes(ir, opts) + hourStepTail(segment, opts) + trailingQualifier(ir, opts);
|
|
388
445
|
}
|
|
389
446
|
function plainHourStep(segment) {
|
|
390
447
|
return segment.startToken === "*" && 24 % segment.interval === 0;
|
|
@@ -442,7 +499,7 @@ function renderHourRange(ir, plan, opts) {
|
|
|
442
499
|
return "joka minuutti " + window + trailingQualifier(ir, opts);
|
|
443
500
|
}
|
|
444
501
|
if (plan.minuteForm === "range") {
|
|
445
|
-
return hoursFirstMinutes(window, ir) + trailingQualifier(ir, opts);
|
|
502
|
+
return hoursFirstMinutes(window, ir, opts) + trailingQualifier(ir, opts);
|
|
446
503
|
}
|
|
447
504
|
if (ir.pattern.minute === "0") {
|
|
448
505
|
return "joka tunti " + window + trailingQualifier(ir, opts);
|
|
@@ -454,7 +511,7 @@ function renderHourRange(ir, plan, opts) {
|
|
|
454
511
|
opts
|
|
455
512
|
) + trailingQualifier(ir, opts);
|
|
456
513
|
}
|
|
457
|
-
return hoursFirstMinutes(window, ir) + trailingQualifier(ir, opts);
|
|
514
|
+
return hoursFirstMinutes(window, ir, opts) + trailingQualifier(ir, opts);
|
|
458
515
|
}
|
|
459
516
|
function renderHourStep(ir, plan, opts) {
|
|
460
517
|
return stepHours(stepSegment(ir.analyses.segments.hour), opts) + trailingQualifier(ir, opts);
|
|
@@ -470,6 +527,12 @@ function hourWindow(window, opts) {
|
|
|
470
527
|
);
|
|
471
528
|
}
|
|
472
529
|
function renderClockTimes(ir, plan, opts) {
|
|
530
|
+
if (ir.shapes.minute === "single") {
|
|
531
|
+
const cadence = hourCadence(ir, +ir.pattern.minute, opts);
|
|
532
|
+
if (cadence !== null) {
|
|
533
|
+
return cadence;
|
|
534
|
+
}
|
|
535
|
+
}
|
|
473
536
|
if (plan.times.length === 1) {
|
|
474
537
|
const time = plan.times[0];
|
|
475
538
|
return leadingQualifier(ir, opts) + timeWord(time.hour, time.minute, time.second, opts);
|
|
@@ -480,6 +543,12 @@ function renderClockTimes(ir, plan, opts) {
|
|
|
480
543
|
return leadingQualifier(ir, opts) + "klo " + joinList(digits);
|
|
481
544
|
}
|
|
482
545
|
function renderCompactClockTimes(ir, plan, opts) {
|
|
546
|
+
if (plan.fold) {
|
|
547
|
+
const cadence = hourCadence(ir, plan.minute, opts);
|
|
548
|
+
if (cadence !== null) {
|
|
549
|
+
return cadence;
|
|
550
|
+
}
|
|
551
|
+
}
|
|
483
552
|
const hourSegs = ir.analyses.segments.hour;
|
|
484
553
|
if (hoursAreRangeIsolated(hourSegs)) {
|
|
485
554
|
if (plan.fold) {
|
|
@@ -490,14 +559,14 @@ function renderCompactClockTimes(ir, plan, opts) {
|
|
|
490
559
|
opts
|
|
491
560
|
);
|
|
492
561
|
}
|
|
493
|
-
const phrase2 = bareMinutes(ir) + " " + hourSegmentTimesWithSeka(ir, 0, null, opts) + trailingQualifier(ir, opts);
|
|
562
|
+
const phrase2 = bareMinutes(ir, opts) + " " + hourSegmentTimesWithSeka(ir, 0, null, opts) + trailingQualifier(ir, opts);
|
|
494
563
|
return ir.analyses.clockSecond ? secondsLeadClause(ir, opts) + ", " + phrase2 : phrase2;
|
|
495
564
|
}
|
|
496
565
|
if (plan.fold) {
|
|
497
566
|
return leadingQualifier(ir, opts) + hourSegmentTimes(ir, plan.minute, ir.analyses.clockSecond, opts);
|
|
498
567
|
}
|
|
499
568
|
const hoursStr = hourSegmentTimes(ir, 0, null, opts);
|
|
500
|
-
const phrase = hoursFirstMinutes(hoursStr, ir) + trailingQualifier(ir, opts);
|
|
569
|
+
const phrase = hoursFirstMinutes(hoursStr, ir, opts) + trailingQualifier(ir, opts);
|
|
501
570
|
return ir.analyses.clockSecond ? secondsLeadClause(ir, opts) + ", " + phrase : phrase;
|
|
502
571
|
}
|
|
503
572
|
var renderers = {
|
|
@@ -520,20 +589,48 @@ var renderers = {
|
|
|
520
589
|
singleMinute: renderSingleMinute,
|
|
521
590
|
standaloneSeconds: renderStandaloneSeconds
|
|
522
591
|
};
|
|
592
|
+
function renderStride(stride, opts) {
|
|
593
|
+
const { interval, start, last, cycle, unit } = stride;
|
|
594
|
+
const cadence = genitive(interval, opts) + " " + unit.gen + " v\xE4lein";
|
|
595
|
+
const tiles = cycle % interval === 0;
|
|
596
|
+
if (start === 0 && tiles) {
|
|
597
|
+
return cadence;
|
|
598
|
+
}
|
|
599
|
+
if (start < interval && tiles) {
|
|
600
|
+
return cadence + " " + unit.anchor + " " + unit.ela + " " + start + " alkaen";
|
|
601
|
+
}
|
|
602
|
+
return cadence + " " + unit.ela + " " + start + " " + unit.ill + " " + last;
|
|
603
|
+
}
|
|
604
|
+
function strideFromSegments(segments, unit, opts) {
|
|
605
|
+
const values = singleValues(segments);
|
|
606
|
+
const step = values && arithmeticStep(values);
|
|
607
|
+
return step ? renderStride({ ...step, cycle: 60, unit }, opts) : null;
|
|
608
|
+
}
|
|
609
|
+
function singleValues(segments) {
|
|
610
|
+
const values = [];
|
|
611
|
+
for (const segment of segments) {
|
|
612
|
+
if (segment.kind !== "single") {
|
|
613
|
+
return null;
|
|
614
|
+
}
|
|
615
|
+
values.push(+segment.value);
|
|
616
|
+
}
|
|
617
|
+
return values;
|
|
618
|
+
}
|
|
523
619
|
function stepCycle60(segment, unit, opts) {
|
|
524
620
|
if (segment.startToken.indexOf("-") !== -1) {
|
|
525
621
|
return atMarks(joinList(wordList(segment.fires)), unit, true);
|
|
526
622
|
}
|
|
527
623
|
const start = segment.startToken === "*" ? 0 : +segment.startToken;
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
if (start !== 0) {
|
|
531
|
-
if (segment.fires.length <= 3) {
|
|
532
|
-
return atMarks(joinList(wordList(segment.fires)), unit, true);
|
|
533
|
-
}
|
|
534
|
-
return cadence + " " + unit.anchor + " " + unit.ela + " " + start + " alkaen";
|
|
624
|
+
if (start !== 0 && segment.fires.length <= 3) {
|
|
625
|
+
return atMarks(joinList(wordList(segment.fires)), unit, true);
|
|
535
626
|
}
|
|
536
|
-
return
|
|
627
|
+
return renderStride({
|
|
628
|
+
interval: segment.interval,
|
|
629
|
+
start,
|
|
630
|
+
last: segment.fires[segment.fires.length - 1],
|
|
631
|
+
cycle: 60,
|
|
632
|
+
unit
|
|
633
|
+
}, opts);
|
|
537
634
|
}
|
|
538
635
|
function stepHours(segment, opts) {
|
|
539
636
|
if (segment.startToken.indexOf("-") !== -1) {
|
|
@@ -550,6 +647,71 @@ function stepHours(segment, opts) {
|
|
|
550
647
|
}
|
|
551
648
|
return cadence + " klo " + hourElatives[start] + " alkaen";
|
|
552
649
|
}
|
|
650
|
+
function hourStrideCadence(stride, opts) {
|
|
651
|
+
const { start, interval, last } = stride;
|
|
652
|
+
const cadence = genitive(interval, opts) + " tunnin v\xE4lein";
|
|
653
|
+
const tiles = 24 % interval === 0;
|
|
654
|
+
if (start === 0 && tiles) {
|
|
655
|
+
return cadence;
|
|
656
|
+
}
|
|
657
|
+
if (start < interval && tiles) {
|
|
658
|
+
return cadence + " klo " + hourElatives[start] + " alkaen";
|
|
659
|
+
}
|
|
660
|
+
return cadence + " " + kloRange({ hour: start, minute: 0 }, { hour: last, minute: 0 }, opts);
|
|
661
|
+
}
|
|
662
|
+
function hourStride(ir) {
|
|
663
|
+
const segments = ir.analyses.segments.hour;
|
|
664
|
+
if (!segments) {
|
|
665
|
+
return null;
|
|
666
|
+
}
|
|
667
|
+
if (segments.length === 1 && segments[0].kind === "step") {
|
|
668
|
+
const segment = segments[0];
|
|
669
|
+
const start = segment.startToken === "*" ? 0 : +segment.startToken.split("-")[0];
|
|
670
|
+
return { interval: segment.interval, last: segment.fires[segment.fires.length - 1], start };
|
|
671
|
+
}
|
|
672
|
+
const values = singleValues(segments);
|
|
673
|
+
const step = values && arithmeticStep(values);
|
|
674
|
+
return step || null;
|
|
675
|
+
}
|
|
676
|
+
function subMinuteSecond(ir) {
|
|
677
|
+
return ir.pattern.second === "*" || ir.shapes.second === "step";
|
|
678
|
+
}
|
|
679
|
+
function hourCadenceLead(ir, minute, opts) {
|
|
680
|
+
if (minute === 0) {
|
|
681
|
+
if (subMinuteSecond(ir)) {
|
|
682
|
+
return secondsLeadClause(ir, opts) + " minuutin ajan";
|
|
683
|
+
}
|
|
684
|
+
return secondsLeadClause(ir, opts);
|
|
685
|
+
}
|
|
686
|
+
const minutePhrase = atMarks(String(minute), units.minute, false);
|
|
687
|
+
if (ir.pattern.second === "0") {
|
|
688
|
+
return minutePhrase;
|
|
689
|
+
}
|
|
690
|
+
return secondsLeadClause(ir, opts) + ", " + minutePhrase;
|
|
691
|
+
}
|
|
692
|
+
function hourCadence(ir, minute, opts) {
|
|
693
|
+
const stride = hourStride(ir);
|
|
694
|
+
if (!stride) {
|
|
695
|
+
return null;
|
|
696
|
+
}
|
|
697
|
+
const fires = (stride.last - stride.start) / stride.interval + 1;
|
|
698
|
+
if (ir.pattern.second === "0" && fires <= maxClockTimes) {
|
|
699
|
+
return null;
|
|
700
|
+
}
|
|
701
|
+
const segment = ir.analyses.segments.hour[0];
|
|
702
|
+
const confined = minute === 0 && subMinuteSecond(ir) && ir.analyses.segments.hour.length === 1 && segment.kind === "step" && cleanHourStride(segment);
|
|
703
|
+
if (confined) {
|
|
704
|
+
return secondsLeadClause(ir, opts) + " minuutin ajan " + everyNthHour(segment, opts) + trailingQualifier(ir, opts);
|
|
705
|
+
}
|
|
706
|
+
return hourCadenceLead(ir, minute, opts) + ", " + hourStrideCadence(stride, opts) + trailingQualifier(ir, opts);
|
|
707
|
+
}
|
|
708
|
+
function cleanHourStride(segment) {
|
|
709
|
+
if (segment.startToken.indexOf("-") !== -1) {
|
|
710
|
+
return false;
|
|
711
|
+
}
|
|
712
|
+
const start = segment.startToken === "*" ? 0 : +segment.startToken;
|
|
713
|
+
return 24 % segment.interval === 0 && start < segment.interval;
|
|
714
|
+
}
|
|
553
715
|
function kloList(hours, opts) {
|
|
554
716
|
if (hours.length === 1) {
|
|
555
717
|
return timeWord(hours[0], 0, null, opts);
|
|
@@ -814,13 +976,10 @@ function quartzWeekdayPhrase(weekdayField) {
|
|
|
814
976
|
}
|
|
815
977
|
}
|
|
816
978
|
function weekdayNumber(token) {
|
|
817
|
-
|
|
818
|
-
return weekdayTokens[token];
|
|
819
|
-
}
|
|
820
|
-
return +token % 7;
|
|
979
|
+
return toFieldNumber("" + token, weekdayNumbers) % 7;
|
|
821
980
|
}
|
|
822
981
|
function monthNumber(token) {
|
|
823
|
-
return
|
|
982
|
+
return +token;
|
|
824
983
|
}
|
|
825
984
|
function applyYear(description, ir, opts) {
|
|
826
985
|
const yearField = ir.pattern.year;
|
|
@@ -902,7 +1061,9 @@ var fi = {
|
|
|
902
1061
|
fallback: "tunnistamaton cron-lauseke",
|
|
903
1062
|
options: normalizeOptions,
|
|
904
1063
|
reboot: "j\xE4rjestelm\xE4n k\xE4ynnistyess\xE4",
|
|
905
|
-
|
|
1064
|
+
// A description ending in a period already carries it, so closing the
|
|
1065
|
+
// sentence must not double it.
|
|
1066
|
+
sentence: (description) => "Suoritetaan " + description + (description.endsWith(".") ? "" : ".")
|
|
906
1067
|
};
|
|
907
1068
|
var index_default = fi;
|
|
908
1069
|
export {
|