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.js
CHANGED
|
@@ -31,6 +31,16 @@ function isNonNegativeInteger(value) {
|
|
|
31
31
|
const digits = /^\d+$/;
|
|
32
32
|
return digits.test(value);
|
|
33
33
|
}
|
|
34
|
+
function toFieldNumber(token, numberMap) {
|
|
35
|
+
return isNonNegativeInteger(token) ? +token : numberMap[token.toUpperCase()];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// src/core/shapes.ts
|
|
39
|
+
function isOpenStep(field) {
|
|
40
|
+
return field.indexOf("/") !== -1 && field.indexOf("-") === -1 && field.indexOf(",") === -1;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// src/core/cadence.ts
|
|
34
44
|
function arithmeticStep(values) {
|
|
35
45
|
if (values.length < 5) {
|
|
36
46
|
return null;
|
|
@@ -46,34 +56,11 @@ function arithmeticStep(values) {
|
|
|
46
56
|
}
|
|
47
57
|
return { start: values[0], interval, last: values[values.length - 1] };
|
|
48
58
|
}
|
|
49
|
-
function
|
|
50
|
-
return
|
|
51
|
-
}
|
|
52
|
-
function orderWeekdaysForDisplay(segments) {
|
|
53
|
-
const flattened = segments.flatMap(function flat(segment) {
|
|
54
|
-
return segment.kind === "step" ? segment.fires.map(function single(value) {
|
|
55
|
-
return { kind: "single", value: "" + value };
|
|
56
|
-
}) : [segment];
|
|
57
|
-
});
|
|
58
|
-
function key(segment) {
|
|
59
|
-
return segment.kind === "range" ? weekdayDisplayKey(+segment.bounds[0]) : weekdayDisplayKey(+segment.value);
|
|
60
|
-
}
|
|
61
|
-
return flattened.map(function index(segment, position) {
|
|
62
|
-
return [segment, position];
|
|
63
|
-
}).sort(function byDisplayKey(a, b) {
|
|
64
|
-
return key(a[0]) - key(b[0]) || a[1] - b[1];
|
|
65
|
-
}).map(function unwrap(pair) {
|
|
66
|
-
return pair[0];
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
function toFieldNumber(token, numberMap) {
|
|
70
|
-
return isNonNegativeInteger(token) ? +token : numberMap[token.toUpperCase()];
|
|
59
|
+
function segmentsOf(schedule, field) {
|
|
60
|
+
return schedule.analyses.segments[field] ?? [];
|
|
71
61
|
}
|
|
72
|
-
function
|
|
73
|
-
return
|
|
74
|
-
}
|
|
75
|
-
function stepSegment(ir, field) {
|
|
76
|
-
return segmentsOf(ir, field)[0];
|
|
62
|
+
function stepSegment(schedule, field) {
|
|
63
|
+
return segmentsOf(schedule, field)[0];
|
|
77
64
|
}
|
|
78
65
|
function singleValues(segments) {
|
|
79
66
|
const values = [];
|
|
@@ -88,6 +75,17 @@ function singleValues(segments) {
|
|
|
88
75
|
function offsetCleanStride(stride) {
|
|
89
76
|
return stride.start < stride.interval && 24 % stride.interval === 0;
|
|
90
77
|
}
|
|
78
|
+
function renderStride(spec, parts) {
|
|
79
|
+
const { start, interval, cycle } = spec;
|
|
80
|
+
const tiles = cycle % interval === 0;
|
|
81
|
+
if (start === 0 && tiles) {
|
|
82
|
+
return parts.bare();
|
|
83
|
+
}
|
|
84
|
+
if (start < interval && tiles) {
|
|
85
|
+
return parts.offset();
|
|
86
|
+
}
|
|
87
|
+
return parts.bounded();
|
|
88
|
+
}
|
|
91
89
|
function hourListStride(values) {
|
|
92
90
|
if (values.length < 2) {
|
|
93
91
|
return null;
|
|
@@ -107,9 +105,26 @@ function hourListStride(values) {
|
|
|
107
105
|
return { interval, last: values[values.length - 1], start: values[0] };
|
|
108
106
|
}
|
|
109
107
|
|
|
110
|
-
// src/core/
|
|
111
|
-
function
|
|
112
|
-
return
|
|
108
|
+
// src/core/weekday.ts
|
|
109
|
+
function weekdayDisplayKey(value) {
|
|
110
|
+
return value === 0 ? 7 : value;
|
|
111
|
+
}
|
|
112
|
+
function orderWeekdaysForDisplay(segments) {
|
|
113
|
+
const flattened = segments.flatMap(function flat(segment) {
|
|
114
|
+
return segment.kind === "step" ? segment.fires.map(function single(value) {
|
|
115
|
+
return { kind: "single", value: "" + value };
|
|
116
|
+
}) : [segment];
|
|
117
|
+
});
|
|
118
|
+
function key(segment) {
|
|
119
|
+
return segment.kind === "range" ? weekdayDisplayKey(+segment.bounds[0]) : weekdayDisplayKey(+segment.value);
|
|
120
|
+
}
|
|
121
|
+
return flattened.map(function index(segment, position) {
|
|
122
|
+
return [segment, position];
|
|
123
|
+
}).sort(function byDisplayKey(a, b) {
|
|
124
|
+
return key(a[0]) - key(b[0]) || a[1] - b[1];
|
|
125
|
+
}).map(function unwrap(pair) {
|
|
126
|
+
return pair[0];
|
|
127
|
+
});
|
|
113
128
|
}
|
|
114
129
|
|
|
115
130
|
// src/lang/fi/dialects.ts
|
|
@@ -266,94 +281,108 @@ function normalizeOptions(options) {
|
|
|
266
281
|
years: !!options.years
|
|
267
282
|
};
|
|
268
283
|
}
|
|
269
|
-
function restrictedMonthUnion(
|
|
270
|
-
return
|
|
284
|
+
function restrictedMonthUnion(schedule) {
|
|
285
|
+
return schedule.pattern.date !== "*" && schedule.pattern.weekday !== "*" && schedule.pattern.month !== "*";
|
|
271
286
|
}
|
|
272
|
-
function
|
|
273
|
-
|
|
287
|
+
function oddDayUnion(dateField) {
|
|
288
|
+
if (!isOpenStep(dateField)) {
|
|
289
|
+
return null;
|
|
290
|
+
}
|
|
291
|
+
const [start, step] = dateField.split("/");
|
|
292
|
+
return (start === "*" || start === "1") && +step === 2 ? "kuukauden parittomina p\xE4ivin\xE4" : null;
|
|
293
|
+
}
|
|
294
|
+
function unionDateArm(schedule) {
|
|
295
|
+
return quartzDatePhrase(schedule.pattern.date) || oddDayUnion(schedule.pattern.date) || dateWords(schedule) + " p\xE4iv\xE4n\xE4";
|
|
274
296
|
}
|
|
275
|
-
function
|
|
276
|
-
|
|
277
|
-
|
|
297
|
+
function unionWeekdayArm(schedule) {
|
|
298
|
+
const segments = segmentsOf(schedule, "weekday");
|
|
299
|
+
if (segments.length === 1 && segments[0].kind === "range" && segments[0].bounds[0] === "1" && segments[0].bounds[1] === "5") {
|
|
300
|
+
return "arkisin";
|
|
301
|
+
}
|
|
302
|
+
return weekdayQualifier(schedule);
|
|
303
|
+
}
|
|
304
|
+
function describe(schedule, opts) {
|
|
305
|
+
if (restrictedMonthUnion(schedule)) {
|
|
306
|
+
const timePart = render(schedule, schedule.plan, opts);
|
|
278
307
|
return applyYear(
|
|
279
|
-
monthPhrase(
|
|
280
|
-
|
|
308
|
+
monthPhrase(schedule) + " " + timePart + " " + unionDateArm(schedule) + " tai " + unionWeekdayArm(schedule),
|
|
309
|
+
schedule,
|
|
281
310
|
opts
|
|
282
311
|
);
|
|
283
312
|
}
|
|
284
|
-
return applyYear(render(
|
|
313
|
+
return applyYear(render(schedule, schedule.plan, opts), schedule, opts);
|
|
285
314
|
}
|
|
286
|
-
function render(
|
|
315
|
+
function render(schedule, plan, opts) {
|
|
287
316
|
const renderer = renderers[plan.kind];
|
|
288
|
-
return renderer(
|
|
317
|
+
return renderer(schedule, plan, opts);
|
|
289
318
|
}
|
|
290
|
-
function renderEverySecond(
|
|
291
|
-
return "joka sekunti" + trailingQualifier(
|
|
319
|
+
function renderEverySecond(schedule, plan, opts) {
|
|
320
|
+
return "joka sekunti" + trailingQualifier(schedule, opts);
|
|
292
321
|
}
|
|
293
|
-
function renderStandaloneSeconds(
|
|
294
|
-
return secondsLeadClause(
|
|
322
|
+
function renderStandaloneSeconds(schedule, plan, opts) {
|
|
323
|
+
return secondsLeadClause(schedule, opts) + trailingQualifier(schedule, opts);
|
|
295
324
|
}
|
|
296
|
-
function renderSecondPastMinute(
|
|
297
|
-
return atMarks(
|
|
325
|
+
function renderSecondPastMinute(schedule, plan, opts) {
|
|
326
|
+
return atMarks(schedule.pattern.second, units.second, true) + trailingQualifier(schedule, opts);
|
|
298
327
|
}
|
|
299
|
-
function renderSecondsWithinMinute(
|
|
300
|
-
const minuteField =
|
|
328
|
+
function renderSecondsWithinMinute(schedule, plan, opts) {
|
|
329
|
+
const minuteField = schedule.pattern.minute;
|
|
301
330
|
if (plan.singleSecond) {
|
|
302
|
-
return units.minute.mark + " " + minuteField + " " + units.minute.gen + " ja " +
|
|
331
|
+
return units.minute.mark + " " + minuteField + " " + units.minute.gen + " ja " + schedule.pattern.second + " " + units.second.gen + " kohdalla" + trailingQualifier(schedule, opts);
|
|
303
332
|
}
|
|
304
|
-
return secondsLeadClause(
|
|
333
|
+
return secondsLeadClause(schedule, opts) + ", " + atMarks(minuteField, units.minute, true) + trailingQualifier(schedule, opts);
|
|
305
334
|
}
|
|
306
|
-
function composeSecondsOverMinuteStep(
|
|
307
|
-
const seg = stepSegment(
|
|
335
|
+
function composeSecondsOverMinuteStep(schedule, freq, opts) {
|
|
336
|
+
const seg = stepSegment(schedule, "minute");
|
|
308
337
|
const stepPhrase = stepCycle60(seg, units.minute, opts);
|
|
309
338
|
if (freq.hours.kind === "during" && minuteStepIsAnchored(seg)) {
|
|
310
|
-
const bareHours = kloFromTimes(
|
|
311
|
-
return hoursFirstMinutes(bareHours,
|
|
339
|
+
const bareHours = kloFromTimes(schedule, freq.hours.times, opts);
|
|
340
|
+
return hoursFirstMinutes(bareHours, schedule, opts) + ", " + secondsLeadClause(schedule, opts) + trailingQualifier(schedule, opts);
|
|
312
341
|
}
|
|
313
342
|
let hourClause = "";
|
|
314
343
|
if (freq.hours.kind === "during") {
|
|
315
|
-
hourClause = " " + hourWindowsFromTimes(
|
|
344
|
+
hourClause = " " + hourWindowsFromTimes(schedule, freq.hours.times, opts);
|
|
316
345
|
} else if (freq.hours.kind === "window") {
|
|
317
346
|
hourClause = " " + hourWindow(freq.hours, opts);
|
|
318
347
|
} else if (freq.hours.kind === "step") {
|
|
319
|
-
hourClause = " " + everyNthHour(stepSegment(
|
|
348
|
+
hourClause = " " + everyNthHour(stepSegment(schedule, "hour"), opts);
|
|
320
349
|
}
|
|
321
|
-
return stepPhrase + ", " + secondsLeadClause(
|
|
350
|
+
return stepPhrase + ", " + secondsLeadClause(schedule, opts) + hourClause + trailingQualifier(schedule, opts);
|
|
322
351
|
}
|
|
323
|
-
function composeHourCadence(
|
|
352
|
+
function composeHourCadence(schedule, plan, opts) {
|
|
324
353
|
const clockRest = plan.rest.kind === "clockTimes" || plan.rest.kind === "compactClockTimes";
|
|
325
|
-
if (!clockRest ||
|
|
354
|
+
if (!clockRest || schedule.shapes.minute !== "single") {
|
|
326
355
|
return null;
|
|
327
356
|
}
|
|
328
|
-
const minute = +
|
|
329
|
-
return hourCadence(
|
|
357
|
+
const minute = +schedule.pattern.minute;
|
|
358
|
+
return hourCadence(schedule, minute, opts) ?? hourRangeCadence(schedule, minute, opts);
|
|
330
359
|
}
|
|
331
|
-
function renderComposeSeconds(
|
|
332
|
-
const cadence = composeHourCadence(
|
|
360
|
+
function renderComposeSeconds(schedule, plan, opts) {
|
|
361
|
+
const cadence = composeHourCadence(schedule, plan, opts);
|
|
333
362
|
if (cadence !== null) {
|
|
334
363
|
return cadence;
|
|
335
364
|
}
|
|
336
|
-
if (plan.rest.kind === "minuteFrequency" &&
|
|
337
|
-
return composeSecondsOverMinuteStep(
|
|
365
|
+
if (plan.rest.kind === "minuteFrequency" && schedule.pattern.second !== "*") {
|
|
366
|
+
return composeSecondsOverMinuteStep(schedule, plan.rest, opts);
|
|
338
367
|
}
|
|
339
368
|
if (plan.rest.kind === "clockTimes" && plan.rest.times.every((time) => +time.minute === 0)) {
|
|
340
|
-
return composeMinuteZero(
|
|
369
|
+
return composeMinuteZero(schedule, plan.rest, opts);
|
|
341
370
|
}
|
|
342
|
-
if (isEveryOtherMinuteSeconds(
|
|
343
|
-
return secondsLeadClause(
|
|
371
|
+
if (isEveryOtherMinuteSeconds(schedule, plan)) {
|
|
372
|
+
return secondsLeadClause(schedule, opts) + " joka toisena minuuttina";
|
|
344
373
|
}
|
|
345
|
-
const restOwnsLead = plan.rest.kind === "compactClockTimes" &&
|
|
346
|
-
const lead = restOwnsLead ? "" : secondsLeadClause(
|
|
347
|
-
return lead + render(
|
|
374
|
+
const restOwnsLead = plan.rest.kind === "compactClockTimes" && schedule.analyses.clockSecond;
|
|
375
|
+
const lead = restOwnsLead ? "" : secondsLeadClause(schedule, opts) + ", ";
|
|
376
|
+
return lead + render(schedule, plan.rest, opts);
|
|
348
377
|
}
|
|
349
|
-
function isEveryOtherMinuteSeconds(
|
|
350
|
-
if (plan.rest.kind !== "minuteFrequency" ||
|
|
378
|
+
function isEveryOtherMinuteSeconds(schedule, plan) {
|
|
379
|
+
if (plan.rest.kind !== "minuteFrequency" || schedule.pattern.second !== "*" || schedule.shapes.hour !== "wildcard") {
|
|
351
380
|
return false;
|
|
352
381
|
}
|
|
353
|
-
const seg = stepSegment(
|
|
382
|
+
const seg = stepSegment(schedule, "minute");
|
|
354
383
|
return seg.startToken === "*" && seg.interval === 2;
|
|
355
384
|
}
|
|
356
|
-
function composeMinuteZero(
|
|
385
|
+
function composeMinuteZero(schedule, rest, opts) {
|
|
357
386
|
const clocks = rest.times.map(function clock(time) {
|
|
358
387
|
return clockDigits(
|
|
359
388
|
{ hour: time.hour, minute: time.minute },
|
|
@@ -361,54 +390,66 @@ function composeMinuteZero(ir, rest, opts) {
|
|
|
361
390
|
);
|
|
362
391
|
});
|
|
363
392
|
const frame = clocks.length === 1 ? "minuutin " + clocks[0] : "minuuttien " + joinList(clocks);
|
|
364
|
-
const dayTrail = leadingQualifier(
|
|
365
|
-
return secondsLeadClause(
|
|
393
|
+
const dayTrail = leadingQualifier(schedule, opts).trimEnd();
|
|
394
|
+
return secondsLeadClause(schedule, opts) + " " + frame + " aikana" + (dayTrail ? ", " + dayTrail : "");
|
|
366
395
|
}
|
|
367
|
-
function secondsLeadClause(
|
|
368
|
-
const secondField =
|
|
369
|
-
const shape =
|
|
396
|
+
function secondsLeadClause(schedule, opts) {
|
|
397
|
+
const secondField = schedule.pattern.second;
|
|
398
|
+
const shape = schedule.shapes.second;
|
|
370
399
|
if (secondField === "*") {
|
|
371
400
|
return "joka sekunti";
|
|
372
401
|
}
|
|
373
402
|
if (shape === "step") {
|
|
374
403
|
return stepCycle60(
|
|
375
|
-
stepSegment(
|
|
404
|
+
stepSegment(schedule, "second"),
|
|
376
405
|
units.second,
|
|
377
406
|
opts
|
|
378
407
|
);
|
|
379
408
|
}
|
|
380
|
-
const marked =
|
|
409
|
+
const marked = schedule.pattern.minute === "*";
|
|
381
410
|
if (shape === "single") {
|
|
382
411
|
return atMarks(secondField, units.second, marked);
|
|
383
412
|
}
|
|
384
|
-
return strideFromSegments(
|
|
385
|
-
|
|
413
|
+
return strideFromSegments(
|
|
414
|
+
segmentsOf(schedule, "second"),
|
|
415
|
+
units.second,
|
|
416
|
+
opts
|
|
417
|
+
) ?? atMarks(
|
|
418
|
+
joinList(segmentWords(segmentsOf(schedule, "second"))),
|
|
386
419
|
units.second,
|
|
387
420
|
marked
|
|
388
421
|
);
|
|
389
422
|
}
|
|
390
|
-
function renderEveryMinute(
|
|
391
|
-
return "joka minuutti" + trailingQualifier(
|
|
423
|
+
function renderEveryMinute(schedule, plan, opts) {
|
|
424
|
+
return "joka minuutti" + trailingQualifier(schedule, opts);
|
|
392
425
|
}
|
|
393
|
-
function renderSingleMinute(
|
|
394
|
-
return atMarks(
|
|
426
|
+
function renderSingleMinute(schedule, plan, opts) {
|
|
427
|
+
return atMarks(schedule.pattern.minute, units.minute, true) + trailingQualifier(schedule, opts);
|
|
395
428
|
}
|
|
396
|
-
function renderRangeOfMinutes(
|
|
397
|
-
return minutesList(
|
|
429
|
+
function renderRangeOfMinutes(schedule, plan, opts) {
|
|
430
|
+
return minutesList(schedule, opts) + trailingQualifier(schedule, opts);
|
|
398
431
|
}
|
|
399
|
-
function renderMultipleMinutes(
|
|
400
|
-
return minutesList(
|
|
432
|
+
function renderMultipleMinutes(schedule, plan, opts) {
|
|
433
|
+
return minutesList(schedule, opts) + trailingQualifier(schedule, opts);
|
|
401
434
|
}
|
|
402
|
-
function minutesList(
|
|
403
|
-
return strideFromSegments(
|
|
404
|
-
|
|
435
|
+
function minutesList(schedule, opts) {
|
|
436
|
+
return strideFromSegments(
|
|
437
|
+
segmentsOf(schedule, "minute"),
|
|
438
|
+
units.minute,
|
|
439
|
+
opts
|
|
440
|
+
) ?? atMarks(
|
|
441
|
+
joinList(segmentWords(segmentsOf(schedule, "minute"))),
|
|
405
442
|
units.minute,
|
|
406
443
|
true
|
|
407
444
|
);
|
|
408
445
|
}
|
|
409
|
-
function bareMinutes(
|
|
410
|
-
return strideFromSegments(
|
|
411
|
-
|
|
446
|
+
function bareMinutes(schedule, opts) {
|
|
447
|
+
return strideFromSegments(
|
|
448
|
+
segmentsOf(schedule, "minute"),
|
|
449
|
+
units.minute,
|
|
450
|
+
opts
|
|
451
|
+
) ?? atMarks(
|
|
452
|
+
joinList(segmentWords(segmentsOf(schedule, "minute"))),
|
|
412
453
|
units.minute,
|
|
413
454
|
false
|
|
414
455
|
);
|
|
@@ -438,16 +479,16 @@ function hoursAreRangeIsolated(segments) {
|
|
|
438
479
|
}
|
|
439
480
|
return hasRange && hasSingle;
|
|
440
481
|
}
|
|
441
|
-
function hoursFirstMinutes(hoursStr,
|
|
442
|
-
const stride = strideFromSegments(segmentsOf(
|
|
482
|
+
function hoursFirstMinutes(hoursStr, schedule, opts) {
|
|
483
|
+
const stride = strideFromSegments(segmentsOf(schedule, "minute"), units.minute, opts);
|
|
443
484
|
if (stride) {
|
|
444
485
|
return hoursStr + " aina " + stride;
|
|
445
486
|
}
|
|
446
|
-
return hoursStr + " aina minuuttien " + joinList(segmentWords(segmentsOf(
|
|
487
|
+
return hoursStr + " aina minuuttien " + joinList(segmentWords(segmentsOf(schedule, "minute"))) + " kohdalla";
|
|
447
488
|
}
|
|
448
|
-
function hourSegmentTimesWithSeka(
|
|
489
|
+
function hourSegmentTimesWithSeka(schedule, minute, second, opts) {
|
|
449
490
|
const pieces = [];
|
|
450
|
-
segmentsOf(
|
|
491
|
+
segmentsOf(schedule, "hour").forEach(function clock(segment) {
|
|
451
492
|
if (segment.kind === "range") {
|
|
452
493
|
pieces.push(rangeDigits(
|
|
453
494
|
{ hour: +segment.bounds[0], minute, second },
|
|
@@ -460,61 +501,61 @@ function hourSegmentTimesWithSeka(ir, minute, second, opts) {
|
|
|
460
501
|
});
|
|
461
502
|
return "klo " + pieces.slice(0, -1).join(", ") + " sek\xE4 klo " + pieces[pieces.length - 1];
|
|
462
503
|
}
|
|
463
|
-
function renderMinuteFrequency(
|
|
464
|
-
const seg = stepSegment(
|
|
504
|
+
function renderMinuteFrequency(schedule, plan, opts) {
|
|
505
|
+
const seg = stepSegment(schedule, "minute");
|
|
465
506
|
if (plan.hours.kind === "during") {
|
|
466
|
-
const cadence = unevenHourCadence(
|
|
507
|
+
const cadence = unevenHourCadence(schedule, opts);
|
|
467
508
|
if (cadence !== null) {
|
|
468
|
-
return stepCycle60(seg, units.minute, opts) + ", " + cadence + trailingQualifier(
|
|
509
|
+
return stepCycle60(seg, units.minute, opts) + ", " + cadence + trailingQualifier(schedule, opts);
|
|
469
510
|
}
|
|
470
511
|
if (minuteStepIsAnchored(seg)) {
|
|
471
|
-
const bareHours = kloFromTimes(
|
|
472
|
-
return hoursFirstMinutes(bareHours,
|
|
512
|
+
const bareHours = kloFromTimes(schedule, plan.hours.times, opts);
|
|
513
|
+
return hoursFirstMinutes(bareHours, schedule, opts) + trailingQualifier(schedule, opts);
|
|
473
514
|
}
|
|
474
|
-
return stepCycle60(seg, units.minute, opts) + " " + hourWindowsFromTimes(
|
|
515
|
+
return stepCycle60(seg, units.minute, opts) + " " + hourWindowsFromTimes(schedule, plan.hours.times, opts) + trailingQualifier(schedule, opts);
|
|
475
516
|
}
|
|
476
517
|
let phrase = stepCycle60(seg, units.minute, opts);
|
|
477
518
|
if (plan.hours.kind === "window") {
|
|
478
519
|
phrase += " " + hourWindow(plan.hours, opts);
|
|
479
520
|
} else if (plan.hours.kind === "step") {
|
|
480
|
-
phrase += " " + everyNthHour(stepSegment(
|
|
521
|
+
phrase += " " + everyNthHour(stepSegment(schedule, "hour"), opts);
|
|
481
522
|
}
|
|
482
|
-
return phrase + trailingQualifier(
|
|
523
|
+
return phrase + trailingQualifier(schedule, opts);
|
|
483
524
|
}
|
|
484
|
-
function renderMinuteSpanInHour(
|
|
485
|
-
if (
|
|
486
|
-
return "joka minuutti kello " + plan.hour + " aikana" + trailingQualifier(
|
|
525
|
+
function renderMinuteSpanInHour(schedule, plan, opts) {
|
|
526
|
+
if (schedule.pattern.minute === "*") {
|
|
527
|
+
return "joka minuutti kello " + plan.hour + " aikana" + trailingQualifier(schedule, opts);
|
|
487
528
|
}
|
|
488
529
|
return "joka minuutti " + kloRange(
|
|
489
530
|
{ hour: plan.hour, minute: plan.span[0] },
|
|
490
531
|
{ hour: plan.hour, minute: plan.span[1] },
|
|
491
532
|
opts
|
|
492
|
-
) + trailingQualifier(
|
|
533
|
+
) + trailingQualifier(schedule, opts);
|
|
493
534
|
}
|
|
494
|
-
function renderMinutesAcrossHours(
|
|
495
|
-
const cadence = unevenHourCadence(
|
|
535
|
+
function renderMinutesAcrossHours(schedule, plan, opts) {
|
|
536
|
+
const cadence = unevenHourCadence(schedule, opts);
|
|
496
537
|
if (plan.form === "wildcard") {
|
|
497
|
-
return cadence ? "joka minuutti, " + cadence + trailingQualifier(
|
|
538
|
+
return cadence ? "joka minuutti, " + cadence + trailingQualifier(schedule, opts) : "joka minuutti " + hourWindowsFromTimes(schedule, plan.times, opts) + trailingQualifier(schedule, opts);
|
|
498
539
|
}
|
|
499
540
|
if (cadence !== null) {
|
|
500
|
-
return bareMinutes(
|
|
541
|
+
return bareMinutes(schedule, opts) + ", " + cadence + trailingQualifier(schedule, opts);
|
|
501
542
|
}
|
|
502
|
-
if (hoursAreRangeIsolated(segmentsOf(
|
|
503
|
-
return bareMinutes(
|
|
543
|
+
if (hoursAreRangeIsolated(segmentsOf(schedule, "hour"))) {
|
|
544
|
+
return bareMinutes(schedule, opts) + " " + hourSegmentTimesWithSeka(schedule, 0, null, opts) + trailingQualifier(schedule, opts);
|
|
504
545
|
}
|
|
505
|
-
const hoursStr = kloFromTimes(
|
|
506
|
-
return hoursFirstMinutes(hoursStr,
|
|
546
|
+
const hoursStr = kloFromTimes(schedule, plan.times, opts);
|
|
547
|
+
return hoursFirstMinutes(hoursStr, schedule, opts) + trailingQualifier(schedule, opts);
|
|
507
548
|
}
|
|
508
|
-
function renderMinuteSpanAcrossHourStep(
|
|
509
|
-
const segment = stepSegment(
|
|
510
|
-
const cadence = unevenHourCadence(
|
|
549
|
+
function renderMinuteSpanAcrossHourStep(schedule, plan, opts) {
|
|
550
|
+
const segment = stepSegment(schedule, "hour");
|
|
551
|
+
const cadence = unevenHourCadence(schedule, opts);
|
|
511
552
|
if (plan.form === "wildcard") {
|
|
512
|
-
return "joka minuutti " + everyNthHour(segment, opts) + trailingQualifier(
|
|
553
|
+
return "joka minuutti " + everyNthHour(segment, opts) + trailingQualifier(schedule, opts);
|
|
513
554
|
}
|
|
514
555
|
if (cadence !== null) {
|
|
515
|
-
return bareMinutes(
|
|
556
|
+
return bareMinutes(schedule, opts) + ", " + cadence + trailingQualifier(schedule, opts);
|
|
516
557
|
}
|
|
517
|
-
return bareMinutes(
|
|
558
|
+
return bareMinutes(schedule, opts) + hourStepTail(segment, opts) + trailingQualifier(schedule, opts);
|
|
518
559
|
}
|
|
519
560
|
function plainHourStep(segment) {
|
|
520
561
|
return segment.startToken === "*" && 24 % segment.interval === 0;
|
|
@@ -563,35 +604,35 @@ function hourStepTail(segment, opts) {
|
|
|
563
604
|
const sep = plainHourStep(segment) ? " " : ", ";
|
|
564
605
|
return sep + plainOrFullHourStep(segment, opts);
|
|
565
606
|
}
|
|
566
|
-
function renderEveryHour(
|
|
567
|
-
return "joka tunti" + trailingQualifier(
|
|
607
|
+
function renderEveryHour(schedule, plan, opts) {
|
|
608
|
+
return "joka tunti" + trailingQualifier(schedule, opts);
|
|
568
609
|
}
|
|
569
|
-
function renderHourRange(
|
|
610
|
+
function renderHourRange(schedule, plan, opts) {
|
|
570
611
|
const window = hourWindow(boundedWindow(plan), opts);
|
|
571
612
|
if (plan.minuteForm === "wildcard") {
|
|
572
|
-
return "joka minuutti " + window + trailingQualifier(
|
|
613
|
+
return "joka minuutti " + window + trailingQualifier(schedule, opts);
|
|
573
614
|
}
|
|
574
615
|
if (plan.minuteForm === "range") {
|
|
575
|
-
return hoursFirstMinutes(window,
|
|
616
|
+
return hoursFirstMinutes(window, schedule, opts) + trailingQualifier(schedule, opts);
|
|
576
617
|
}
|
|
577
|
-
if (
|
|
578
|
-
return "joka tunti " + window + trailingQualifier(
|
|
618
|
+
if (schedule.pattern.minute === "0") {
|
|
619
|
+
return "joka tunti " + window + trailingQualifier(schedule, opts);
|
|
579
620
|
}
|
|
580
|
-
if (
|
|
581
|
-
return atMarks(
|
|
582
|
-
{ hour: plan.from, minute: +
|
|
621
|
+
if (schedule.shapes.minute === "single") {
|
|
622
|
+
return atMarks(schedule.pattern.minute, units.minute, false) + " " + kloRange(
|
|
623
|
+
{ hour: plan.from, minute: +schedule.pattern.minute },
|
|
583
624
|
{ hour: plan.to, minute: plan.last },
|
|
584
625
|
opts
|
|
585
|
-
) + trailingQualifier(
|
|
626
|
+
) + trailingQualifier(schedule, opts);
|
|
586
627
|
}
|
|
587
|
-
return hoursFirstMinutes(window,
|
|
628
|
+
return hoursFirstMinutes(window, schedule, opts) + trailingQualifier(schedule, opts);
|
|
588
629
|
}
|
|
589
|
-
function renderHourStep(
|
|
590
|
-
const cadence = unevenHourCadence(
|
|
630
|
+
function renderHourStep(schedule, plan, opts) {
|
|
631
|
+
const cadence = unevenHourCadence(schedule, opts);
|
|
591
632
|
if (cadence !== null) {
|
|
592
|
-
return cadence + trailingQualifier(
|
|
633
|
+
return cadence + trailingQualifier(schedule, opts);
|
|
593
634
|
}
|
|
594
|
-
return stepHours(stepSegment(
|
|
635
|
+
return stepHours(stepSegment(schedule, "hour"), opts) + trailingQualifier(schedule, opts);
|
|
595
636
|
}
|
|
596
637
|
function boundedWindow(plan) {
|
|
597
638
|
return { from: plan.from, last: plan.boundMinute ?? 0, to: plan.to };
|
|
@@ -603,53 +644,62 @@ function hourWindow(window, opts) {
|
|
|
603
644
|
opts
|
|
604
645
|
);
|
|
605
646
|
}
|
|
606
|
-
function renderClockTimes(
|
|
607
|
-
if (
|
|
608
|
-
const minute = +
|
|
609
|
-
const cadence = hourCadence(
|
|
647
|
+
function renderClockTimes(schedule, plan, opts) {
|
|
648
|
+
if (schedule.shapes.minute === "single") {
|
|
649
|
+
const minute = +schedule.pattern.minute;
|
|
650
|
+
const cadence = hourCadence(schedule, minute, opts) ?? hourRangeCadence(schedule, minute, opts);
|
|
610
651
|
if (cadence !== null) {
|
|
611
652
|
return cadence;
|
|
612
653
|
}
|
|
613
654
|
}
|
|
614
655
|
if (plan.times.length === 1) {
|
|
615
656
|
const time = plan.times[0];
|
|
616
|
-
return leadingQualifier(
|
|
657
|
+
return leadingQualifier(schedule, opts) + timeWord(time.hour, time.minute, time.second, opts);
|
|
617
658
|
}
|
|
618
659
|
const digits = plan.times.map(function clock(time) {
|
|
619
660
|
return timeDigits(time.hour, time.minute, time.second, opts);
|
|
620
661
|
});
|
|
621
|
-
return leadingQualifier(
|
|
662
|
+
return leadingQualifier(schedule, opts) + "klo " + joinList(digits);
|
|
622
663
|
}
|
|
623
|
-
function renderCompactClockTimes(
|
|
664
|
+
function renderCompactClockTimes(schedule, plan, opts) {
|
|
624
665
|
if (plan.fold) {
|
|
625
|
-
const cadence2 = hourCadence(
|
|
666
|
+
const cadence2 = hourCadence(schedule, plan.minute, opts) ?? hourRangeCadence(schedule, plan.minute, opts);
|
|
626
667
|
if (cadence2 !== null) {
|
|
627
668
|
return cadence2;
|
|
628
669
|
}
|
|
629
670
|
}
|
|
630
|
-
const hourSegs = segmentsOf(
|
|
671
|
+
const hourSegs = segmentsOf(schedule, "hour");
|
|
631
672
|
if (hoursAreRangeIsolated(hourSegs)) {
|
|
632
673
|
if (plan.fold) {
|
|
633
|
-
return leadingQualifier(
|
|
634
|
-
|
|
674
|
+
return leadingQualifier(schedule, opts) + hourSegmentTimesWithSeka(
|
|
675
|
+
schedule,
|
|
635
676
|
plan.minute,
|
|
636
|
-
|
|
677
|
+
schedule.analyses.clockSecond,
|
|
637
678
|
opts
|
|
638
679
|
);
|
|
639
680
|
}
|
|
640
|
-
const phrase2 = bareMinutes(
|
|
641
|
-
return
|
|
681
|
+
const phrase2 = bareMinutes(schedule, opts) + " " + hourSegmentTimesWithSeka(schedule, 0, null, opts) + trailingQualifier(schedule, opts);
|
|
682
|
+
return schedule.analyses.clockSecond ? secondsLeadClause(schedule, opts) + ", " + phrase2 : phrase2;
|
|
642
683
|
}
|
|
643
684
|
if (plan.fold) {
|
|
644
|
-
return leadingQualifier(
|
|
685
|
+
return leadingQualifier(schedule, opts) + hourSegmentTimes(
|
|
686
|
+
schedule,
|
|
687
|
+
plan.minute,
|
|
688
|
+
schedule.analyses.clockSecond,
|
|
689
|
+
opts
|
|
690
|
+
);
|
|
645
691
|
}
|
|
646
|
-
const cadence = unevenHourCadence(
|
|
647
|
-
const phrase = cadence ? bareMinutes(
|
|
692
|
+
const cadence = unevenHourCadence(schedule, opts);
|
|
693
|
+
const phrase = cadence ? bareMinutes(schedule, opts) + ", " + cadence + trailingQualifier(schedule, opts) : (
|
|
648
694
|
// A minute list over purely enumerated hours (step fires, all singles) —
|
|
649
695
|
// hours-first, drop "joka tunti".
|
|
650
|
-
hoursFirstMinutes(
|
|
696
|
+
hoursFirstMinutes(
|
|
697
|
+
hourSegmentTimes(schedule, 0, null, opts),
|
|
698
|
+
schedule,
|
|
699
|
+
opts
|
|
700
|
+
) + trailingQualifier(schedule, opts)
|
|
651
701
|
);
|
|
652
|
-
return
|
|
702
|
+
return schedule.analyses.clockSecond ? secondsLeadClause(schedule, opts) + ", " + phrase : phrase;
|
|
653
703
|
}
|
|
654
704
|
var renderers = {
|
|
655
705
|
clockTimes: renderClockTimes,
|
|
@@ -671,22 +721,19 @@ var renderers = {
|
|
|
671
721
|
singleMinute: renderSingleMinute,
|
|
672
722
|
standaloneSeconds: renderStandaloneSeconds
|
|
673
723
|
};
|
|
674
|
-
function
|
|
724
|
+
function renderStride2(stride, opts) {
|
|
675
725
|
const { interval, start, last, cycle, unit } = stride;
|
|
676
726
|
const cadence = genitive(interval, opts) + " " + unit.gen + " v\xE4lein";
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
return cadence + " " + unit.anchor + " " + unit.ela + " " + start + " alkaen";
|
|
683
|
-
}
|
|
684
|
-
return cadence + " " + unit.ela + " " + start + " " + unit.ill + " " + last;
|
|
727
|
+
return renderStride({ start, interval, cycle }, {
|
|
728
|
+
bare: () => cadence,
|
|
729
|
+
offset: () => cadence + " " + unit.anchor + " " + unit.ela + " " + start + " alkaen",
|
|
730
|
+
bounded: () => cadence + " " + unit.ela + " " + start + " " + unit.ill + " " + last
|
|
731
|
+
});
|
|
685
732
|
}
|
|
686
733
|
function strideFromSegments(segments, unit, opts) {
|
|
687
734
|
const values = singleValues(segments);
|
|
688
735
|
const step = values && arithmeticStep(values);
|
|
689
|
-
return step ?
|
|
736
|
+
return step ? renderStride2({ ...step, cycle: 60, unit }, opts) : null;
|
|
690
737
|
}
|
|
691
738
|
function stepCycle60(segment, unit, opts) {
|
|
692
739
|
if (segment.startToken.indexOf("-") !== -1) {
|
|
@@ -696,7 +743,7 @@ function stepCycle60(segment, unit, opts) {
|
|
|
696
743
|
if (start !== 0 && segment.fires.length <= 3) {
|
|
697
744
|
return atMarks(joinList(wordList(segment.fires)), unit, true);
|
|
698
745
|
}
|
|
699
|
-
return
|
|
746
|
+
return renderStride2({
|
|
700
747
|
interval: segment.interval,
|
|
701
748
|
start,
|
|
702
749
|
last: segment.fires[segment.fires.length - 1],
|
|
@@ -722,17 +769,14 @@ function stepHours(segment, opts) {
|
|
|
722
769
|
function hourStrideCadence(stride, opts) {
|
|
723
770
|
const { start, interval, last } = stride;
|
|
724
771
|
const cadence = genitive(interval, opts) + " tunnin v\xE4lein";
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
return cadence + " klo " + hourElatives[start] + " alkaen";
|
|
731
|
-
}
|
|
732
|
-
return cadence + " " + kloRange({ hour: start, minute: 0 }, { hour: last, minute: 0 }, opts);
|
|
772
|
+
return renderStride({ start, interval, cycle: 24 }, {
|
|
773
|
+
bare: () => cadence,
|
|
774
|
+
offset: () => cadence + " klo " + hourElatives[start] + " alkaen",
|
|
775
|
+
bounded: () => cadence + " " + kloRange({ hour: start, minute: 0 }, { hour: last, minute: 0 }, opts)
|
|
776
|
+
});
|
|
733
777
|
}
|
|
734
|
-
function hourStride(
|
|
735
|
-
const segments =
|
|
778
|
+
function hourStride(schedule) {
|
|
779
|
+
const segments = schedule.analyses.segments.hour;
|
|
736
780
|
if (!segments) {
|
|
737
781
|
return null;
|
|
738
782
|
}
|
|
@@ -747,47 +791,47 @@ function hourStride(ir) {
|
|
|
747
791
|
const values = singleValues(segments);
|
|
748
792
|
return values && hourListStride(values);
|
|
749
793
|
}
|
|
750
|
-
function unevenHourCadence(
|
|
751
|
-
const stride = hourStride(
|
|
794
|
+
function unevenHourCadence(schedule, opts) {
|
|
795
|
+
const stride = hourStride(schedule);
|
|
752
796
|
if (!stride || offsetCleanStride(stride)) {
|
|
753
797
|
return null;
|
|
754
798
|
}
|
|
755
799
|
return hourStrideCadence(stride, opts);
|
|
756
800
|
}
|
|
757
|
-
function subMinuteSecond(
|
|
758
|
-
return
|
|
801
|
+
function subMinuteSecond(schedule) {
|
|
802
|
+
return schedule.pattern.second === "*" || schedule.shapes.second === "step";
|
|
759
803
|
}
|
|
760
|
-
function hourCadenceLead(
|
|
804
|
+
function hourCadenceLead(schedule, minute, opts) {
|
|
761
805
|
if (minute === 0) {
|
|
762
|
-
if (subMinuteSecond(
|
|
763
|
-
return secondsLeadClause(
|
|
806
|
+
if (subMinuteSecond(schedule)) {
|
|
807
|
+
return secondsLeadClause(schedule, opts) + " minuutin ajan";
|
|
764
808
|
}
|
|
765
|
-
return secondsLeadClause(
|
|
809
|
+
return secondsLeadClause(schedule, opts);
|
|
766
810
|
}
|
|
767
811
|
const minutePhrase = atMarks(String(minute), units.minute, false);
|
|
768
|
-
if (
|
|
812
|
+
if (schedule.pattern.second === "0") {
|
|
769
813
|
return minutePhrase;
|
|
770
814
|
}
|
|
771
|
-
return secondsLeadClause(
|
|
815
|
+
return secondsLeadClause(schedule, opts) + ", " + minutePhrase;
|
|
772
816
|
}
|
|
773
|
-
function hourCadence(
|
|
774
|
-
const stride = hourStride(
|
|
817
|
+
function hourCadence(schedule, minute, opts) {
|
|
818
|
+
const stride = hourStride(schedule);
|
|
775
819
|
if (!stride) {
|
|
776
820
|
return null;
|
|
777
821
|
}
|
|
778
822
|
const fires = (stride.last - stride.start) / stride.interval + 1;
|
|
779
|
-
if (
|
|
823
|
+
if (schedule.pattern.second === "0" && fires <= maxClockTimes && offsetCleanStride(stride)) {
|
|
780
824
|
return null;
|
|
781
825
|
}
|
|
782
|
-
const segment = segmentsOf(
|
|
783
|
-
const confined = minute === 0 && subMinuteSecond(
|
|
826
|
+
const segment = segmentsOf(schedule, "hour")[0];
|
|
827
|
+
const confined = minute === 0 && subMinuteSecond(schedule) && segmentsOf(schedule, "hour").length === 1 && segment.kind === "step" && cleanHourStride(segment);
|
|
784
828
|
if (confined) {
|
|
785
|
-
return secondsLeadClause(
|
|
829
|
+
return secondsLeadClause(schedule, opts) + " minuutin ajan " + everyNthHour(segment, opts) + trailingQualifier(schedule, opts);
|
|
786
830
|
}
|
|
787
|
-
if (minute === 0 &&
|
|
788
|
-
return hourStrideCadence(stride, opts) + trailingQualifier(
|
|
831
|
+
if (minute === 0 && schedule.pattern.second === "0") {
|
|
832
|
+
return hourStrideCadence(stride, opts) + trailingQualifier(schedule, opts);
|
|
789
833
|
}
|
|
790
|
-
return hourCadenceLead(
|
|
834
|
+
return hourCadenceLead(schedule, minute, opts) + ", " + hourStrideCadence(stride, opts) + trailingQualifier(schedule, opts);
|
|
791
835
|
}
|
|
792
836
|
function cleanHourStride(segment) {
|
|
793
837
|
if (segment.startToken.indexOf("-") !== -1) {
|
|
@@ -796,22 +840,22 @@ function cleanHourStride(segment) {
|
|
|
796
840
|
const start = segment.startToken === "*" ? 0 : +segment.startToken;
|
|
797
841
|
return 24 % segment.interval === 0 && start < segment.interval;
|
|
798
842
|
}
|
|
799
|
-
function hasHourWindow(
|
|
800
|
-
const segments =
|
|
843
|
+
function hasHourWindow(schedule) {
|
|
844
|
+
const segments = schedule.analyses.segments.hour;
|
|
801
845
|
return !!segments && segments.some(function range(segment) {
|
|
802
846
|
return segment.kind === "range";
|
|
803
847
|
});
|
|
804
848
|
}
|
|
805
|
-
function hourRangeWindowTail(
|
|
806
|
-
return segmentsOf(
|
|
849
|
+
function hourRangeWindowTail(schedule, opts) {
|
|
850
|
+
return segmentsOf(schedule, "hour").length === 1 ? hourSegmentTimes(schedule, 0, null, opts) : hourSegmentTimesWithSeka(schedule, 0, null, opts);
|
|
807
851
|
}
|
|
808
|
-
function hourRangeCadence(
|
|
809
|
-
if (minute !== 0 || !hasHourWindow(
|
|
852
|
+
function hourRangeCadence(schedule, minute, opts) {
|
|
853
|
+
if (minute !== 0 || !hasHourWindow(schedule) || schedule.pattern.second === "0") {
|
|
810
854
|
return null;
|
|
811
855
|
}
|
|
812
|
-
const tail = hourRangeWindowTail(
|
|
813
|
-
const joiner = subMinuteSecond(
|
|
814
|
-
return hourCadenceLead(
|
|
856
|
+
const tail = hourRangeWindowTail(schedule, opts);
|
|
857
|
+
const joiner = subMinuteSecond(schedule) ? " " : ", ";
|
|
858
|
+
return hourCadenceLead(schedule, minute, opts) + joiner + tail + trailingQualifier(schedule, opts);
|
|
815
859
|
}
|
|
816
860
|
function kloList(hours, opts) {
|
|
817
861
|
if (hours.length === 1) {
|
|
@@ -821,17 +865,17 @@ function kloList(hours, opts) {
|
|
|
821
865
|
return timeDigits(hour, 0, null, opts);
|
|
822
866
|
}));
|
|
823
867
|
}
|
|
824
|
-
function kloFromTimes(
|
|
868
|
+
function kloFromTimes(schedule, times, opts) {
|
|
825
869
|
if (times.kind === "fires") {
|
|
826
870
|
return kloList(times.fires, opts);
|
|
827
871
|
}
|
|
828
|
-
return hourSegmentTimes(
|
|
872
|
+
return hourSegmentTimes(schedule, 0, null, opts);
|
|
829
873
|
}
|
|
830
|
-
function hourWindowsFromTimes(
|
|
874
|
+
function hourWindowsFromTimes(schedule, times, opts) {
|
|
831
875
|
if (times.kind === "fires") {
|
|
832
876
|
return kloList(times.fires, opts);
|
|
833
877
|
}
|
|
834
|
-
const segments = segmentsOf(
|
|
878
|
+
const segments = segmentsOf(schedule, "hour");
|
|
835
879
|
if (!segments.some(function ranged(segment) {
|
|
836
880
|
return segment.kind === "range";
|
|
837
881
|
})) {
|
|
@@ -869,9 +913,9 @@ function hourSegmentFires(segments) {
|
|
|
869
913
|
function hourWindowDigits(hour, opts) {
|
|
870
914
|
return rangeDigits({ hour, minute: 0 }, { hour, minute: 59 }, opts);
|
|
871
915
|
}
|
|
872
|
-
function hourSegmentTimes(
|
|
916
|
+
function hourSegmentTimes(schedule, minute, second, opts) {
|
|
873
917
|
const pieces = [];
|
|
874
|
-
segmentsOf(
|
|
918
|
+
segmentsOf(schedule, "hour").forEach(function clock(segment) {
|
|
875
919
|
if (segment.kind === "step") {
|
|
876
920
|
pieces.push(...segment.fires.map(function each(hour) {
|
|
877
921
|
return timeDigits(hour, minute, second, opts);
|
|
@@ -921,53 +965,54 @@ function timeDigits(hour, minute, second, opts) {
|
|
|
921
965
|
{ lean: true, sep: opts.style.sep }
|
|
922
966
|
);
|
|
923
967
|
}
|
|
924
|
-
function leadingQualifier(
|
|
925
|
-
const pattern =
|
|
926
|
-
if (restrictedMonthUnion(
|
|
968
|
+
function leadingQualifier(schedule, opts) {
|
|
969
|
+
const pattern = schedule.pattern;
|
|
970
|
+
if (restrictedMonthUnion(schedule)) {
|
|
927
971
|
return "";
|
|
928
972
|
}
|
|
929
973
|
if (pattern.date !== "*" && pattern.weekday !== "*") {
|
|
930
|
-
return dateOrWeekday(
|
|
974
|
+
return dateOrWeekday(schedule, opts) + " ";
|
|
931
975
|
}
|
|
932
976
|
if (pattern.date !== "*") {
|
|
933
|
-
return datePhrase(
|
|
977
|
+
return datePhrase(schedule, opts) + " ";
|
|
934
978
|
}
|
|
935
979
|
if (pattern.weekday !== "*") {
|
|
936
|
-
return weekdayQualifier(
|
|
980
|
+
return weekdayQualifier(schedule) + monthScope(schedule) + " ";
|
|
937
981
|
}
|
|
938
982
|
if (pattern.month !== "*") {
|
|
939
|
-
return "joka p\xE4iv\xE4 " + monthPhrase(
|
|
983
|
+
return "joka p\xE4iv\xE4 " + monthPhrase(schedule) + " ";
|
|
940
984
|
}
|
|
941
985
|
return "joka p\xE4iv\xE4 ";
|
|
942
986
|
}
|
|
943
|
-
function trailingQualifier(
|
|
944
|
-
const pattern =
|
|
945
|
-
if (restrictedMonthUnion(
|
|
987
|
+
function trailingQualifier(schedule, opts) {
|
|
988
|
+
const pattern = schedule.pattern;
|
|
989
|
+
if (restrictedMonthUnion(schedule)) {
|
|
946
990
|
return "";
|
|
947
991
|
}
|
|
948
992
|
if (pattern.date !== "*" && pattern.weekday !== "*") {
|
|
949
|
-
return " " + dateOrWeekday(
|
|
993
|
+
return " " + dateOrWeekday(schedule, opts);
|
|
950
994
|
}
|
|
951
995
|
if (pattern.date !== "*") {
|
|
952
|
-
return " " + datePhrase(
|
|
996
|
+
return " " + datePhrase(schedule, opts);
|
|
953
997
|
}
|
|
954
998
|
if (pattern.weekday !== "*") {
|
|
955
|
-
return " " + weekdayQualifier(
|
|
999
|
+
return " " + weekdayQualifier(schedule) + monthScope(schedule);
|
|
956
1000
|
}
|
|
957
1001
|
if (pattern.month !== "*") {
|
|
958
|
-
return " " + monthPhrase(
|
|
1002
|
+
return " " + monthPhrase(schedule);
|
|
959
1003
|
}
|
|
960
1004
|
return "";
|
|
961
1005
|
}
|
|
962
|
-
function dateOrWeekday(
|
|
963
|
-
|
|
1006
|
+
function dateOrWeekday(schedule, opts) {
|
|
1007
|
+
const dateArm = oddDayUnion(schedule.pattern.date) || datePhrase(schedule, opts);
|
|
1008
|
+
return dateArm + " tai " + unionWeekdayArm(schedule) + monthScope(schedule);
|
|
964
1009
|
}
|
|
965
|
-
function weekdayQualifier(
|
|
966
|
-
const quartz = quartzWeekdayPhrase(
|
|
1010
|
+
function weekdayQualifier(schedule) {
|
|
1011
|
+
const quartz = quartzWeekdayPhrase(schedule.pattern.weekday);
|
|
967
1012
|
if (quartz) {
|
|
968
1013
|
return quartz;
|
|
969
1014
|
}
|
|
970
|
-
const segments = orderWeekdaysForDisplay(segmentsOf(
|
|
1015
|
+
const segments = orderWeekdaysForDisplay(segmentsOf(schedule, "weekday"));
|
|
971
1016
|
return joinList(segments.map(function piece(segment) {
|
|
972
1017
|
if (segment.kind === "range") {
|
|
973
1018
|
return weekdays[weekdayNumber(segment.bounds[0])].ela + " " + weekdays[weekdayNumber(segment.bounds[1])].ill;
|
|
@@ -975,8 +1020,8 @@ function weekdayQualifier(ir) {
|
|
|
975
1020
|
return weekdays[weekdayNumber(segment.value)].isin;
|
|
976
1021
|
}));
|
|
977
1022
|
}
|
|
978
|
-
function monthPhrase(
|
|
979
|
-
const segments = flattenSteps(segmentsOf(
|
|
1023
|
+
function monthPhrase(schedule) {
|
|
1024
|
+
const segments = flattenSteps(segmentsOf(schedule, "month"));
|
|
980
1025
|
return joinList(segments.map(function piece(segment) {
|
|
981
1026
|
if (segment.kind === "range") {
|
|
982
1027
|
return monthStems[monthNumber(segment.bounds[0])] + "kuusta " + monthStems[monthNumber(segment.bounds[1])] + "kuuhun";
|
|
@@ -984,11 +1029,11 @@ function monthPhrase(ir) {
|
|
|
984
1029
|
return monthStems[monthNumber(segment.value)] + "kuussa";
|
|
985
1030
|
}));
|
|
986
1031
|
}
|
|
987
|
-
function monthScope(
|
|
988
|
-
if (
|
|
1032
|
+
function monthScope(schedule) {
|
|
1033
|
+
if (schedule.pattern.month === "*") {
|
|
989
1034
|
return "";
|
|
990
1035
|
}
|
|
991
|
-
return " " + monthPhrase(
|
|
1036
|
+
return " " + monthPhrase(schedule);
|
|
992
1037
|
}
|
|
993
1038
|
function flattenSteps(segments) {
|
|
994
1039
|
return segments.flatMap(function flat(segment) {
|
|
@@ -997,16 +1042,16 @@ function flattenSteps(segments) {
|
|
|
997
1042
|
}) : [segment];
|
|
998
1043
|
});
|
|
999
1044
|
}
|
|
1000
|
-
function datePhrase(
|
|
1001
|
-
const pattern =
|
|
1045
|
+
function datePhrase(schedule, opts) {
|
|
1046
|
+
const pattern = schedule.pattern;
|
|
1002
1047
|
const quartz = quartzDatePhrase(pattern.date);
|
|
1003
1048
|
if (quartz) {
|
|
1004
|
-
return quartz + monthScope(
|
|
1049
|
+
return quartz + monthScope(schedule);
|
|
1005
1050
|
}
|
|
1006
1051
|
if (isOpenStep(pattern.date)) {
|
|
1007
|
-
return stepDates(pattern.date, opts) + monthScope(
|
|
1052
|
+
return stepDates(pattern.date, opts) + monthScope(schedule);
|
|
1008
1053
|
}
|
|
1009
|
-
return monthAnchor(
|
|
1054
|
+
return monthAnchor(schedule, opts) + " " + dateWords(schedule) + " p\xE4iv\xE4n\xE4" + foldedYear(schedule) + monthStepStart(pattern.month) + rangedMonthScope(schedule);
|
|
1010
1055
|
}
|
|
1011
1056
|
function monthStepStart(monthField) {
|
|
1012
1057
|
if (!isOpenStep(monthField)) {
|
|
@@ -1018,30 +1063,30 @@ function monthStepStart(monthField) {
|
|
|
1018
1063
|
}
|
|
1019
1064
|
return " " + monthStems[monthNumber(start)] + "kuusta alkaen";
|
|
1020
1065
|
}
|
|
1021
|
-
function monthAnchor(
|
|
1022
|
-
const monthField =
|
|
1023
|
-
if (monthField === "*" || monthRanged(
|
|
1066
|
+
function monthAnchor(schedule, opts) {
|
|
1067
|
+
const monthField = schedule.pattern.month;
|
|
1068
|
+
if (monthField === "*" || monthRanged(schedule)) {
|
|
1024
1069
|
return "kuukauden";
|
|
1025
1070
|
}
|
|
1026
1071
|
if (isOpenStep(monthField)) {
|
|
1027
1072
|
return stepMonths(monthField, opts);
|
|
1028
1073
|
}
|
|
1029
|
-
const segments = flattenSteps(segmentsOf(
|
|
1074
|
+
const segments = flattenSteps(segmentsOf(schedule, "month"));
|
|
1030
1075
|
return joinList(segments.map(function genitiveOf(segment) {
|
|
1031
1076
|
const single = segment;
|
|
1032
1077
|
return monthStems[monthNumber(single.value)] + "kuun";
|
|
1033
1078
|
}));
|
|
1034
1079
|
}
|
|
1035
|
-
function rangedMonthScope(
|
|
1036
|
-
return monthRanged(
|
|
1080
|
+
function rangedMonthScope(schedule) {
|
|
1081
|
+
return monthRanged(schedule) ? " " + monthPhrase(schedule) : "";
|
|
1037
1082
|
}
|
|
1038
|
-
function monthRanged(
|
|
1039
|
-
return
|
|
1083
|
+
function monthRanged(schedule) {
|
|
1084
|
+
return schedule.pattern.month !== "*" && segmentsOf(schedule, "month").some(function range(segment) {
|
|
1040
1085
|
return segment.kind === "range";
|
|
1041
1086
|
});
|
|
1042
1087
|
}
|
|
1043
|
-
function dateWords(
|
|
1044
|
-
return joinList(segmentsOf(
|
|
1088
|
+
function dateWords(schedule) {
|
|
1089
|
+
return joinList(segmentsOf(schedule, "date").flatMap(
|
|
1045
1090
|
function word(segment) {
|
|
1046
1091
|
if (segment.kind === "range") {
|
|
1047
1092
|
return [segment.bounds[0] + ".\u2013" + segment.bounds[1] + "."];
|
|
@@ -1097,15 +1142,15 @@ function weekdayNumber(token) {
|
|
|
1097
1142
|
function monthNumber(token) {
|
|
1098
1143
|
return +token;
|
|
1099
1144
|
}
|
|
1100
|
-
function applyYear(description,
|
|
1101
|
-
const yearField =
|
|
1145
|
+
function applyYear(description, schedule, opts) {
|
|
1146
|
+
const yearField = schedule.pattern.year;
|
|
1102
1147
|
if (yearField === "*") {
|
|
1103
1148
|
return description;
|
|
1104
1149
|
}
|
|
1105
1150
|
if (yearField.indexOf("/") !== -1) {
|
|
1106
1151
|
return description + " " + stepYears(yearField, opts);
|
|
1107
1152
|
}
|
|
1108
|
-
if (foldedYear(
|
|
1153
|
+
if (foldedYear(schedule) && schedule.pattern.date !== "*") {
|
|
1109
1154
|
return description;
|
|
1110
1155
|
}
|
|
1111
1156
|
if (yearField.indexOf(",") !== -1) {
|
|
@@ -1125,8 +1170,8 @@ function stepYears(yearField, opts) {
|
|
|
1125
1170
|
}
|
|
1126
1171
|
return phrase;
|
|
1127
1172
|
}
|
|
1128
|
-
function foldedYear(
|
|
1129
|
-
const yearField =
|
|
1173
|
+
function foldedYear(schedule) {
|
|
1174
|
+
const yearField = schedule.pattern.year;
|
|
1130
1175
|
if (yearField === "*" || yearField.indexOf("/") !== -1 || yearField.indexOf("-") !== -1 || yearField.indexOf(",") !== -1) {
|
|
1131
1176
|
return "";
|
|
1132
1177
|
}
|