cronli5 0.2.1 → 0.3.4
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 +109 -0
- package/README.md +4 -4
- package/cronli5.min.js +2 -2
- package/dist/cronli5.cjs +471 -383
- package/dist/cronli5.js +471 -383
- package/dist/lang/de.cjs +286 -215
- package/dist/lang/de.js +286 -215
- package/dist/lang/en.cjs +413 -327
- package/dist/lang/en.js +413 -327
- package/dist/lang/es.cjs +303 -265
- package/dist/lang/es.js +303 -265
- package/dist/lang/fi.cjs +311 -266
- package/dist/lang/fi.js +311 -266
- package/dist/lang/zh.cjs +320 -240
- package/dist/lang/zh.js +320 -240
- package/package.json +6 -6
- package/src/core/analyze.ts +12 -12
- package/src/core/cadence.ts +164 -0
- package/src/core/index.ts +3 -1
- package/src/core/normalize.ts +3 -3
- package/src/core/parse.ts +1 -1
- package/src/core/{ir.ts → schedule.ts} +17 -18
- package/src/core/specs.ts +1 -1
- package/src/core/util.ts +3 -165
- package/src/core/validate.ts +1 -1
- package/src/core/weekday.ts +54 -0
- package/src/cronli5.ts +5 -5
- package/src/lang/de/index.ts +329 -219
- package/src/lang/en/dialects.ts +1 -1
- package/src/lang/en/index.ts +521 -372
- package/src/lang/es/index.ts +338 -286
- package/src/lang/es/notes.md +1 -1
- package/src/lang/fi/dialects.ts +1 -1
- package/src/lang/fi/index.ts +365 -299
- package/src/lang/fi/notes.md +23 -8
- package/src/lang/fi/status.json +1 -1
- package/src/lang/zh/index.ts +386 -245
- package/src/types.ts +6 -6
- package/types/core/analyze.d.ts +3 -3
- package/types/core/cadence.d.ts +33 -0
- package/types/core/index.d.ts +3 -1
- package/types/core/normalize.d.ts +1 -1
- package/types/core/parse.d.ts +1 -1
- package/types/core/{ir.d.ts → schedule.d.ts} +11 -16
- package/types/core/specs.d.ts +1 -1
- package/types/core/util.d.ts +1 -30
- package/types/core/weekday.d.ts +10 -0
- package/types/lang/de/index.d.ts +1 -1
- package/types/lang/en/dialects.d.ts +1 -1
- package/types/lang/en/index.d.ts +1 -1
- package/types/lang/es/index.d.ts +1 -1
- package/types/lang/fi/dialects.d.ts +1 -1
- package/types/lang/fi/index.d.ts +1 -1
- package/types/lang/zh/index.d.ts +1 -1
- package/types/types.d.ts +5 -5
package/dist/lang/fi.cjs
CHANGED
|
@@ -57,6 +57,16 @@ function isNonNegativeInteger(value) {
|
|
|
57
57
|
const digits = /^\d+$/;
|
|
58
58
|
return digits.test(value);
|
|
59
59
|
}
|
|
60
|
+
function toFieldNumber(token, numberMap) {
|
|
61
|
+
return isNonNegativeInteger(token) ? +token : numberMap[token.toUpperCase()];
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// src/core/shapes.ts
|
|
65
|
+
function isOpenStep(field) {
|
|
66
|
+
return field.indexOf("/") !== -1 && field.indexOf("-") === -1 && field.indexOf(",") === -1;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// src/core/cadence.ts
|
|
60
70
|
function arithmeticStep(values) {
|
|
61
71
|
if (values.length < 5) {
|
|
62
72
|
return null;
|
|
@@ -72,34 +82,11 @@ function arithmeticStep(values) {
|
|
|
72
82
|
}
|
|
73
83
|
return { start: values[0], interval, last: values[values.length - 1] };
|
|
74
84
|
}
|
|
75
|
-
function
|
|
76
|
-
return
|
|
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
|
-
}
|
|
95
|
-
function toFieldNumber(token, numberMap) {
|
|
96
|
-
return isNonNegativeInteger(token) ? +token : numberMap[token.toUpperCase()];
|
|
85
|
+
function segmentsOf(schedule, field) {
|
|
86
|
+
return schedule.analyses.segments[field] ?? [];
|
|
97
87
|
}
|
|
98
|
-
function
|
|
99
|
-
return
|
|
100
|
-
}
|
|
101
|
-
function stepSegment(ir, field) {
|
|
102
|
-
return segmentsOf(ir, field)[0];
|
|
88
|
+
function stepSegment(schedule, field) {
|
|
89
|
+
return segmentsOf(schedule, field)[0];
|
|
103
90
|
}
|
|
104
91
|
function singleValues(segments) {
|
|
105
92
|
const values = [];
|
|
@@ -114,6 +101,17 @@ function singleValues(segments) {
|
|
|
114
101
|
function offsetCleanStride(stride) {
|
|
115
102
|
return stride.start < stride.interval && 24 % stride.interval === 0;
|
|
116
103
|
}
|
|
104
|
+
function renderStride(spec, parts) {
|
|
105
|
+
const { start, interval, cycle } = spec;
|
|
106
|
+
const tiles = cycle % interval === 0;
|
|
107
|
+
if (start === 0 && tiles) {
|
|
108
|
+
return parts.bare();
|
|
109
|
+
}
|
|
110
|
+
if (start < interval && tiles) {
|
|
111
|
+
return parts.offset();
|
|
112
|
+
}
|
|
113
|
+
return parts.bounded();
|
|
114
|
+
}
|
|
117
115
|
function hourListStride(values) {
|
|
118
116
|
if (values.length < 2) {
|
|
119
117
|
return null;
|
|
@@ -133,9 +131,26 @@ function hourListStride(values) {
|
|
|
133
131
|
return { interval, last: values[values.length - 1], start: values[0] };
|
|
134
132
|
}
|
|
135
133
|
|
|
136
|
-
// src/core/
|
|
137
|
-
function
|
|
138
|
-
return
|
|
134
|
+
// src/core/weekday.ts
|
|
135
|
+
function weekdayDisplayKey(value) {
|
|
136
|
+
return value === 0 ? 7 : value;
|
|
137
|
+
}
|
|
138
|
+
function orderWeekdaysForDisplay(segments) {
|
|
139
|
+
const flattened = segments.flatMap(function flat(segment) {
|
|
140
|
+
return segment.kind === "step" ? segment.fires.map(function single(value) {
|
|
141
|
+
return { kind: "single", value: "" + value };
|
|
142
|
+
}) : [segment];
|
|
143
|
+
});
|
|
144
|
+
function key(segment) {
|
|
145
|
+
return segment.kind === "range" ? weekdayDisplayKey(+segment.bounds[0]) : weekdayDisplayKey(+segment.value);
|
|
146
|
+
}
|
|
147
|
+
return flattened.map(function index(segment, position) {
|
|
148
|
+
return [segment, position];
|
|
149
|
+
}).sort(function byDisplayKey(a, b) {
|
|
150
|
+
return key(a[0]) - key(b[0]) || a[1] - b[1];
|
|
151
|
+
}).map(function unwrap(pair) {
|
|
152
|
+
return pair[0];
|
|
153
|
+
});
|
|
139
154
|
}
|
|
140
155
|
|
|
141
156
|
// src/lang/fi/dialects.ts
|
|
@@ -292,94 +307,108 @@ function normalizeOptions(options) {
|
|
|
292
307
|
years: !!options.years
|
|
293
308
|
};
|
|
294
309
|
}
|
|
295
|
-
function restrictedMonthUnion(
|
|
296
|
-
return
|
|
310
|
+
function restrictedMonthUnion(schedule) {
|
|
311
|
+
return schedule.pattern.date !== "*" && schedule.pattern.weekday !== "*" && schedule.pattern.month !== "*";
|
|
297
312
|
}
|
|
298
|
-
function
|
|
299
|
-
|
|
313
|
+
function oddDayUnion(dateField) {
|
|
314
|
+
if (!isOpenStep(dateField)) {
|
|
315
|
+
return null;
|
|
316
|
+
}
|
|
317
|
+
const [start, step] = dateField.split("/");
|
|
318
|
+
return (start === "*" || start === "1") && +step === 2 ? "kuukauden parittomina p\xE4ivin\xE4" : null;
|
|
319
|
+
}
|
|
320
|
+
function unionDateArm(schedule) {
|
|
321
|
+
return quartzDatePhrase(schedule.pattern.date) || oddDayUnion(schedule.pattern.date) || dateWords(schedule) + " p\xE4iv\xE4n\xE4";
|
|
300
322
|
}
|
|
301
|
-
function
|
|
302
|
-
|
|
303
|
-
|
|
323
|
+
function unionWeekdayArm(schedule) {
|
|
324
|
+
const segments = segmentsOf(schedule, "weekday");
|
|
325
|
+
if (segments.length === 1 && segments[0].kind === "range" && segments[0].bounds[0] === "1" && segments[0].bounds[1] === "5") {
|
|
326
|
+
return "arkisin";
|
|
327
|
+
}
|
|
328
|
+
return weekdayQualifier(schedule);
|
|
329
|
+
}
|
|
330
|
+
function describe(schedule, opts) {
|
|
331
|
+
if (restrictedMonthUnion(schedule)) {
|
|
332
|
+
const timePart = render(schedule, schedule.plan, opts);
|
|
304
333
|
return applyYear(
|
|
305
|
-
monthPhrase(
|
|
306
|
-
|
|
334
|
+
monthPhrase(schedule) + " " + timePart + " " + unionDateArm(schedule) + " tai " + unionWeekdayArm(schedule),
|
|
335
|
+
schedule,
|
|
307
336
|
opts
|
|
308
337
|
);
|
|
309
338
|
}
|
|
310
|
-
return applyYear(render(
|
|
339
|
+
return applyYear(render(schedule, schedule.plan, opts), schedule, opts);
|
|
311
340
|
}
|
|
312
|
-
function render(
|
|
341
|
+
function render(schedule, plan, opts) {
|
|
313
342
|
const renderer = renderers[plan.kind];
|
|
314
|
-
return renderer(
|
|
343
|
+
return renderer(schedule, plan, opts);
|
|
315
344
|
}
|
|
316
|
-
function renderEverySecond(
|
|
317
|
-
return "joka sekunti" + trailingQualifier(
|
|
345
|
+
function renderEverySecond(schedule, plan, opts) {
|
|
346
|
+
return "joka sekunti" + trailingQualifier(schedule, opts);
|
|
318
347
|
}
|
|
319
|
-
function renderStandaloneSeconds(
|
|
320
|
-
return secondsLeadClause(
|
|
348
|
+
function renderStandaloneSeconds(schedule, plan, opts) {
|
|
349
|
+
return secondsLeadClause(schedule, opts) + trailingQualifier(schedule, opts);
|
|
321
350
|
}
|
|
322
|
-
function renderSecondPastMinute(
|
|
323
|
-
return atMarks(
|
|
351
|
+
function renderSecondPastMinute(schedule, plan, opts) {
|
|
352
|
+
return atMarks(schedule.pattern.second, units.second, true) + trailingQualifier(schedule, opts);
|
|
324
353
|
}
|
|
325
|
-
function renderSecondsWithinMinute(
|
|
326
|
-
const minuteField =
|
|
354
|
+
function renderSecondsWithinMinute(schedule, plan, opts) {
|
|
355
|
+
const minuteField = schedule.pattern.minute;
|
|
327
356
|
if (plan.singleSecond) {
|
|
328
|
-
return units.minute.mark + " " + minuteField + " " + units.minute.gen + " ja " +
|
|
357
|
+
return units.minute.mark + " " + minuteField + " " + units.minute.gen + " ja " + schedule.pattern.second + " " + units.second.gen + " kohdalla" + trailingQualifier(schedule, opts);
|
|
329
358
|
}
|
|
330
|
-
return secondsLeadClause(
|
|
359
|
+
return secondsLeadClause(schedule, opts) + ", " + atMarks(minuteField, units.minute, true) + trailingQualifier(schedule, opts);
|
|
331
360
|
}
|
|
332
|
-
function composeSecondsOverMinuteStep(
|
|
333
|
-
const seg = stepSegment(
|
|
361
|
+
function composeSecondsOverMinuteStep(schedule, freq, opts) {
|
|
362
|
+
const seg = stepSegment(schedule, "minute");
|
|
334
363
|
const stepPhrase = stepCycle60(seg, units.minute, opts);
|
|
335
364
|
if (freq.hours.kind === "during" && minuteStepIsAnchored(seg)) {
|
|
336
|
-
const bareHours = kloFromTimes(
|
|
337
|
-
return hoursFirstMinutes(bareHours,
|
|
365
|
+
const bareHours = kloFromTimes(schedule, freq.hours.times, opts);
|
|
366
|
+
return hoursFirstMinutes(bareHours, schedule, opts) + ", " + secondsLeadClause(schedule, opts) + trailingQualifier(schedule, opts);
|
|
338
367
|
}
|
|
339
368
|
let hourClause = "";
|
|
340
369
|
if (freq.hours.kind === "during") {
|
|
341
|
-
hourClause = " " + hourWindowsFromTimes(
|
|
370
|
+
hourClause = " " + hourWindowsFromTimes(schedule, freq.hours.times, opts);
|
|
342
371
|
} else if (freq.hours.kind === "window") {
|
|
343
372
|
hourClause = " " + hourWindow(freq.hours, opts);
|
|
344
373
|
} else if (freq.hours.kind === "step") {
|
|
345
|
-
hourClause = " " + everyNthHour(stepSegment(
|
|
374
|
+
hourClause = " " + everyNthHour(stepSegment(schedule, "hour"), opts);
|
|
346
375
|
}
|
|
347
|
-
return stepPhrase + ", " + secondsLeadClause(
|
|
376
|
+
return stepPhrase + ", " + secondsLeadClause(schedule, opts) + hourClause + trailingQualifier(schedule, opts);
|
|
348
377
|
}
|
|
349
|
-
function composeHourCadence(
|
|
378
|
+
function composeHourCadence(schedule, plan, opts) {
|
|
350
379
|
const clockRest = plan.rest.kind === "clockTimes" || plan.rest.kind === "compactClockTimes";
|
|
351
|
-
if (!clockRest ||
|
|
380
|
+
if (!clockRest || schedule.shapes.minute !== "single") {
|
|
352
381
|
return null;
|
|
353
382
|
}
|
|
354
|
-
const minute = +
|
|
355
|
-
return hourCadence(
|
|
383
|
+
const minute = +schedule.pattern.minute;
|
|
384
|
+
return hourCadence(schedule, minute, opts) ?? hourRangeCadence(schedule, minute, opts);
|
|
356
385
|
}
|
|
357
|
-
function renderComposeSeconds(
|
|
358
|
-
const cadence = composeHourCadence(
|
|
386
|
+
function renderComposeSeconds(schedule, plan, opts) {
|
|
387
|
+
const cadence = composeHourCadence(schedule, plan, opts);
|
|
359
388
|
if (cadence !== null) {
|
|
360
389
|
return cadence;
|
|
361
390
|
}
|
|
362
|
-
if (plan.rest.kind === "minuteFrequency" &&
|
|
363
|
-
return composeSecondsOverMinuteStep(
|
|
391
|
+
if (plan.rest.kind === "minuteFrequency" && schedule.pattern.second !== "*") {
|
|
392
|
+
return composeSecondsOverMinuteStep(schedule, plan.rest, opts);
|
|
364
393
|
}
|
|
365
394
|
if (plan.rest.kind === "clockTimes" && plan.rest.times.every((time) => +time.minute === 0)) {
|
|
366
|
-
return composeMinuteZero(
|
|
395
|
+
return composeMinuteZero(schedule, plan.rest, opts);
|
|
367
396
|
}
|
|
368
|
-
if (isEveryOtherMinuteSeconds(
|
|
369
|
-
return secondsLeadClause(
|
|
397
|
+
if (isEveryOtherMinuteSeconds(schedule, plan)) {
|
|
398
|
+
return secondsLeadClause(schedule, opts) + " joka toisena minuuttina";
|
|
370
399
|
}
|
|
371
|
-
const restOwnsLead = plan.rest.kind === "compactClockTimes" &&
|
|
372
|
-
const lead = restOwnsLead ? "" : secondsLeadClause(
|
|
373
|
-
return lead + render(
|
|
400
|
+
const restOwnsLead = plan.rest.kind === "compactClockTimes" && schedule.analyses.clockSecond;
|
|
401
|
+
const lead = restOwnsLead ? "" : secondsLeadClause(schedule, opts) + ", ";
|
|
402
|
+
return lead + render(schedule, plan.rest, opts);
|
|
374
403
|
}
|
|
375
|
-
function isEveryOtherMinuteSeconds(
|
|
376
|
-
if (plan.rest.kind !== "minuteFrequency" ||
|
|
404
|
+
function isEveryOtherMinuteSeconds(schedule, plan) {
|
|
405
|
+
if (plan.rest.kind !== "minuteFrequency" || schedule.pattern.second !== "*" || schedule.shapes.hour !== "wildcard") {
|
|
377
406
|
return false;
|
|
378
407
|
}
|
|
379
|
-
const seg = stepSegment(
|
|
408
|
+
const seg = stepSegment(schedule, "minute");
|
|
380
409
|
return seg.startToken === "*" && seg.interval === 2;
|
|
381
410
|
}
|
|
382
|
-
function composeMinuteZero(
|
|
411
|
+
function composeMinuteZero(schedule, rest, opts) {
|
|
383
412
|
const clocks = rest.times.map(function clock(time) {
|
|
384
413
|
return clockDigits(
|
|
385
414
|
{ hour: time.hour, minute: time.minute },
|
|
@@ -387,54 +416,66 @@ function composeMinuteZero(ir, rest, opts) {
|
|
|
387
416
|
);
|
|
388
417
|
});
|
|
389
418
|
const frame = clocks.length === 1 ? "minuutin " + clocks[0] : "minuuttien " + joinList(clocks);
|
|
390
|
-
const dayTrail = leadingQualifier(
|
|
391
|
-
return secondsLeadClause(
|
|
419
|
+
const dayTrail = leadingQualifier(schedule, opts).trimEnd();
|
|
420
|
+
return secondsLeadClause(schedule, opts) + " " + frame + " aikana" + (dayTrail ? ", " + dayTrail : "");
|
|
392
421
|
}
|
|
393
|
-
function secondsLeadClause(
|
|
394
|
-
const secondField =
|
|
395
|
-
const shape =
|
|
422
|
+
function secondsLeadClause(schedule, opts) {
|
|
423
|
+
const secondField = schedule.pattern.second;
|
|
424
|
+
const shape = schedule.shapes.second;
|
|
396
425
|
if (secondField === "*") {
|
|
397
426
|
return "joka sekunti";
|
|
398
427
|
}
|
|
399
428
|
if (shape === "step") {
|
|
400
429
|
return stepCycle60(
|
|
401
|
-
stepSegment(
|
|
430
|
+
stepSegment(schedule, "second"),
|
|
402
431
|
units.second,
|
|
403
432
|
opts
|
|
404
433
|
);
|
|
405
434
|
}
|
|
406
|
-
const marked =
|
|
435
|
+
const marked = schedule.pattern.minute === "*";
|
|
407
436
|
if (shape === "single") {
|
|
408
437
|
return atMarks(secondField, units.second, marked);
|
|
409
438
|
}
|
|
410
|
-
return strideFromSegments(
|
|
411
|
-
|
|
439
|
+
return strideFromSegments(
|
|
440
|
+
segmentsOf(schedule, "second"),
|
|
441
|
+
units.second,
|
|
442
|
+
opts
|
|
443
|
+
) ?? atMarks(
|
|
444
|
+
joinList(segmentWords(segmentsOf(schedule, "second"))),
|
|
412
445
|
units.second,
|
|
413
446
|
marked
|
|
414
447
|
);
|
|
415
448
|
}
|
|
416
|
-
function renderEveryMinute(
|
|
417
|
-
return "joka minuutti" + trailingQualifier(
|
|
449
|
+
function renderEveryMinute(schedule, plan, opts) {
|
|
450
|
+
return "joka minuutti" + trailingQualifier(schedule, opts);
|
|
418
451
|
}
|
|
419
|
-
function renderSingleMinute(
|
|
420
|
-
return atMarks(
|
|
452
|
+
function renderSingleMinute(schedule, plan, opts) {
|
|
453
|
+
return atMarks(schedule.pattern.minute, units.minute, true) + trailingQualifier(schedule, opts);
|
|
421
454
|
}
|
|
422
|
-
function renderRangeOfMinutes(
|
|
423
|
-
return minutesList(
|
|
455
|
+
function renderRangeOfMinutes(schedule, plan, opts) {
|
|
456
|
+
return minutesList(schedule, opts) + trailingQualifier(schedule, opts);
|
|
424
457
|
}
|
|
425
|
-
function renderMultipleMinutes(
|
|
426
|
-
return minutesList(
|
|
458
|
+
function renderMultipleMinutes(schedule, plan, opts) {
|
|
459
|
+
return minutesList(schedule, opts) + trailingQualifier(schedule, opts);
|
|
427
460
|
}
|
|
428
|
-
function minutesList(
|
|
429
|
-
return strideFromSegments(
|
|
430
|
-
|
|
461
|
+
function minutesList(schedule, opts) {
|
|
462
|
+
return strideFromSegments(
|
|
463
|
+
segmentsOf(schedule, "minute"),
|
|
464
|
+
units.minute,
|
|
465
|
+
opts
|
|
466
|
+
) ?? atMarks(
|
|
467
|
+
joinList(segmentWords(segmentsOf(schedule, "minute"))),
|
|
431
468
|
units.minute,
|
|
432
469
|
true
|
|
433
470
|
);
|
|
434
471
|
}
|
|
435
|
-
function bareMinutes(
|
|
436
|
-
return strideFromSegments(
|
|
437
|
-
|
|
472
|
+
function bareMinutes(schedule, opts) {
|
|
473
|
+
return strideFromSegments(
|
|
474
|
+
segmentsOf(schedule, "minute"),
|
|
475
|
+
units.minute,
|
|
476
|
+
opts
|
|
477
|
+
) ?? atMarks(
|
|
478
|
+
joinList(segmentWords(segmentsOf(schedule, "minute"))),
|
|
438
479
|
units.minute,
|
|
439
480
|
false
|
|
440
481
|
);
|
|
@@ -464,16 +505,16 @@ function hoursAreRangeIsolated(segments) {
|
|
|
464
505
|
}
|
|
465
506
|
return hasRange && hasSingle;
|
|
466
507
|
}
|
|
467
|
-
function hoursFirstMinutes(hoursStr,
|
|
468
|
-
const stride = strideFromSegments(segmentsOf(
|
|
508
|
+
function hoursFirstMinutes(hoursStr, schedule, opts) {
|
|
509
|
+
const stride = strideFromSegments(segmentsOf(schedule, "minute"), units.minute, opts);
|
|
469
510
|
if (stride) {
|
|
470
511
|
return hoursStr + " aina " + stride;
|
|
471
512
|
}
|
|
472
|
-
return hoursStr + " aina minuuttien " + joinList(segmentWords(segmentsOf(
|
|
513
|
+
return hoursStr + " aina minuuttien " + joinList(segmentWords(segmentsOf(schedule, "minute"))) + " kohdalla";
|
|
473
514
|
}
|
|
474
|
-
function hourSegmentTimesWithSeka(
|
|
515
|
+
function hourSegmentTimesWithSeka(schedule, minute, second, opts) {
|
|
475
516
|
const pieces = [];
|
|
476
|
-
segmentsOf(
|
|
517
|
+
segmentsOf(schedule, "hour").forEach(function clock(segment) {
|
|
477
518
|
if (segment.kind === "range") {
|
|
478
519
|
pieces.push(rangeDigits(
|
|
479
520
|
{ hour: +segment.bounds[0], minute, second },
|
|
@@ -486,61 +527,61 @@ function hourSegmentTimesWithSeka(ir, minute, second, opts) {
|
|
|
486
527
|
});
|
|
487
528
|
return "klo " + pieces.slice(0, -1).join(", ") + " sek\xE4 klo " + pieces[pieces.length - 1];
|
|
488
529
|
}
|
|
489
|
-
function renderMinuteFrequency(
|
|
490
|
-
const seg = stepSegment(
|
|
530
|
+
function renderMinuteFrequency(schedule, plan, opts) {
|
|
531
|
+
const seg = stepSegment(schedule, "minute");
|
|
491
532
|
if (plan.hours.kind === "during") {
|
|
492
|
-
const cadence = unevenHourCadence(
|
|
533
|
+
const cadence = unevenHourCadence(schedule, opts);
|
|
493
534
|
if (cadence !== null) {
|
|
494
|
-
return stepCycle60(seg, units.minute, opts) + ", " + cadence + trailingQualifier(
|
|
535
|
+
return stepCycle60(seg, units.minute, opts) + ", " + cadence + trailingQualifier(schedule, opts);
|
|
495
536
|
}
|
|
496
537
|
if (minuteStepIsAnchored(seg)) {
|
|
497
|
-
const bareHours = kloFromTimes(
|
|
498
|
-
return hoursFirstMinutes(bareHours,
|
|
538
|
+
const bareHours = kloFromTimes(schedule, plan.hours.times, opts);
|
|
539
|
+
return hoursFirstMinutes(bareHours, schedule, opts) + trailingQualifier(schedule, opts);
|
|
499
540
|
}
|
|
500
|
-
return stepCycle60(seg, units.minute, opts) + " " + hourWindowsFromTimes(
|
|
541
|
+
return stepCycle60(seg, units.minute, opts) + " " + hourWindowsFromTimes(schedule, plan.hours.times, opts) + trailingQualifier(schedule, opts);
|
|
501
542
|
}
|
|
502
543
|
let phrase = stepCycle60(seg, units.minute, opts);
|
|
503
544
|
if (plan.hours.kind === "window") {
|
|
504
545
|
phrase += " " + hourWindow(plan.hours, opts);
|
|
505
546
|
} else if (plan.hours.kind === "step") {
|
|
506
|
-
phrase += " " + everyNthHour(stepSegment(
|
|
547
|
+
phrase += " " + everyNthHour(stepSegment(schedule, "hour"), opts);
|
|
507
548
|
}
|
|
508
|
-
return phrase + trailingQualifier(
|
|
549
|
+
return phrase + trailingQualifier(schedule, opts);
|
|
509
550
|
}
|
|
510
|
-
function renderMinuteSpanInHour(
|
|
511
|
-
if (
|
|
512
|
-
return "joka minuutti kello " + plan.hour + " aikana" + trailingQualifier(
|
|
551
|
+
function renderMinuteSpanInHour(schedule, plan, opts) {
|
|
552
|
+
if (schedule.pattern.minute === "*") {
|
|
553
|
+
return "joka minuutti kello " + plan.hour + " aikana" + trailingQualifier(schedule, opts);
|
|
513
554
|
}
|
|
514
555
|
return "joka minuutti " + kloRange(
|
|
515
556
|
{ hour: plan.hour, minute: plan.span[0] },
|
|
516
557
|
{ hour: plan.hour, minute: plan.span[1] },
|
|
517
558
|
opts
|
|
518
|
-
) + trailingQualifier(
|
|
559
|
+
) + trailingQualifier(schedule, opts);
|
|
519
560
|
}
|
|
520
|
-
function renderMinutesAcrossHours(
|
|
521
|
-
const cadence = unevenHourCadence(
|
|
561
|
+
function renderMinutesAcrossHours(schedule, plan, opts) {
|
|
562
|
+
const cadence = unevenHourCadence(schedule, opts);
|
|
522
563
|
if (plan.form === "wildcard") {
|
|
523
|
-
return cadence ? "joka minuutti, " + cadence + trailingQualifier(
|
|
564
|
+
return cadence ? "joka minuutti, " + cadence + trailingQualifier(schedule, opts) : "joka minuutti " + hourWindowsFromTimes(schedule, plan.times, opts) + trailingQualifier(schedule, opts);
|
|
524
565
|
}
|
|
525
566
|
if (cadence !== null) {
|
|
526
|
-
return bareMinutes(
|
|
567
|
+
return bareMinutes(schedule, opts) + ", " + cadence + trailingQualifier(schedule, opts);
|
|
527
568
|
}
|
|
528
|
-
if (hoursAreRangeIsolated(segmentsOf(
|
|
529
|
-
return bareMinutes(
|
|
569
|
+
if (hoursAreRangeIsolated(segmentsOf(schedule, "hour"))) {
|
|
570
|
+
return bareMinutes(schedule, opts) + " " + hourSegmentTimesWithSeka(schedule, 0, null, opts) + trailingQualifier(schedule, opts);
|
|
530
571
|
}
|
|
531
|
-
const hoursStr = kloFromTimes(
|
|
532
|
-
return hoursFirstMinutes(hoursStr,
|
|
572
|
+
const hoursStr = kloFromTimes(schedule, plan.times, opts);
|
|
573
|
+
return hoursFirstMinutes(hoursStr, schedule, opts) + trailingQualifier(schedule, opts);
|
|
533
574
|
}
|
|
534
|
-
function renderMinuteSpanAcrossHourStep(
|
|
535
|
-
const segment = stepSegment(
|
|
536
|
-
const cadence = unevenHourCadence(
|
|
575
|
+
function renderMinuteSpanAcrossHourStep(schedule, plan, opts) {
|
|
576
|
+
const segment = stepSegment(schedule, "hour");
|
|
577
|
+
const cadence = unevenHourCadence(schedule, opts);
|
|
537
578
|
if (plan.form === "wildcard") {
|
|
538
|
-
return "joka minuutti " + everyNthHour(segment, opts) + trailingQualifier(
|
|
579
|
+
return "joka minuutti " + everyNthHour(segment, opts) + trailingQualifier(schedule, opts);
|
|
539
580
|
}
|
|
540
581
|
if (cadence !== null) {
|
|
541
|
-
return bareMinutes(
|
|
582
|
+
return bareMinutes(schedule, opts) + ", " + cadence + trailingQualifier(schedule, opts);
|
|
542
583
|
}
|
|
543
|
-
return bareMinutes(
|
|
584
|
+
return bareMinutes(schedule, opts) + hourStepTail(segment, opts) + trailingQualifier(schedule, opts);
|
|
544
585
|
}
|
|
545
586
|
function plainHourStep(segment) {
|
|
546
587
|
return segment.startToken === "*" && 24 % segment.interval === 0;
|
|
@@ -589,35 +630,35 @@ function hourStepTail(segment, opts) {
|
|
|
589
630
|
const sep = plainHourStep(segment) ? " " : ", ";
|
|
590
631
|
return sep + plainOrFullHourStep(segment, opts);
|
|
591
632
|
}
|
|
592
|
-
function renderEveryHour(
|
|
593
|
-
return "joka tunti" + trailingQualifier(
|
|
633
|
+
function renderEveryHour(schedule, plan, opts) {
|
|
634
|
+
return "joka tunti" + trailingQualifier(schedule, opts);
|
|
594
635
|
}
|
|
595
|
-
function renderHourRange(
|
|
636
|
+
function renderHourRange(schedule, plan, opts) {
|
|
596
637
|
const window = hourWindow(boundedWindow(plan), opts);
|
|
597
638
|
if (plan.minuteForm === "wildcard") {
|
|
598
|
-
return "joka minuutti " + window + trailingQualifier(
|
|
639
|
+
return "joka minuutti " + window + trailingQualifier(schedule, opts);
|
|
599
640
|
}
|
|
600
641
|
if (plan.minuteForm === "range") {
|
|
601
|
-
return hoursFirstMinutes(window,
|
|
642
|
+
return hoursFirstMinutes(window, schedule, opts) + trailingQualifier(schedule, opts);
|
|
602
643
|
}
|
|
603
|
-
if (
|
|
604
|
-
return "joka tunti " + window + trailingQualifier(
|
|
644
|
+
if (schedule.pattern.minute === "0") {
|
|
645
|
+
return "joka tunti " + window + trailingQualifier(schedule, opts);
|
|
605
646
|
}
|
|
606
|
-
if (
|
|
607
|
-
return atMarks(
|
|
608
|
-
{ hour: plan.from, minute: +
|
|
647
|
+
if (schedule.shapes.minute === "single") {
|
|
648
|
+
return atMarks(schedule.pattern.minute, units.minute, false) + " " + kloRange(
|
|
649
|
+
{ hour: plan.from, minute: +schedule.pattern.minute },
|
|
609
650
|
{ hour: plan.to, minute: plan.last },
|
|
610
651
|
opts
|
|
611
|
-
) + trailingQualifier(
|
|
652
|
+
) + trailingQualifier(schedule, opts);
|
|
612
653
|
}
|
|
613
|
-
return hoursFirstMinutes(window,
|
|
654
|
+
return hoursFirstMinutes(window, schedule, opts) + trailingQualifier(schedule, opts);
|
|
614
655
|
}
|
|
615
|
-
function renderHourStep(
|
|
616
|
-
const cadence = unevenHourCadence(
|
|
656
|
+
function renderHourStep(schedule, plan, opts) {
|
|
657
|
+
const cadence = unevenHourCadence(schedule, opts);
|
|
617
658
|
if (cadence !== null) {
|
|
618
|
-
return cadence + trailingQualifier(
|
|
659
|
+
return cadence + trailingQualifier(schedule, opts);
|
|
619
660
|
}
|
|
620
|
-
return stepHours(stepSegment(
|
|
661
|
+
return stepHours(stepSegment(schedule, "hour"), opts) + trailingQualifier(schedule, opts);
|
|
621
662
|
}
|
|
622
663
|
function boundedWindow(plan) {
|
|
623
664
|
return { from: plan.from, last: plan.boundMinute ?? 0, to: plan.to };
|
|
@@ -629,53 +670,62 @@ function hourWindow(window, opts) {
|
|
|
629
670
|
opts
|
|
630
671
|
);
|
|
631
672
|
}
|
|
632
|
-
function renderClockTimes(
|
|
633
|
-
if (
|
|
634
|
-
const minute = +
|
|
635
|
-
const cadence = hourCadence(
|
|
673
|
+
function renderClockTimes(schedule, plan, opts) {
|
|
674
|
+
if (schedule.shapes.minute === "single") {
|
|
675
|
+
const minute = +schedule.pattern.minute;
|
|
676
|
+
const cadence = hourCadence(schedule, minute, opts) ?? hourRangeCadence(schedule, minute, opts);
|
|
636
677
|
if (cadence !== null) {
|
|
637
678
|
return cadence;
|
|
638
679
|
}
|
|
639
680
|
}
|
|
640
681
|
if (plan.times.length === 1) {
|
|
641
682
|
const time = plan.times[0];
|
|
642
|
-
return leadingQualifier(
|
|
683
|
+
return leadingQualifier(schedule, opts) + timeWord(time.hour, time.minute, time.second, opts);
|
|
643
684
|
}
|
|
644
685
|
const digits = plan.times.map(function clock(time) {
|
|
645
686
|
return timeDigits(time.hour, time.minute, time.second, opts);
|
|
646
687
|
});
|
|
647
|
-
return leadingQualifier(
|
|
688
|
+
return leadingQualifier(schedule, opts) + "klo " + joinList(digits);
|
|
648
689
|
}
|
|
649
|
-
function renderCompactClockTimes(
|
|
690
|
+
function renderCompactClockTimes(schedule, plan, opts) {
|
|
650
691
|
if (plan.fold) {
|
|
651
|
-
const cadence2 = hourCadence(
|
|
692
|
+
const cadence2 = hourCadence(schedule, plan.minute, opts) ?? hourRangeCadence(schedule, plan.minute, opts);
|
|
652
693
|
if (cadence2 !== null) {
|
|
653
694
|
return cadence2;
|
|
654
695
|
}
|
|
655
696
|
}
|
|
656
|
-
const hourSegs = segmentsOf(
|
|
697
|
+
const hourSegs = segmentsOf(schedule, "hour");
|
|
657
698
|
if (hoursAreRangeIsolated(hourSegs)) {
|
|
658
699
|
if (plan.fold) {
|
|
659
|
-
return leadingQualifier(
|
|
660
|
-
|
|
700
|
+
return leadingQualifier(schedule, opts) + hourSegmentTimesWithSeka(
|
|
701
|
+
schedule,
|
|
661
702
|
plan.minute,
|
|
662
|
-
|
|
703
|
+
schedule.analyses.clockSecond,
|
|
663
704
|
opts
|
|
664
705
|
);
|
|
665
706
|
}
|
|
666
|
-
const phrase2 = bareMinutes(
|
|
667
|
-
return
|
|
707
|
+
const phrase2 = bareMinutes(schedule, opts) + " " + hourSegmentTimesWithSeka(schedule, 0, null, opts) + trailingQualifier(schedule, opts);
|
|
708
|
+
return schedule.analyses.clockSecond ? secondsLeadClause(schedule, opts) + ", " + phrase2 : phrase2;
|
|
668
709
|
}
|
|
669
710
|
if (plan.fold) {
|
|
670
|
-
return leadingQualifier(
|
|
711
|
+
return leadingQualifier(schedule, opts) + hourSegmentTimes(
|
|
712
|
+
schedule,
|
|
713
|
+
plan.minute,
|
|
714
|
+
schedule.analyses.clockSecond,
|
|
715
|
+
opts
|
|
716
|
+
);
|
|
671
717
|
}
|
|
672
|
-
const cadence = unevenHourCadence(
|
|
673
|
-
const phrase = cadence ? bareMinutes(
|
|
718
|
+
const cadence = unevenHourCadence(schedule, opts);
|
|
719
|
+
const phrase = cadence ? bareMinutes(schedule, opts) + ", " + cadence + trailingQualifier(schedule, opts) : (
|
|
674
720
|
// A minute list over purely enumerated hours (step fires, all singles) —
|
|
675
721
|
// hours-first, drop "joka tunti".
|
|
676
|
-
hoursFirstMinutes(
|
|
722
|
+
hoursFirstMinutes(
|
|
723
|
+
hourSegmentTimes(schedule, 0, null, opts),
|
|
724
|
+
schedule,
|
|
725
|
+
opts
|
|
726
|
+
) + trailingQualifier(schedule, opts)
|
|
677
727
|
);
|
|
678
|
-
return
|
|
728
|
+
return schedule.analyses.clockSecond ? secondsLeadClause(schedule, opts) + ", " + phrase : phrase;
|
|
679
729
|
}
|
|
680
730
|
var renderers = {
|
|
681
731
|
clockTimes: renderClockTimes,
|
|
@@ -697,22 +747,19 @@ var renderers = {
|
|
|
697
747
|
singleMinute: renderSingleMinute,
|
|
698
748
|
standaloneSeconds: renderStandaloneSeconds
|
|
699
749
|
};
|
|
700
|
-
function
|
|
750
|
+
function renderStride2(stride, opts) {
|
|
701
751
|
const { interval, start, last, cycle, unit } = stride;
|
|
702
752
|
const cadence = genitive(interval, opts) + " " + unit.gen + " v\xE4lein";
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
return cadence + " " + unit.anchor + " " + unit.ela + " " + start + " alkaen";
|
|
709
|
-
}
|
|
710
|
-
return cadence + " " + unit.ela + " " + start + " " + unit.ill + " " + last;
|
|
753
|
+
return renderStride({ start, interval, cycle }, {
|
|
754
|
+
bare: () => cadence,
|
|
755
|
+
offset: () => cadence + " " + unit.anchor + " " + unit.ela + " " + start + " alkaen",
|
|
756
|
+
bounded: () => cadence + " " + unit.ela + " " + start + " " + unit.ill + " " + last
|
|
757
|
+
});
|
|
711
758
|
}
|
|
712
759
|
function strideFromSegments(segments, unit, opts) {
|
|
713
760
|
const values = singleValues(segments);
|
|
714
761
|
const step = values && arithmeticStep(values);
|
|
715
|
-
return step ?
|
|
762
|
+
return step ? renderStride2({ ...step, cycle: 60, unit }, opts) : null;
|
|
716
763
|
}
|
|
717
764
|
function stepCycle60(segment, unit, opts) {
|
|
718
765
|
if (segment.startToken.indexOf("-") !== -1) {
|
|
@@ -722,7 +769,7 @@ function stepCycle60(segment, unit, opts) {
|
|
|
722
769
|
if (start !== 0 && segment.fires.length <= 3) {
|
|
723
770
|
return atMarks(joinList(wordList(segment.fires)), unit, true);
|
|
724
771
|
}
|
|
725
|
-
return
|
|
772
|
+
return renderStride2({
|
|
726
773
|
interval: segment.interval,
|
|
727
774
|
start,
|
|
728
775
|
last: segment.fires[segment.fires.length - 1],
|
|
@@ -748,17 +795,14 @@ function stepHours(segment, opts) {
|
|
|
748
795
|
function hourStrideCadence(stride, opts) {
|
|
749
796
|
const { start, interval, last } = stride;
|
|
750
797
|
const cadence = genitive(interval, opts) + " tunnin v\xE4lein";
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
return cadence + " klo " + hourElatives[start] + " alkaen";
|
|
757
|
-
}
|
|
758
|
-
return cadence + " " + kloRange({ hour: start, minute: 0 }, { hour: last, minute: 0 }, opts);
|
|
798
|
+
return renderStride({ start, interval, cycle: 24 }, {
|
|
799
|
+
bare: () => cadence,
|
|
800
|
+
offset: () => cadence + " klo " + hourElatives[start] + " alkaen",
|
|
801
|
+
bounded: () => cadence + " " + kloRange({ hour: start, minute: 0 }, { hour: last, minute: 0 }, opts)
|
|
802
|
+
});
|
|
759
803
|
}
|
|
760
|
-
function hourStride(
|
|
761
|
-
const segments =
|
|
804
|
+
function hourStride(schedule) {
|
|
805
|
+
const segments = schedule.analyses.segments.hour;
|
|
762
806
|
if (!segments) {
|
|
763
807
|
return null;
|
|
764
808
|
}
|
|
@@ -773,47 +817,47 @@ function hourStride(ir) {
|
|
|
773
817
|
const values = singleValues(segments);
|
|
774
818
|
return values && hourListStride(values);
|
|
775
819
|
}
|
|
776
|
-
function unevenHourCadence(
|
|
777
|
-
const stride = hourStride(
|
|
820
|
+
function unevenHourCadence(schedule, opts) {
|
|
821
|
+
const stride = hourStride(schedule);
|
|
778
822
|
if (!stride || offsetCleanStride(stride)) {
|
|
779
823
|
return null;
|
|
780
824
|
}
|
|
781
825
|
return hourStrideCadence(stride, opts);
|
|
782
826
|
}
|
|
783
|
-
function subMinuteSecond(
|
|
784
|
-
return
|
|
827
|
+
function subMinuteSecond(schedule) {
|
|
828
|
+
return schedule.pattern.second === "*" || schedule.shapes.second === "step";
|
|
785
829
|
}
|
|
786
|
-
function hourCadenceLead(
|
|
830
|
+
function hourCadenceLead(schedule, minute, opts) {
|
|
787
831
|
if (minute === 0) {
|
|
788
|
-
if (subMinuteSecond(
|
|
789
|
-
return secondsLeadClause(
|
|
832
|
+
if (subMinuteSecond(schedule)) {
|
|
833
|
+
return secondsLeadClause(schedule, opts) + " minuutin ajan";
|
|
790
834
|
}
|
|
791
|
-
return secondsLeadClause(
|
|
835
|
+
return secondsLeadClause(schedule, opts);
|
|
792
836
|
}
|
|
793
837
|
const minutePhrase = atMarks(String(minute), units.minute, false);
|
|
794
|
-
if (
|
|
838
|
+
if (schedule.pattern.second === "0") {
|
|
795
839
|
return minutePhrase;
|
|
796
840
|
}
|
|
797
|
-
return secondsLeadClause(
|
|
841
|
+
return secondsLeadClause(schedule, opts) + ", " + minutePhrase;
|
|
798
842
|
}
|
|
799
|
-
function hourCadence(
|
|
800
|
-
const stride = hourStride(
|
|
843
|
+
function hourCadence(schedule, minute, opts) {
|
|
844
|
+
const stride = hourStride(schedule);
|
|
801
845
|
if (!stride) {
|
|
802
846
|
return null;
|
|
803
847
|
}
|
|
804
848
|
const fires = (stride.last - stride.start) / stride.interval + 1;
|
|
805
|
-
if (
|
|
849
|
+
if (schedule.pattern.second === "0" && fires <= maxClockTimes && offsetCleanStride(stride)) {
|
|
806
850
|
return null;
|
|
807
851
|
}
|
|
808
|
-
const segment = segmentsOf(
|
|
809
|
-
const confined = minute === 0 && subMinuteSecond(
|
|
852
|
+
const segment = segmentsOf(schedule, "hour")[0];
|
|
853
|
+
const confined = minute === 0 && subMinuteSecond(schedule) && segmentsOf(schedule, "hour").length === 1 && segment.kind === "step" && cleanHourStride(segment);
|
|
810
854
|
if (confined) {
|
|
811
|
-
return secondsLeadClause(
|
|
855
|
+
return secondsLeadClause(schedule, opts) + " minuutin ajan " + everyNthHour(segment, opts) + trailingQualifier(schedule, opts);
|
|
812
856
|
}
|
|
813
|
-
if (minute === 0 &&
|
|
814
|
-
return hourStrideCadence(stride, opts) + trailingQualifier(
|
|
857
|
+
if (minute === 0 && schedule.pattern.second === "0") {
|
|
858
|
+
return hourStrideCadence(stride, opts) + trailingQualifier(schedule, opts);
|
|
815
859
|
}
|
|
816
|
-
return hourCadenceLead(
|
|
860
|
+
return hourCadenceLead(schedule, minute, opts) + ", " + hourStrideCadence(stride, opts) + trailingQualifier(schedule, opts);
|
|
817
861
|
}
|
|
818
862
|
function cleanHourStride(segment) {
|
|
819
863
|
if (segment.startToken.indexOf("-") !== -1) {
|
|
@@ -822,22 +866,22 @@ function cleanHourStride(segment) {
|
|
|
822
866
|
const start = segment.startToken === "*" ? 0 : +segment.startToken;
|
|
823
867
|
return 24 % segment.interval === 0 && start < segment.interval;
|
|
824
868
|
}
|
|
825
|
-
function hasHourWindow(
|
|
826
|
-
const segments =
|
|
869
|
+
function hasHourWindow(schedule) {
|
|
870
|
+
const segments = schedule.analyses.segments.hour;
|
|
827
871
|
return !!segments && segments.some(function range(segment) {
|
|
828
872
|
return segment.kind === "range";
|
|
829
873
|
});
|
|
830
874
|
}
|
|
831
|
-
function hourRangeWindowTail(
|
|
832
|
-
return segmentsOf(
|
|
875
|
+
function hourRangeWindowTail(schedule, opts) {
|
|
876
|
+
return segmentsOf(schedule, "hour").length === 1 ? hourSegmentTimes(schedule, 0, null, opts) : hourSegmentTimesWithSeka(schedule, 0, null, opts);
|
|
833
877
|
}
|
|
834
|
-
function hourRangeCadence(
|
|
835
|
-
if (minute !== 0 || !hasHourWindow(
|
|
878
|
+
function hourRangeCadence(schedule, minute, opts) {
|
|
879
|
+
if (minute !== 0 || !hasHourWindow(schedule) || schedule.pattern.second === "0") {
|
|
836
880
|
return null;
|
|
837
881
|
}
|
|
838
|
-
const tail = hourRangeWindowTail(
|
|
839
|
-
const joiner = subMinuteSecond(
|
|
840
|
-
return hourCadenceLead(
|
|
882
|
+
const tail = hourRangeWindowTail(schedule, opts);
|
|
883
|
+
const joiner = subMinuteSecond(schedule) ? " " : ", ";
|
|
884
|
+
return hourCadenceLead(schedule, minute, opts) + joiner + tail + trailingQualifier(schedule, opts);
|
|
841
885
|
}
|
|
842
886
|
function kloList(hours, opts) {
|
|
843
887
|
if (hours.length === 1) {
|
|
@@ -847,17 +891,17 @@ function kloList(hours, opts) {
|
|
|
847
891
|
return timeDigits(hour, 0, null, opts);
|
|
848
892
|
}));
|
|
849
893
|
}
|
|
850
|
-
function kloFromTimes(
|
|
894
|
+
function kloFromTimes(schedule, times, opts) {
|
|
851
895
|
if (times.kind === "fires") {
|
|
852
896
|
return kloList(times.fires, opts);
|
|
853
897
|
}
|
|
854
|
-
return hourSegmentTimes(
|
|
898
|
+
return hourSegmentTimes(schedule, 0, null, opts);
|
|
855
899
|
}
|
|
856
|
-
function hourWindowsFromTimes(
|
|
900
|
+
function hourWindowsFromTimes(schedule, times, opts) {
|
|
857
901
|
if (times.kind === "fires") {
|
|
858
902
|
return kloList(times.fires, opts);
|
|
859
903
|
}
|
|
860
|
-
const segments = segmentsOf(
|
|
904
|
+
const segments = segmentsOf(schedule, "hour");
|
|
861
905
|
if (!segments.some(function ranged(segment) {
|
|
862
906
|
return segment.kind === "range";
|
|
863
907
|
})) {
|
|
@@ -895,9 +939,9 @@ function hourSegmentFires(segments) {
|
|
|
895
939
|
function hourWindowDigits(hour, opts) {
|
|
896
940
|
return rangeDigits({ hour, minute: 0 }, { hour, minute: 59 }, opts);
|
|
897
941
|
}
|
|
898
|
-
function hourSegmentTimes(
|
|
942
|
+
function hourSegmentTimes(schedule, minute, second, opts) {
|
|
899
943
|
const pieces = [];
|
|
900
|
-
segmentsOf(
|
|
944
|
+
segmentsOf(schedule, "hour").forEach(function clock(segment) {
|
|
901
945
|
if (segment.kind === "step") {
|
|
902
946
|
pieces.push(...segment.fires.map(function each(hour) {
|
|
903
947
|
return timeDigits(hour, minute, second, opts);
|
|
@@ -947,53 +991,54 @@ function timeDigits(hour, minute, second, opts) {
|
|
|
947
991
|
{ lean: true, sep: opts.style.sep }
|
|
948
992
|
);
|
|
949
993
|
}
|
|
950
|
-
function leadingQualifier(
|
|
951
|
-
const pattern =
|
|
952
|
-
if (restrictedMonthUnion(
|
|
994
|
+
function leadingQualifier(schedule, opts) {
|
|
995
|
+
const pattern = schedule.pattern;
|
|
996
|
+
if (restrictedMonthUnion(schedule)) {
|
|
953
997
|
return "";
|
|
954
998
|
}
|
|
955
999
|
if (pattern.date !== "*" && pattern.weekday !== "*") {
|
|
956
|
-
return dateOrWeekday(
|
|
1000
|
+
return dateOrWeekday(schedule, opts) + " ";
|
|
957
1001
|
}
|
|
958
1002
|
if (pattern.date !== "*") {
|
|
959
|
-
return datePhrase(
|
|
1003
|
+
return datePhrase(schedule, opts) + " ";
|
|
960
1004
|
}
|
|
961
1005
|
if (pattern.weekday !== "*") {
|
|
962
|
-
return weekdayQualifier(
|
|
1006
|
+
return weekdayQualifier(schedule) + monthScope(schedule) + " ";
|
|
963
1007
|
}
|
|
964
1008
|
if (pattern.month !== "*") {
|
|
965
|
-
return "joka p\xE4iv\xE4 " + monthPhrase(
|
|
1009
|
+
return "joka p\xE4iv\xE4 " + monthPhrase(schedule) + " ";
|
|
966
1010
|
}
|
|
967
1011
|
return "joka p\xE4iv\xE4 ";
|
|
968
1012
|
}
|
|
969
|
-
function trailingQualifier(
|
|
970
|
-
const pattern =
|
|
971
|
-
if (restrictedMonthUnion(
|
|
1013
|
+
function trailingQualifier(schedule, opts) {
|
|
1014
|
+
const pattern = schedule.pattern;
|
|
1015
|
+
if (restrictedMonthUnion(schedule)) {
|
|
972
1016
|
return "";
|
|
973
1017
|
}
|
|
974
1018
|
if (pattern.date !== "*" && pattern.weekday !== "*") {
|
|
975
|
-
return " " + dateOrWeekday(
|
|
1019
|
+
return " " + dateOrWeekday(schedule, opts);
|
|
976
1020
|
}
|
|
977
1021
|
if (pattern.date !== "*") {
|
|
978
|
-
return " " + datePhrase(
|
|
1022
|
+
return " " + datePhrase(schedule, opts);
|
|
979
1023
|
}
|
|
980
1024
|
if (pattern.weekday !== "*") {
|
|
981
|
-
return " " + weekdayQualifier(
|
|
1025
|
+
return " " + weekdayQualifier(schedule) + monthScope(schedule);
|
|
982
1026
|
}
|
|
983
1027
|
if (pattern.month !== "*") {
|
|
984
|
-
return " " + monthPhrase(
|
|
1028
|
+
return " " + monthPhrase(schedule);
|
|
985
1029
|
}
|
|
986
1030
|
return "";
|
|
987
1031
|
}
|
|
988
|
-
function dateOrWeekday(
|
|
989
|
-
|
|
1032
|
+
function dateOrWeekday(schedule, opts) {
|
|
1033
|
+
const dateArm = oddDayUnion(schedule.pattern.date) || datePhrase(schedule, opts);
|
|
1034
|
+
return dateArm + " tai " + unionWeekdayArm(schedule) + monthScope(schedule);
|
|
990
1035
|
}
|
|
991
|
-
function weekdayQualifier(
|
|
992
|
-
const quartz = quartzWeekdayPhrase(
|
|
1036
|
+
function weekdayQualifier(schedule) {
|
|
1037
|
+
const quartz = quartzWeekdayPhrase(schedule.pattern.weekday);
|
|
993
1038
|
if (quartz) {
|
|
994
1039
|
return quartz;
|
|
995
1040
|
}
|
|
996
|
-
const segments = orderWeekdaysForDisplay(segmentsOf(
|
|
1041
|
+
const segments = orderWeekdaysForDisplay(segmentsOf(schedule, "weekday"));
|
|
997
1042
|
return joinList(segments.map(function piece(segment) {
|
|
998
1043
|
if (segment.kind === "range") {
|
|
999
1044
|
return weekdays[weekdayNumber(segment.bounds[0])].ela + " " + weekdays[weekdayNumber(segment.bounds[1])].ill;
|
|
@@ -1001,8 +1046,8 @@ function weekdayQualifier(ir) {
|
|
|
1001
1046
|
return weekdays[weekdayNumber(segment.value)].isin;
|
|
1002
1047
|
}));
|
|
1003
1048
|
}
|
|
1004
|
-
function monthPhrase(
|
|
1005
|
-
const segments = flattenSteps(segmentsOf(
|
|
1049
|
+
function monthPhrase(schedule) {
|
|
1050
|
+
const segments = flattenSteps(segmentsOf(schedule, "month"));
|
|
1006
1051
|
return joinList(segments.map(function piece(segment) {
|
|
1007
1052
|
if (segment.kind === "range") {
|
|
1008
1053
|
return monthStems[monthNumber(segment.bounds[0])] + "kuusta " + monthStems[monthNumber(segment.bounds[1])] + "kuuhun";
|
|
@@ -1010,11 +1055,11 @@ function monthPhrase(ir) {
|
|
|
1010
1055
|
return monthStems[monthNumber(segment.value)] + "kuussa";
|
|
1011
1056
|
}));
|
|
1012
1057
|
}
|
|
1013
|
-
function monthScope(
|
|
1014
|
-
if (
|
|
1058
|
+
function monthScope(schedule) {
|
|
1059
|
+
if (schedule.pattern.month === "*") {
|
|
1015
1060
|
return "";
|
|
1016
1061
|
}
|
|
1017
|
-
return " " + monthPhrase(
|
|
1062
|
+
return " " + monthPhrase(schedule);
|
|
1018
1063
|
}
|
|
1019
1064
|
function flattenSteps(segments) {
|
|
1020
1065
|
return segments.flatMap(function flat(segment) {
|
|
@@ -1023,16 +1068,16 @@ function flattenSteps(segments) {
|
|
|
1023
1068
|
}) : [segment];
|
|
1024
1069
|
});
|
|
1025
1070
|
}
|
|
1026
|
-
function datePhrase(
|
|
1027
|
-
const pattern =
|
|
1071
|
+
function datePhrase(schedule, opts) {
|
|
1072
|
+
const pattern = schedule.pattern;
|
|
1028
1073
|
const quartz = quartzDatePhrase(pattern.date);
|
|
1029
1074
|
if (quartz) {
|
|
1030
|
-
return quartz + monthScope(
|
|
1075
|
+
return quartz + monthScope(schedule);
|
|
1031
1076
|
}
|
|
1032
1077
|
if (isOpenStep(pattern.date)) {
|
|
1033
|
-
return stepDates(pattern.date, opts) + monthScope(
|
|
1078
|
+
return stepDates(pattern.date, opts) + monthScope(schedule);
|
|
1034
1079
|
}
|
|
1035
|
-
return monthAnchor(
|
|
1080
|
+
return monthAnchor(schedule, opts) + " " + dateWords(schedule) + " p\xE4iv\xE4n\xE4" + foldedYear(schedule) + monthStepStart(pattern.month) + rangedMonthScope(schedule);
|
|
1036
1081
|
}
|
|
1037
1082
|
function monthStepStart(monthField) {
|
|
1038
1083
|
if (!isOpenStep(monthField)) {
|
|
@@ -1044,30 +1089,30 @@ function monthStepStart(monthField) {
|
|
|
1044
1089
|
}
|
|
1045
1090
|
return " " + monthStems[monthNumber(start)] + "kuusta alkaen";
|
|
1046
1091
|
}
|
|
1047
|
-
function monthAnchor(
|
|
1048
|
-
const monthField =
|
|
1049
|
-
if (monthField === "*" || monthRanged(
|
|
1092
|
+
function monthAnchor(schedule, opts) {
|
|
1093
|
+
const monthField = schedule.pattern.month;
|
|
1094
|
+
if (monthField === "*" || monthRanged(schedule)) {
|
|
1050
1095
|
return "kuukauden";
|
|
1051
1096
|
}
|
|
1052
1097
|
if (isOpenStep(monthField)) {
|
|
1053
1098
|
return stepMonths(monthField, opts);
|
|
1054
1099
|
}
|
|
1055
|
-
const segments = flattenSteps(segmentsOf(
|
|
1100
|
+
const segments = flattenSteps(segmentsOf(schedule, "month"));
|
|
1056
1101
|
return joinList(segments.map(function genitiveOf(segment) {
|
|
1057
1102
|
const single = segment;
|
|
1058
1103
|
return monthStems[monthNumber(single.value)] + "kuun";
|
|
1059
1104
|
}));
|
|
1060
1105
|
}
|
|
1061
|
-
function rangedMonthScope(
|
|
1062
|
-
return monthRanged(
|
|
1106
|
+
function rangedMonthScope(schedule) {
|
|
1107
|
+
return monthRanged(schedule) ? " " + monthPhrase(schedule) : "";
|
|
1063
1108
|
}
|
|
1064
|
-
function monthRanged(
|
|
1065
|
-
return
|
|
1109
|
+
function monthRanged(schedule) {
|
|
1110
|
+
return schedule.pattern.month !== "*" && segmentsOf(schedule, "month").some(function range(segment) {
|
|
1066
1111
|
return segment.kind === "range";
|
|
1067
1112
|
});
|
|
1068
1113
|
}
|
|
1069
|
-
function dateWords(
|
|
1070
|
-
return joinList(segmentsOf(
|
|
1114
|
+
function dateWords(schedule) {
|
|
1115
|
+
return joinList(segmentsOf(schedule, "date").flatMap(
|
|
1071
1116
|
function word(segment) {
|
|
1072
1117
|
if (segment.kind === "range") {
|
|
1073
1118
|
return [segment.bounds[0] + ".\u2013" + segment.bounds[1] + "."];
|
|
@@ -1123,15 +1168,15 @@ function weekdayNumber(token) {
|
|
|
1123
1168
|
function monthNumber(token) {
|
|
1124
1169
|
return +token;
|
|
1125
1170
|
}
|
|
1126
|
-
function applyYear(description,
|
|
1127
|
-
const yearField =
|
|
1171
|
+
function applyYear(description, schedule, opts) {
|
|
1172
|
+
const yearField = schedule.pattern.year;
|
|
1128
1173
|
if (yearField === "*") {
|
|
1129
1174
|
return description;
|
|
1130
1175
|
}
|
|
1131
1176
|
if (yearField.indexOf("/") !== -1) {
|
|
1132
1177
|
return description + " " + stepYears(yearField, opts);
|
|
1133
1178
|
}
|
|
1134
|
-
if (foldedYear(
|
|
1179
|
+
if (foldedYear(schedule) && schedule.pattern.date !== "*") {
|
|
1135
1180
|
return description;
|
|
1136
1181
|
}
|
|
1137
1182
|
if (yearField.indexOf(",") !== -1) {
|
|
@@ -1151,8 +1196,8 @@ function stepYears(yearField, opts) {
|
|
|
1151
1196
|
}
|
|
1152
1197
|
return phrase;
|
|
1153
1198
|
}
|
|
1154
|
-
function foldedYear(
|
|
1155
|
-
const yearField =
|
|
1199
|
+
function foldedYear(schedule) {
|
|
1200
|
+
const yearField = schedule.pattern.year;
|
|
1156
1201
|
if (yearField === "*" || yearField.indexOf("/") !== -1 || yearField.indexOf("-") !== -1 || yearField.indexOf(",") !== -1) {
|
|
1157
1202
|
return "";
|
|
1158
1203
|
}
|