cronli5 0.1.4 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -0
- package/cronli5.min.js +2 -2
- package/dist/cronli5.cjs +180 -36
- package/dist/cronli5.js +180 -36
- package/dist/lang/de.cjs +172 -8
- package/dist/lang/de.js +172 -8
- package/dist/lang/en.cjs +175 -29
- package/dist/lang/en.js +175 -29
- package/dist/lang/es.cjs +180 -25
- package/dist/lang/es.js +180 -25
- package/dist/lang/fi.cjs +188 -40
- package/dist/lang/fi.js +188 -40
- package/dist/lang/zh.cjs +165 -19
- package/dist/lang/zh.js +165 -19
- package/package.json +2 -1
- package/src/core/analyze.ts +7 -0
- package/src/core/ir.ts +1 -1
- package/src/core/util.ts +31 -1
- package/src/lang/de/index.ts +360 -16
- package/src/lang/en/index.ts +333 -33
- package/src/lang/es/index.ts +373 -40
- package/src/lang/fi/index.ts +404 -72
- package/src/lang/zh/index.ts +327 -35
- package/types/core/ir.d.ts +1 -1
- package/types/core/util.d.ts +6 -1
package/dist/lang/fi.js
CHANGED
|
@@ -24,12 +24,28 @@ var weekdayNumbers = {
|
|
|
24
24
|
FRI: 5,
|
|
25
25
|
SAT: 6
|
|
26
26
|
};
|
|
27
|
+
var maxClockTimes = 6;
|
|
27
28
|
|
|
28
29
|
// src/core/util.ts
|
|
29
30
|
function isNonNegativeInteger(value) {
|
|
30
31
|
const digits = /^\d+$/;
|
|
31
32
|
return digits.test(value);
|
|
32
33
|
}
|
|
34
|
+
function arithmeticStep(values) {
|
|
35
|
+
if (values.length < 5) {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
const interval = values[1] - values[0];
|
|
39
|
+
if (interval < 2) {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
for (let i = 2; i < values.length; i += 1) {
|
|
43
|
+
if (values[i] - values[i - 1] !== interval) {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return { start: values[0], interval, last: values[values.length - 1] };
|
|
48
|
+
}
|
|
33
49
|
function toFieldNumber(token, numberMap) {
|
|
34
50
|
return isNonNegativeInteger(token) ? +token : numberMap[token.toUpperCase()];
|
|
35
51
|
}
|
|
@@ -165,12 +181,14 @@ var units = {
|
|
|
165
181
|
mark: "joka tunti",
|
|
166
182
|
anchor: "jokaisen tunnin",
|
|
167
183
|
ela: "minuutista",
|
|
184
|
+
ill: "minuuttiin",
|
|
168
185
|
gen: "minuutin"
|
|
169
186
|
},
|
|
170
187
|
second: {
|
|
171
188
|
mark: "joka minuutti",
|
|
172
189
|
anchor: "jokaisen minuutin",
|
|
173
190
|
ela: "sekunnista",
|
|
191
|
+
ill: "sekuntiin",
|
|
174
192
|
gen: "sekunnin"
|
|
175
193
|
}
|
|
176
194
|
};
|
|
@@ -226,29 +244,50 @@ function renderSecondsWithinMinute(ir, plan, opts) {
|
|
|
226
244
|
}
|
|
227
245
|
return secondsLeadClause(ir, opts) + ", " + atMarks(minuteField, units.minute, true) + trailingQualifier(ir, opts);
|
|
228
246
|
}
|
|
247
|
+
function composeSecondsOverMinuteStep(ir, freq, opts) {
|
|
248
|
+
const seg = stepSegment(ir.analyses.segments.minute);
|
|
249
|
+
const stepPhrase = stepCycle60(seg, units.minute, opts);
|
|
250
|
+
if (freq.hours.kind === "during" && minuteStepIsAnchored(seg)) {
|
|
251
|
+
const bareHours = kloFromTimes(ir, freq.hours.times, opts);
|
|
252
|
+
return hoursFirstMinutes(bareHours, ir, opts) + ", " + secondsLeadClause(ir, opts) + trailingQualifier(ir, opts);
|
|
253
|
+
}
|
|
254
|
+
let hourClause = "";
|
|
255
|
+
if (freq.hours.kind === "during") {
|
|
256
|
+
hourClause = " " + hourWindowsFromTimes(ir, freq.hours.times, opts);
|
|
257
|
+
} else if (freq.hours.kind === "window") {
|
|
258
|
+
hourClause = " " + hourWindow(freq.hours, opts);
|
|
259
|
+
} else if (freq.hours.kind === "step") {
|
|
260
|
+
hourClause = " " + everyNthHour(stepSegment(ir.analyses.segments.hour), opts);
|
|
261
|
+
}
|
|
262
|
+
return stepPhrase + ", " + secondsLeadClause(ir, opts) + hourClause + trailingQualifier(ir, opts);
|
|
263
|
+
}
|
|
264
|
+
function composeHourCadence(ir, plan, opts) {
|
|
265
|
+
const clockRest = plan.rest.kind === "clockTimes" || plan.rest.kind === "compactClockTimes";
|
|
266
|
+
return clockRest && ir.shapes.minute === "single" ? hourCadence(ir, +ir.pattern.minute, opts) : null;
|
|
267
|
+
}
|
|
229
268
|
function renderComposeSeconds(ir, plan, opts) {
|
|
269
|
+
const cadence = composeHourCadence(ir, plan, opts);
|
|
270
|
+
if (cadence !== null) {
|
|
271
|
+
return cadence;
|
|
272
|
+
}
|
|
230
273
|
if (plan.rest.kind === "minuteFrequency" && ir.pattern.second !== "*") {
|
|
231
|
-
|
|
232
|
-
const seg = stepSegment(ir.analyses.segments.minute);
|
|
233
|
-
const stepPhrase = stepCycle60(seg, units.minute, opts);
|
|
234
|
-
let hourClause = "";
|
|
235
|
-
if (freq.hours.kind === "during" && minuteStepIsAnchored(seg)) {
|
|
236
|
-
const bareHours = kloFromTimes(ir, freq.hours.times, opts);
|
|
237
|
-
return hoursFirstMinutes(bareHours, ir) + ", " + secondsLeadClause(ir, opts) + trailingQualifier(ir, opts);
|
|
238
|
-
} else if (freq.hours.kind === "during" && !minuteStepIsAnchored(seg)) {
|
|
239
|
-
hourClause = " " + hourWindowsFromTimes(ir, freq.hours.times, opts);
|
|
240
|
-
} else if (freq.hours.kind === "window") {
|
|
241
|
-
hourClause = " " + hourWindow(freq.hours, opts);
|
|
242
|
-
} else if (freq.hours.kind === "step") {
|
|
243
|
-
hourClause = " " + everyNthHour(stepSegment(ir.analyses.segments.hour), opts);
|
|
244
|
-
}
|
|
245
|
-
return stepPhrase + ", " + secondsLeadClause(ir, opts) + hourClause + trailingQualifier(ir, opts);
|
|
274
|
+
return composeSecondsOverMinuteStep(ir, plan.rest, opts);
|
|
246
275
|
}
|
|
247
276
|
if (plan.rest.kind === "clockTimes" && plan.rest.times.every((time) => +time.minute === 0)) {
|
|
248
277
|
return composeMinuteZero(ir, plan.rest, opts);
|
|
249
278
|
}
|
|
279
|
+
if (isEveryOtherMinuteSeconds(ir, plan)) {
|
|
280
|
+
return secondsLeadClause(ir, opts) + " joka toisena minuuttina";
|
|
281
|
+
}
|
|
250
282
|
return secondsLeadClause(ir, opts) + ", " + render(ir, plan.rest, opts);
|
|
251
283
|
}
|
|
284
|
+
function isEveryOtherMinuteSeconds(ir, plan) {
|
|
285
|
+
if (plan.rest.kind !== "minuteFrequency" || ir.pattern.second !== "*" || ir.shapes.hour !== "wildcard") {
|
|
286
|
+
return false;
|
|
287
|
+
}
|
|
288
|
+
const seg = stepSegment(ir.analyses.segments.minute);
|
|
289
|
+
return seg.startToken === "*" && seg.interval === 2;
|
|
290
|
+
}
|
|
252
291
|
function composeMinuteZero(ir, rest, opts) {
|
|
253
292
|
const clocks = rest.times.map(function clock(time) {
|
|
254
293
|
return clockDigits(
|
|
@@ -277,7 +316,7 @@ function secondsLeadClause(ir, opts) {
|
|
|
277
316
|
if (shape === "single") {
|
|
278
317
|
return atMarks(secondField, units.second, marked);
|
|
279
318
|
}
|
|
280
|
-
return atMarks(
|
|
319
|
+
return strideFromSegments(ir.analyses.segments.second, units.second, opts) ?? atMarks(
|
|
281
320
|
joinList(segmentWords(ir.analyses.segments.second)),
|
|
282
321
|
units.second,
|
|
283
322
|
marked
|
|
@@ -290,20 +329,20 @@ function renderSingleMinute(ir, plan, opts) {
|
|
|
290
329
|
return atMarks(ir.pattern.minute, units.minute, true) + trailingQualifier(ir, opts);
|
|
291
330
|
}
|
|
292
331
|
function renderRangeOfMinutes(ir, plan, opts) {
|
|
293
|
-
return minutesList(ir) + trailingQualifier(ir, opts);
|
|
332
|
+
return minutesList(ir, opts) + trailingQualifier(ir, opts);
|
|
294
333
|
}
|
|
295
334
|
function renderMultipleMinutes(ir, plan, opts) {
|
|
296
|
-
return minutesList(ir) + trailingQualifier(ir, opts);
|
|
335
|
+
return minutesList(ir, opts) + trailingQualifier(ir, opts);
|
|
297
336
|
}
|
|
298
|
-
function minutesList(ir) {
|
|
299
|
-
return atMarks(
|
|
337
|
+
function minutesList(ir, opts) {
|
|
338
|
+
return strideFromSegments(ir.analyses.segments.minute, units.minute, opts) ?? atMarks(
|
|
300
339
|
joinList(segmentWords(ir.analyses.segments.minute)),
|
|
301
340
|
units.minute,
|
|
302
341
|
true
|
|
303
342
|
);
|
|
304
343
|
}
|
|
305
|
-
function bareMinutes(ir) {
|
|
306
|
-
return atMarks(
|
|
344
|
+
function bareMinutes(ir, opts) {
|
|
345
|
+
return strideFromSegments(ir.analyses.segments.minute, units.minute, opts) ?? atMarks(
|
|
307
346
|
joinList(segmentWords(ir.analyses.segments.minute)),
|
|
308
347
|
units.minute,
|
|
309
348
|
false
|
|
@@ -334,7 +373,11 @@ function hoursAreRangeIsolated(segments) {
|
|
|
334
373
|
}
|
|
335
374
|
return hasRange && hasSingle;
|
|
336
375
|
}
|
|
337
|
-
function hoursFirstMinutes(hoursStr, ir) {
|
|
376
|
+
function hoursFirstMinutes(hoursStr, ir, opts) {
|
|
377
|
+
const stride = strideFromSegments(ir.analyses.segments.minute, units.minute, opts);
|
|
378
|
+
if (stride) {
|
|
379
|
+
return hoursStr + " aina " + stride;
|
|
380
|
+
}
|
|
338
381
|
return hoursStr + " aina minuuttien " + joinList(segmentWords(ir.analyses.segments.minute)) + " kohdalla";
|
|
339
382
|
}
|
|
340
383
|
function hourSegmentTimesWithSeka(ir, minute, second, opts) {
|
|
@@ -357,7 +400,7 @@ function renderMinuteFrequency(ir, plan, opts) {
|
|
|
357
400
|
if (plan.hours.kind === "during") {
|
|
358
401
|
if (minuteStepIsAnchored(seg)) {
|
|
359
402
|
const bareHours = kloFromTimes(ir, plan.hours.times, opts);
|
|
360
|
-
return hoursFirstMinutes(bareHours, ir) + trailingQualifier(ir, opts);
|
|
403
|
+
return hoursFirstMinutes(bareHours, ir, opts) + trailingQualifier(ir, opts);
|
|
361
404
|
}
|
|
362
405
|
return stepCycle60(seg, units.minute, opts) + " " + hourWindowsFromTimes(ir, plan.hours.times, opts) + trailingQualifier(ir, opts);
|
|
363
406
|
}
|
|
@@ -384,10 +427,10 @@ function renderMinutesAcrossHours(ir, plan, opts) {
|
|
|
384
427
|
return "joka minuutti " + hourWindowsFromTimes(ir, plan.times, opts) + trailingQualifier(ir, opts);
|
|
385
428
|
}
|
|
386
429
|
if (hoursAreRangeIsolated(ir.analyses.segments.hour)) {
|
|
387
|
-
return bareMinutes(ir) + " " + hourSegmentTimesWithSeka(ir, 0, null, opts) + trailingQualifier(ir, opts);
|
|
430
|
+
return bareMinutes(ir, opts) + " " + hourSegmentTimesWithSeka(ir, 0, null, opts) + trailingQualifier(ir, opts);
|
|
388
431
|
}
|
|
389
432
|
const hoursStr = kloFromTimes(ir, plan.times, opts);
|
|
390
|
-
return hoursFirstMinutes(hoursStr, ir) + trailingQualifier(ir, opts);
|
|
433
|
+
return hoursFirstMinutes(hoursStr, ir, opts) + trailingQualifier(ir, opts);
|
|
391
434
|
}
|
|
392
435
|
function renderMinuteSpanAcrossHourStep(ir, plan, opts) {
|
|
393
436
|
const segment = stepSegment(ir.analyses.segments.hour);
|
|
@@ -396,9 +439,9 @@ function renderMinuteSpanAcrossHourStep(ir, plan, opts) {
|
|
|
396
439
|
}
|
|
397
440
|
if (segment.startToken.indexOf("-") !== -1) {
|
|
398
441
|
const hoursStr = kloList(segment.fires, opts);
|
|
399
|
-
return hoursFirstMinutes(hoursStr, ir) + trailingQualifier(ir, opts);
|
|
442
|
+
return hoursFirstMinutes(hoursStr, ir, opts) + trailingQualifier(ir, opts);
|
|
400
443
|
}
|
|
401
|
-
return bareMinutes(ir) + hourStepTail(segment, opts) + trailingQualifier(ir, opts);
|
|
444
|
+
return bareMinutes(ir, opts) + hourStepTail(segment, opts) + trailingQualifier(ir, opts);
|
|
402
445
|
}
|
|
403
446
|
function plainHourStep(segment) {
|
|
404
447
|
return segment.startToken === "*" && 24 % segment.interval === 0;
|
|
@@ -456,7 +499,7 @@ function renderHourRange(ir, plan, opts) {
|
|
|
456
499
|
return "joka minuutti " + window + trailingQualifier(ir, opts);
|
|
457
500
|
}
|
|
458
501
|
if (plan.minuteForm === "range") {
|
|
459
|
-
return hoursFirstMinutes(window, ir) + trailingQualifier(ir, opts);
|
|
502
|
+
return hoursFirstMinutes(window, ir, opts) + trailingQualifier(ir, opts);
|
|
460
503
|
}
|
|
461
504
|
if (ir.pattern.minute === "0") {
|
|
462
505
|
return "joka tunti " + window + trailingQualifier(ir, opts);
|
|
@@ -468,7 +511,7 @@ function renderHourRange(ir, plan, opts) {
|
|
|
468
511
|
opts
|
|
469
512
|
) + trailingQualifier(ir, opts);
|
|
470
513
|
}
|
|
471
|
-
return hoursFirstMinutes(window, ir) + trailingQualifier(ir, opts);
|
|
514
|
+
return hoursFirstMinutes(window, ir, opts) + trailingQualifier(ir, opts);
|
|
472
515
|
}
|
|
473
516
|
function renderHourStep(ir, plan, opts) {
|
|
474
517
|
return stepHours(stepSegment(ir.analyses.segments.hour), opts) + trailingQualifier(ir, opts);
|
|
@@ -484,6 +527,12 @@ function hourWindow(window, opts) {
|
|
|
484
527
|
);
|
|
485
528
|
}
|
|
486
529
|
function renderClockTimes(ir, plan, opts) {
|
|
530
|
+
if (ir.shapes.minute === "single") {
|
|
531
|
+
const cadence = hourCadence(ir, +ir.pattern.minute, opts);
|
|
532
|
+
if (cadence !== null) {
|
|
533
|
+
return cadence;
|
|
534
|
+
}
|
|
535
|
+
}
|
|
487
536
|
if (plan.times.length === 1) {
|
|
488
537
|
const time = plan.times[0];
|
|
489
538
|
return leadingQualifier(ir, opts) + timeWord(time.hour, time.minute, time.second, opts);
|
|
@@ -494,6 +543,12 @@ function renderClockTimes(ir, plan, opts) {
|
|
|
494
543
|
return leadingQualifier(ir, opts) + "klo " + joinList(digits);
|
|
495
544
|
}
|
|
496
545
|
function renderCompactClockTimes(ir, plan, opts) {
|
|
546
|
+
if (plan.fold) {
|
|
547
|
+
const cadence = hourCadence(ir, plan.minute, opts);
|
|
548
|
+
if (cadence !== null) {
|
|
549
|
+
return cadence;
|
|
550
|
+
}
|
|
551
|
+
}
|
|
497
552
|
const hourSegs = ir.analyses.segments.hour;
|
|
498
553
|
if (hoursAreRangeIsolated(hourSegs)) {
|
|
499
554
|
if (plan.fold) {
|
|
@@ -504,14 +559,14 @@ function renderCompactClockTimes(ir, plan, opts) {
|
|
|
504
559
|
opts
|
|
505
560
|
);
|
|
506
561
|
}
|
|
507
|
-
const phrase2 = bareMinutes(ir) + " " + hourSegmentTimesWithSeka(ir, 0, null, opts) + trailingQualifier(ir, opts);
|
|
562
|
+
const phrase2 = bareMinutes(ir, opts) + " " + hourSegmentTimesWithSeka(ir, 0, null, opts) + trailingQualifier(ir, opts);
|
|
508
563
|
return ir.analyses.clockSecond ? secondsLeadClause(ir, opts) + ", " + phrase2 : phrase2;
|
|
509
564
|
}
|
|
510
565
|
if (plan.fold) {
|
|
511
566
|
return leadingQualifier(ir, opts) + hourSegmentTimes(ir, plan.minute, ir.analyses.clockSecond, opts);
|
|
512
567
|
}
|
|
513
568
|
const hoursStr = hourSegmentTimes(ir, 0, null, opts);
|
|
514
|
-
const phrase = hoursFirstMinutes(hoursStr, ir) + trailingQualifier(ir, opts);
|
|
569
|
+
const phrase = hoursFirstMinutes(hoursStr, ir, opts) + trailingQualifier(ir, opts);
|
|
515
570
|
return ir.analyses.clockSecond ? secondsLeadClause(ir, opts) + ", " + phrase : phrase;
|
|
516
571
|
}
|
|
517
572
|
var renderers = {
|
|
@@ -534,20 +589,48 @@ var renderers = {
|
|
|
534
589
|
singleMinute: renderSingleMinute,
|
|
535
590
|
standaloneSeconds: renderStandaloneSeconds
|
|
536
591
|
};
|
|
592
|
+
function renderStride(stride, opts) {
|
|
593
|
+
const { interval, start, last, cycle, unit } = stride;
|
|
594
|
+
const cadence = genitive(interval, opts) + " " + unit.gen + " v\xE4lein";
|
|
595
|
+
const tiles = cycle % interval === 0;
|
|
596
|
+
if (start === 0 && tiles) {
|
|
597
|
+
return cadence;
|
|
598
|
+
}
|
|
599
|
+
if (start < interval && tiles) {
|
|
600
|
+
return cadence + " " + unit.anchor + " " + unit.ela + " " + start + " alkaen";
|
|
601
|
+
}
|
|
602
|
+
return cadence + " " + unit.ela + " " + start + " " + unit.ill + " " + last;
|
|
603
|
+
}
|
|
604
|
+
function strideFromSegments(segments, unit, opts) {
|
|
605
|
+
const values = singleValues(segments);
|
|
606
|
+
const step = values && arithmeticStep(values);
|
|
607
|
+
return step ? renderStride({ ...step, cycle: 60, unit }, opts) : null;
|
|
608
|
+
}
|
|
609
|
+
function singleValues(segments) {
|
|
610
|
+
const values = [];
|
|
611
|
+
for (const segment of segments) {
|
|
612
|
+
if (segment.kind !== "single") {
|
|
613
|
+
return null;
|
|
614
|
+
}
|
|
615
|
+
values.push(+segment.value);
|
|
616
|
+
}
|
|
617
|
+
return values;
|
|
618
|
+
}
|
|
537
619
|
function stepCycle60(segment, unit, opts) {
|
|
538
620
|
if (segment.startToken.indexOf("-") !== -1) {
|
|
539
621
|
return atMarks(joinList(wordList(segment.fires)), unit, true);
|
|
540
622
|
}
|
|
541
623
|
const start = segment.startToken === "*" ? 0 : +segment.startToken;
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
if (start !== 0) {
|
|
545
|
-
if (segment.fires.length <= 3) {
|
|
546
|
-
return atMarks(joinList(wordList(segment.fires)), unit, true);
|
|
547
|
-
}
|
|
548
|
-
return cadence + " " + unit.anchor + " " + unit.ela + " " + start + " alkaen";
|
|
624
|
+
if (start !== 0 && segment.fires.length <= 3) {
|
|
625
|
+
return atMarks(joinList(wordList(segment.fires)), unit, true);
|
|
549
626
|
}
|
|
550
|
-
return
|
|
627
|
+
return renderStride({
|
|
628
|
+
interval: segment.interval,
|
|
629
|
+
start,
|
|
630
|
+
last: segment.fires[segment.fires.length - 1],
|
|
631
|
+
cycle: 60,
|
|
632
|
+
unit
|
|
633
|
+
}, opts);
|
|
551
634
|
}
|
|
552
635
|
function stepHours(segment, opts) {
|
|
553
636
|
if (segment.startToken.indexOf("-") !== -1) {
|
|
@@ -564,6 +647,71 @@ function stepHours(segment, opts) {
|
|
|
564
647
|
}
|
|
565
648
|
return cadence + " klo " + hourElatives[start] + " alkaen";
|
|
566
649
|
}
|
|
650
|
+
function hourStrideCadence(stride, opts) {
|
|
651
|
+
const { start, interval, last } = stride;
|
|
652
|
+
const cadence = genitive(interval, opts) + " tunnin v\xE4lein";
|
|
653
|
+
const tiles = 24 % interval === 0;
|
|
654
|
+
if (start === 0 && tiles) {
|
|
655
|
+
return cadence;
|
|
656
|
+
}
|
|
657
|
+
if (start < interval && tiles) {
|
|
658
|
+
return cadence + " klo " + hourElatives[start] + " alkaen";
|
|
659
|
+
}
|
|
660
|
+
return cadence + " " + kloRange({ hour: start, minute: 0 }, { hour: last, minute: 0 }, opts);
|
|
661
|
+
}
|
|
662
|
+
function hourStride(ir) {
|
|
663
|
+
const segments = ir.analyses.segments.hour;
|
|
664
|
+
if (!segments) {
|
|
665
|
+
return null;
|
|
666
|
+
}
|
|
667
|
+
if (segments.length === 1 && segments[0].kind === "step") {
|
|
668
|
+
const segment = segments[0];
|
|
669
|
+
const start = segment.startToken === "*" ? 0 : +segment.startToken.split("-")[0];
|
|
670
|
+
return { interval: segment.interval, last: segment.fires[segment.fires.length - 1], start };
|
|
671
|
+
}
|
|
672
|
+
const values = singleValues(segments);
|
|
673
|
+
const step = values && arithmeticStep(values);
|
|
674
|
+
return step || null;
|
|
675
|
+
}
|
|
676
|
+
function subMinuteSecond(ir) {
|
|
677
|
+
return ir.pattern.second === "*" || ir.shapes.second === "step";
|
|
678
|
+
}
|
|
679
|
+
function hourCadenceLead(ir, minute, opts) {
|
|
680
|
+
if (minute === 0) {
|
|
681
|
+
if (subMinuteSecond(ir)) {
|
|
682
|
+
return secondsLeadClause(ir, opts) + " minuutin ajan";
|
|
683
|
+
}
|
|
684
|
+
return secondsLeadClause(ir, opts);
|
|
685
|
+
}
|
|
686
|
+
const minutePhrase = atMarks(String(minute), units.minute, false);
|
|
687
|
+
if (ir.pattern.second === "0") {
|
|
688
|
+
return minutePhrase;
|
|
689
|
+
}
|
|
690
|
+
return secondsLeadClause(ir, opts) + ", " + minutePhrase;
|
|
691
|
+
}
|
|
692
|
+
function hourCadence(ir, minute, opts) {
|
|
693
|
+
const stride = hourStride(ir);
|
|
694
|
+
if (!stride) {
|
|
695
|
+
return null;
|
|
696
|
+
}
|
|
697
|
+
const fires = (stride.last - stride.start) / stride.interval + 1;
|
|
698
|
+
if (ir.pattern.second === "0" && fires <= maxClockTimes) {
|
|
699
|
+
return null;
|
|
700
|
+
}
|
|
701
|
+
const segment = ir.analyses.segments.hour[0];
|
|
702
|
+
const confined = minute === 0 && subMinuteSecond(ir) && ir.analyses.segments.hour.length === 1 && segment.kind === "step" && cleanHourStride(segment);
|
|
703
|
+
if (confined) {
|
|
704
|
+
return secondsLeadClause(ir, opts) + " minuutin ajan " + everyNthHour(segment, opts) + trailingQualifier(ir, opts);
|
|
705
|
+
}
|
|
706
|
+
return hourCadenceLead(ir, minute, opts) + ", " + hourStrideCadence(stride, opts) + trailingQualifier(ir, opts);
|
|
707
|
+
}
|
|
708
|
+
function cleanHourStride(segment) {
|
|
709
|
+
if (segment.startToken.indexOf("-") !== -1) {
|
|
710
|
+
return false;
|
|
711
|
+
}
|
|
712
|
+
const start = segment.startToken === "*" ? 0 : +segment.startToken;
|
|
713
|
+
return 24 % segment.interval === 0 && start < segment.interval;
|
|
714
|
+
}
|
|
567
715
|
function kloList(hours, opts) {
|
|
568
716
|
if (hours.length === 1) {
|
|
569
717
|
return timeWord(hours[0], 0, null, opts);
|
package/dist/lang/zh.cjs
CHANGED
|
@@ -29,6 +29,21 @@ function isNonNegativeInteger(value) {
|
|
|
29
29
|
const digits = /^\d+$/;
|
|
30
30
|
return digits.test(value);
|
|
31
31
|
}
|
|
32
|
+
function arithmeticStep(values) {
|
|
33
|
+
if (values.length < 5) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
const interval = values[1] - values[0];
|
|
37
|
+
if (interval < 2) {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
for (let i = 2; i < values.length; i += 1) {
|
|
41
|
+
if (values[i] - values[i - 1] !== interval) {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return { start: values[0], interval, last: values[values.length - 1] };
|
|
46
|
+
}
|
|
32
47
|
function toFieldNumber(token, numberMap) {
|
|
33
48
|
return isNonNegativeInteger(token) ? +token : numberMap[token.toUpperCase()];
|
|
34
49
|
}
|
|
@@ -57,6 +72,7 @@ var monthNumbers = {
|
|
|
57
72
|
NOV: 11,
|
|
58
73
|
DEC: 12
|
|
59
74
|
};
|
|
75
|
+
var maxClockTimes = 6;
|
|
60
76
|
|
|
61
77
|
// src/lang/zh/dialects.ts
|
|
62
78
|
var zh = { variant: "Hans" };
|
|
@@ -87,6 +103,46 @@ function stepSegment(ir, field) {
|
|
|
87
103
|
function cadence(interval, unit) {
|
|
88
104
|
return interval === 1 ? "\u6BCF" + unit : "\u6BCF" + interval + unit;
|
|
89
105
|
}
|
|
106
|
+
function renderStride(stride) {
|
|
107
|
+
const { interval, start, last, cycle, unit, mark, anchor } = stride;
|
|
108
|
+
const tiles = cycle % interval === 0;
|
|
109
|
+
if (start === 0 && tiles) {
|
|
110
|
+
return cadence(interval, unit);
|
|
111
|
+
}
|
|
112
|
+
const lead = anchor + "\u4ECE" + start + mark + "\u8D77" + cadence(interval, unit);
|
|
113
|
+
return start < interval && tiles ? lead : lead + "\uFF0C\u81F3" + last + mark;
|
|
114
|
+
}
|
|
115
|
+
function singleValues(segments) {
|
|
116
|
+
const values = [];
|
|
117
|
+
for (const segment of segments) {
|
|
118
|
+
if (segment.kind !== "single") {
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
values.push(+segment.value);
|
|
122
|
+
}
|
|
123
|
+
return values;
|
|
124
|
+
}
|
|
125
|
+
function strideFromSegments(segments, unit, mark, anchor) {
|
|
126
|
+
const values = singleValues(segments);
|
|
127
|
+
const step = values && arithmeticStep(values);
|
|
128
|
+
return step ? renderStride({ ...step, cycle: 60, unit, mark, anchor }) : null;
|
|
129
|
+
}
|
|
130
|
+
function stepClause(segment, unit, mark, anchor) {
|
|
131
|
+
const start = segment.startToken === "*" ? 0 : +segment.startToken;
|
|
132
|
+
const short = start !== 0 && segment.fires.length <= 3;
|
|
133
|
+
if (segment.startToken.indexOf("-") !== -1 || short) {
|
|
134
|
+
return anchor + segment.fires.join("\u3001") + mark;
|
|
135
|
+
}
|
|
136
|
+
return renderStride({
|
|
137
|
+
interval: segment.interval,
|
|
138
|
+
start,
|
|
139
|
+
last: segment.fires[segment.fires.length - 1],
|
|
140
|
+
cycle: 60,
|
|
141
|
+
unit,
|
|
142
|
+
mark,
|
|
143
|
+
anchor
|
|
144
|
+
});
|
|
145
|
+
}
|
|
90
146
|
function dayPeriod(hour) {
|
|
91
147
|
if (hour < 6) {
|
|
92
148
|
return "\u51CC\u6668";
|
|
@@ -183,8 +239,15 @@ function renderEveryMinute() {
|
|
|
183
239
|
function renderEveryHour() {
|
|
184
240
|
return "\u6BCF\u5C0F\u65F6";
|
|
185
241
|
}
|
|
242
|
+
function minuteHourClause(ir) {
|
|
243
|
+
const segments = fieldSegments(ir, "minute");
|
|
244
|
+
if (ir.shapes.minute === "step") {
|
|
245
|
+
return stepClause(stepSegment(ir, "minute"), "\u5206\u949F", "\u5206", "\u6BCF\u5C0F\u65F6");
|
|
246
|
+
}
|
|
247
|
+
return strideFromSegments(segments, "\u5206\u949F", "\u5206", "\u6BCF\u5C0F\u65F6") ?? "\u6BCF\u5C0F\u65F6" + valueList(segments, "\u5206");
|
|
248
|
+
}
|
|
186
249
|
function renderMinutePast(ir) {
|
|
187
|
-
return
|
|
250
|
+
return minuteHourClause(ir);
|
|
188
251
|
}
|
|
189
252
|
function hourList(ir) {
|
|
190
253
|
return joinAnd(hourFires(ir).map(hourWord));
|
|
@@ -198,7 +261,7 @@ function hourFrame(ir) {
|
|
|
198
261
|
}
|
|
199
262
|
function renderMinuteFrequency(ir, plan) {
|
|
200
263
|
const minuteStep = stepSegment(ir, "minute");
|
|
201
|
-
const base =
|
|
264
|
+
const base = stepClause(minuteStep, UNITS.minute, "\u5206", "\u6BCF\u5C0F\u65F6");
|
|
202
265
|
const { hours } = plan;
|
|
203
266
|
if (hours.kind === "step") {
|
|
204
267
|
const hourStep = stepSegment(ir, "hour");
|
|
@@ -227,12 +290,15 @@ function renderMinutesAcrossHours(ir, plan) {
|
|
|
227
290
|
if (form === "wildcard") {
|
|
228
291
|
return "\u5728" + hourList(ir) + "\uFF0C\u6BCF\u5206\u949F";
|
|
229
292
|
}
|
|
230
|
-
return hourList(ir) + "\uFF0C
|
|
293
|
+
return hourList(ir) + "\uFF0C" + minuteHourClause(ir) + "\uFF0C\u6BCF\u5206\u949F";
|
|
231
294
|
}
|
|
232
295
|
function renderMinuteSpanAcrossHourStep(ir, plan) {
|
|
233
296
|
const hourStep = stepSegment(ir, "hour");
|
|
234
297
|
const { form } = plan;
|
|
235
|
-
|
|
298
|
+
if (form === "list") {
|
|
299
|
+
return renderMinutePast(ir) + "\uFF0C\u5728" + hourList(ir);
|
|
300
|
+
}
|
|
301
|
+
const minuteTail = form === "wildcard" ? "\u6BCF\u5206\u949F" : minuteHourClause(ir) + "\uFF0C\u6BCF\u5206\u949F";
|
|
236
302
|
if (hourStep.startToken !== "*") {
|
|
237
303
|
return form === "wildcard" ? "\u5728" + hourList(ir) + "\uFF0C" + minuteTail : hourList(ir) + "\uFF0C" + minuteTail;
|
|
238
304
|
}
|
|
@@ -243,15 +309,27 @@ function renderMinuteSpanAcrossHourStep(ir, plan) {
|
|
|
243
309
|
return form === "wildcard" ? cad + "\u5185\uFF0C" + minuteTail : cad + "\uFF0C" + minuteTail;
|
|
244
310
|
}
|
|
245
311
|
function renderClockTimes(ir, plan, opts) {
|
|
312
|
+
if (ir.shapes.minute === "single") {
|
|
313
|
+
const cad = hourCadence(ir);
|
|
314
|
+
if (cad !== null) {
|
|
315
|
+
return cad;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
246
318
|
const { times } = plan;
|
|
247
319
|
return joinAnd(times.map((t) => clockTime(t.hour, t.minute, t.second, opts)));
|
|
248
320
|
}
|
|
249
321
|
function renderCompactClockTimes(ir, plan) {
|
|
322
|
+
if (ir.shapes.minute === "single") {
|
|
323
|
+
const cad = hourCadence(ir);
|
|
324
|
+
if (cad !== null) {
|
|
325
|
+
return cad;
|
|
326
|
+
}
|
|
327
|
+
}
|
|
250
328
|
const { minute } = plan;
|
|
251
329
|
const secs = fieldSegments(ir, "second");
|
|
252
330
|
const tail = secs.length && ir.pattern.second !== "0" ? "\uFF0C\u7B2C" + valueText(secs) + "\u79D2" : "";
|
|
253
331
|
if (minute > 0) {
|
|
254
|
-
return
|
|
332
|
+
return minuteHourClause(ir) + "\uFF0C\u5728" + hourList(ir) + tail;
|
|
255
333
|
}
|
|
256
334
|
return hourList(ir) + tail;
|
|
257
335
|
}
|
|
@@ -259,7 +337,7 @@ function renderHourRange(ir, plan) {
|
|
|
259
337
|
const range = plan;
|
|
260
338
|
if (range.minuteForm === "lead") {
|
|
261
339
|
const minuteSegs = fieldSegments(ir, "minute");
|
|
262
|
-
const past = minuteSegs.length && ir.pattern.minute !== "0" ?
|
|
340
|
+
const past = minuteSegs.length && ir.pattern.minute !== "0" ? minuteHourClause(ir) : "\u6BCF\u5C0F\u65F6";
|
|
263
341
|
return "\u5728" + hourWord(range.from) + "\u81F3" + hourWord(range.to) + "\u4E4B\u95F4\uFF0C" + past;
|
|
264
342
|
}
|
|
265
343
|
if (range.minuteForm === "range") {
|
|
@@ -277,8 +355,52 @@ function renderHourStep(ir) {
|
|
|
277
355
|
}
|
|
278
356
|
return cadence(segment.interval, UNITS.hour);
|
|
279
357
|
}
|
|
358
|
+
function hourStride(ir) {
|
|
359
|
+
const segments = fieldSegments(ir, "hour");
|
|
360
|
+
if (segments.length === 1 && segments[0].kind === "step") {
|
|
361
|
+
const segment = segments[0];
|
|
362
|
+
const start = segment.startToken === "*" ? 0 : +segment.startToken;
|
|
363
|
+
if (start !== 0 || 24 % segment.interval !== 0) {
|
|
364
|
+
return null;
|
|
365
|
+
}
|
|
366
|
+
return {
|
|
367
|
+
interval: segment.interval,
|
|
368
|
+
last: segment.fires[segment.fires.length - 1]
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
const values = singleValues(segments);
|
|
372
|
+
const step = values && arithmeticStep(values);
|
|
373
|
+
if (!step || step.start !== 0 || 24 % step.interval !== 0) {
|
|
374
|
+
return null;
|
|
375
|
+
}
|
|
376
|
+
return { interval: step.interval, last: step.last };
|
|
377
|
+
}
|
|
378
|
+
function hourCadence(ir) {
|
|
379
|
+
const stride = hourStride(ir);
|
|
380
|
+
if (!stride) {
|
|
381
|
+
return null;
|
|
382
|
+
}
|
|
383
|
+
const fires = stride.last / stride.interval + 1;
|
|
384
|
+
if (ir.pattern.second === "0" && fires <= maxClockTimes) {
|
|
385
|
+
return null;
|
|
386
|
+
}
|
|
387
|
+
const prefix = cadence(stride.interval, UNITS.hour);
|
|
388
|
+
const minute = +ir.pattern.minute;
|
|
389
|
+
const subMinute = ir.pattern.second === "*" || ir.shapes.second === "step";
|
|
390
|
+
if (minute === 0 && subMinute) {
|
|
391
|
+
return stride.interval === 2 ? "\u5728\u5076\u6570\u5C0F\u65F60\u5206" + secondTail(ir) : null;
|
|
392
|
+
}
|
|
393
|
+
if (minute === 0) {
|
|
394
|
+
return prefix + "0\u5206" + secondTail(ir);
|
|
395
|
+
}
|
|
396
|
+
return ir.pattern.second === "0" ? prefix + minute + "\u5206" : prefix + minute + "\u5206" + secondTail(ir);
|
|
397
|
+
}
|
|
398
|
+
function secondTail(ir) {
|
|
399
|
+
const sec = secondClause(ir);
|
|
400
|
+
return sec === "\u6BCF\u79D2" ? "\u7684\u6BCF\u4E00\u79D2" : "\u7684" + sec;
|
|
401
|
+
}
|
|
280
402
|
function renderRangeOfMinutes(ir) {
|
|
281
|
-
return
|
|
403
|
+
return minuteHourClause(ir) + "\uFF0C\u6BCF\u5206\u949F";
|
|
282
404
|
}
|
|
283
405
|
function renderStandaloneSeconds(ir) {
|
|
284
406
|
const segs = fieldSegments(ir, "second");
|
|
@@ -286,7 +408,7 @@ function renderStandaloneSeconds(ir) {
|
|
|
286
408
|
if (segs.length === 1 && first.kind === "step" && first.startToken === "*") {
|
|
287
409
|
return cadence(first.interval, UNITS.second);
|
|
288
410
|
}
|
|
289
|
-
return "\u6BCF\u5206\u949F\u7B2C" + valueText(segs) + "\u79D2";
|
|
411
|
+
return strideFromSegments(segs, "\u79D2", "\u79D2", "\u6BCF\u5206\u949F") ?? "\u6BCF\u5206\u949F\u7B2C" + valueText(segs) + "\u79D2";
|
|
290
412
|
}
|
|
291
413
|
function renderSecondPastMinute(ir) {
|
|
292
414
|
return "\u6BCF\u5206\u949F\u7B2C" + valueText(fieldSegments(ir, "second")) + "\u79D2";
|
|
@@ -309,7 +431,7 @@ function secondClause(ir) {
|
|
|
309
431
|
if (segs.length === 1 && first.kind === "step" && first.startToken === "*") {
|
|
310
432
|
return cadence(first.interval, UNITS.second);
|
|
311
433
|
}
|
|
312
|
-
return "\u7B2C" + valueText(segs) + "\u79D2";
|
|
434
|
+
return strideFromSegments(segs, "\u79D2", "\u79D2", "\u6BCF\u5206\u949F") ?? "\u7B2C" + valueText(segs) + "\u79D2";
|
|
313
435
|
}
|
|
314
436
|
function minuteClause(ir) {
|
|
315
437
|
if (ir.pattern.minute === "*") {
|
|
@@ -326,13 +448,15 @@ function isHourCadence(ir) {
|
|
|
326
448
|
function composeSecondsOnHour(ir, plan, opts) {
|
|
327
449
|
const sec = secondClause(ir);
|
|
328
450
|
const { rest } = plan;
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
451
|
+
const composedClock = rest.kind === "clockTimes" || rest.kind === "compactClockTimes";
|
|
452
|
+
if (composedClock) {
|
|
453
|
+
const hourCad = hourCadence(ir);
|
|
454
|
+
if (hourCad !== null) {
|
|
455
|
+
return hourCad;
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
if (composedClock && ir.pattern.minute === "0") {
|
|
459
|
+
return composeMinuteZeroClocks(ir, sec);
|
|
336
460
|
}
|
|
337
461
|
const restText = render(ir, rest, opts);
|
|
338
462
|
if (rest.kind === "clockTimes" || rest.kind === "compactClockTimes") {
|
|
@@ -345,6 +469,15 @@ function composeSecondsOnHour(ir, plan, opts) {
|
|
|
345
469
|
}
|
|
346
470
|
return restText + sec;
|
|
347
471
|
}
|
|
472
|
+
function composeMinuteZeroClocks(ir, sec) {
|
|
473
|
+
const clocks = hourFires(ir).map(function clock(hour) {
|
|
474
|
+
return hour === 12 ? "\u6B63\u5348" : hourWord(hour) + "0\u5206";
|
|
475
|
+
});
|
|
476
|
+
const nested = strideFromSegments(fieldSegments(ir, "second"), "\u79D2", "\u79D2", "");
|
|
477
|
+
const tail = sec === "\u6BCF\u79D2" ? "\u7684\u6BCF\u4E00\u79D2" : "\u7684" + (nested ?? sec);
|
|
478
|
+
const core = joinAnd(clocks) + tail;
|
|
479
|
+
return isDaily(ir) ? "\u6BCF\u5929" + core : core;
|
|
480
|
+
}
|
|
348
481
|
function composeSecondsCadence(ir) {
|
|
349
482
|
const sec = secondClause(ir);
|
|
350
483
|
const tail = minuteClause(ir) + sec;
|
|
@@ -355,15 +488,23 @@ function composeSecondsCadence(ir) {
|
|
|
355
488
|
return hourWord(hourFires(ir)[0]) + "\u7684" + tail;
|
|
356
489
|
}
|
|
357
490
|
if (ir.shapes.hour === "wildcard") {
|
|
491
|
+
if (ir.shapes.minute === "step" && sec === "\u6BCF\u79D2") {
|
|
492
|
+
const minuteStep = stepSegment(ir, "minute");
|
|
493
|
+
if (minuteStep.startToken === "*" && minuteStep.interval === 2) {
|
|
494
|
+
return "\u6BCF\u5076\u6570\u5206\u949F\u7684\u6BCF\u4E00\u79D2";
|
|
495
|
+
}
|
|
496
|
+
}
|
|
358
497
|
return sec + "\uFF0C" + minuteClause(ir);
|
|
359
498
|
}
|
|
360
499
|
return hourFrame(ir) + tail;
|
|
361
500
|
}
|
|
362
501
|
function composeSecondsListed(ir) {
|
|
363
502
|
const sec = secondClause(ir);
|
|
364
|
-
const minutes =
|
|
503
|
+
const minutes = minuteHourClause(ir);
|
|
365
504
|
if (ir.shapes.hour === "single" && sec === "\u6BCF\u79D2") {
|
|
366
|
-
|
|
505
|
+
const minuteSegs = fieldSegments(ir, "minute");
|
|
506
|
+
const minuteCad = strideFromSegments(minuteSegs, "\u5206\u949F", "\u5206", "") ?? valueList(minuteSegs, "\u5206");
|
|
507
|
+
return hourWord(hourFires(ir)[0]) + minuteCad + "\u7684\u6BCF\u4E00\u79D2";
|
|
367
508
|
}
|
|
368
509
|
if (ir.shapes.hour === "wildcard") {
|
|
369
510
|
return minutes + "\uFF0C" + sec;
|
|
@@ -580,11 +721,16 @@ function composeCadence(ir, core) {
|
|
|
580
721
|
function composeWindow(ir, core) {
|
|
581
722
|
return qualifier(ir) + core;
|
|
582
723
|
}
|
|
724
|
+
function hourCadenceApplies(ir) {
|
|
725
|
+
return ir.shapes.minute === "single" && hourCadence(ir) !== null;
|
|
726
|
+
}
|
|
583
727
|
function describe(ir, opts) {
|
|
584
728
|
const { kind } = ir.plan;
|
|
585
729
|
const core = render(ir, ir.plan, opts);
|
|
586
730
|
let composed = core;
|
|
587
|
-
if (
|
|
731
|
+
if (hourCadenceApplies(ir)) {
|
|
732
|
+
composed = composeCadence(ir, core);
|
|
733
|
+
} else if (kind === "clockTimes" || kind === "compactClockTimes" && ir.pattern.minute === "0") {
|
|
588
734
|
composed = composePoint(ir, core);
|
|
589
735
|
} else if (kind === "hourStep" || kind === "minuteFrequency" || kind === "minuteSpanAcrossHourStep" || kind === "compactClockTimes") {
|
|
590
736
|
composed = composeCadence(ir, core);
|