cronli5 0.1.2 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +89 -0
- package/cli.js +9 -0
- package/cronli5.min.js +2 -2
- package/dist/cronli5.cjs +280 -64
- package/dist/cronli5.js +280 -64
- package/dist/lang/de.cjs +227 -42
- package/dist/lang/de.js +227 -42
- package/dist/lang/en.cjs +216 -50
- package/dist/lang/en.js +216 -50
- package/dist/lang/es.cjs +259 -54
- package/dist/lang/es.js +259 -54
- package/dist/lang/fi.cjs +230 -69
- package/dist/lang/fi.js +230 -69
- package/dist/lang/zh.cjs +190 -19
- package/dist/lang/zh.js +190 -19
- package/package.json +3 -1
- package/src/core/analyze.ts +7 -0
- package/src/core/ir.ts +1 -1
- package/src/core/normalize.ts +94 -4
- package/src/core/util.ts +31 -1
- package/src/lang/de/index.ts +449 -46
- package/src/lang/en/index.ts +433 -63
- package/src/lang/es/index.ts +505 -63
- package/src/lang/fi/index.ts +455 -89
- package/src/lang/zh/index.ts +393 -30
- package/types/core/ir.d.ts +1 -1
- package/types/core/util.d.ts +6 -1
package/dist/lang/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,10 +261,11 @@ 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");
|
|
268
|
+
return hourStep.startToken === "*" ? cadence(hourStep.interval, UNITS.hour) + base : "\u5728" + hourList(ir) + "\uFF0C" + base;
|
|
205
269
|
}
|
|
206
270
|
if (hours.kind === "single" || hours.kind === "window" && hours.from === hours.to) {
|
|
207
271
|
return "\u5728" + hourWord(hours.from) + "\u81F3" + hours.from + "\u70B9" + hours.last + "\u5206\u4E4B\u95F4\uFF0C" + base;
|
|
@@ -216,6 +280,9 @@ function renderMinuteFrequency(ir, plan) {
|
|
|
216
280
|
}
|
|
217
281
|
function renderMinuteSpanInHour(ir, plan) {
|
|
218
282
|
const span = plan;
|
|
283
|
+
if (ir.pattern.minute === "*") {
|
|
284
|
+
return hourWord(span.hour) + "\u7684\u6BCF\u4E00\u5206\u949F";
|
|
285
|
+
}
|
|
219
286
|
return "\u5728" + hourWord(span.hour) + "\u81F3" + span.hour + "\u70B9" + span.span[1] + "\u5206\u4E4B\u95F4\uFF0C\u6BCF\u5206\u949F";
|
|
220
287
|
}
|
|
221
288
|
function renderMinutesAcrossHours(ir, plan) {
|
|
@@ -223,26 +290,46 @@ function renderMinutesAcrossHours(ir, plan) {
|
|
|
223
290
|
if (form === "wildcard") {
|
|
224
291
|
return "\u5728" + hourList(ir) + "\uFF0C\u6BCF\u5206\u949F";
|
|
225
292
|
}
|
|
226
|
-
return hourList(ir) + "\uFF0C
|
|
293
|
+
return hourList(ir) + "\uFF0C" + minuteHourClause(ir) + "\uFF0C\u6BCF\u5206\u949F";
|
|
227
294
|
}
|
|
228
295
|
function renderMinuteSpanAcrossHourStep(ir, plan) {
|
|
229
|
-
const
|
|
296
|
+
const hourStep = stepSegment(ir, "hour");
|
|
230
297
|
const { form } = plan;
|
|
231
|
-
if (form === "
|
|
232
|
-
return
|
|
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";
|
|
302
|
+
if (hourStep.startToken !== "*") {
|
|
303
|
+
return form === "wildcard" ? "\u5728" + hourList(ir) + "\uFF0C" + minuteTail : hourList(ir) + "\uFF0C" + minuteTail;
|
|
304
|
+
}
|
|
305
|
+
if (hourStep.interval === 2 && form === "wildcard") {
|
|
306
|
+
return "\u5728\u5076\u6570\u5C0F\u65F6\uFF0C" + minuteTail;
|
|
233
307
|
}
|
|
234
|
-
|
|
308
|
+
const cad = cadence(hourStep.interval, UNITS.hour);
|
|
309
|
+
return form === "wildcard" ? cad + "\u5185\uFF0C" + minuteTail : cad + "\uFF0C" + minuteTail;
|
|
235
310
|
}
|
|
236
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
|
+
}
|
|
237
318
|
const { times } = plan;
|
|
238
319
|
return joinAnd(times.map((t) => clockTime(t.hour, t.minute, t.second, opts)));
|
|
239
320
|
}
|
|
240
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
|
+
}
|
|
241
328
|
const { minute } = plan;
|
|
242
329
|
const secs = fieldSegments(ir, "second");
|
|
243
330
|
const tail = secs.length && ir.pattern.second !== "0" ? "\uFF0C\u7B2C" + valueText(secs) + "\u79D2" : "";
|
|
244
331
|
if (minute > 0) {
|
|
245
|
-
return
|
|
332
|
+
return minuteHourClause(ir) + "\uFF0C\u5728" + hourList(ir) + tail;
|
|
246
333
|
}
|
|
247
334
|
return hourList(ir) + tail;
|
|
248
335
|
}
|
|
@@ -250,7 +337,7 @@ function renderHourRange(ir, plan) {
|
|
|
250
337
|
const range = plan;
|
|
251
338
|
if (range.minuteForm === "lead") {
|
|
252
339
|
const minuteSegs = fieldSegments(ir, "minute");
|
|
253
|
-
const past = minuteSegs.length && ir.pattern.minute !== "0" ?
|
|
340
|
+
const past = minuteSegs.length && ir.pattern.minute !== "0" ? minuteHourClause(ir) : "\u6BCF\u5C0F\u65F6";
|
|
254
341
|
return "\u5728" + hourWord(range.from) + "\u81F3" + hourWord(range.to) + "\u4E4B\u95F4\uFF0C" + past;
|
|
255
342
|
}
|
|
256
343
|
if (range.minuteForm === "range") {
|
|
@@ -268,8 +355,52 @@ function renderHourStep(ir) {
|
|
|
268
355
|
}
|
|
269
356
|
return cadence(segment.interval, UNITS.hour);
|
|
270
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
|
+
}
|
|
271
402
|
function renderRangeOfMinutes(ir) {
|
|
272
|
-
return
|
|
403
|
+
return minuteHourClause(ir) + "\uFF0C\u6BCF\u5206\u949F";
|
|
273
404
|
}
|
|
274
405
|
function renderStandaloneSeconds(ir) {
|
|
275
406
|
const segs = fieldSegments(ir, "second");
|
|
@@ -277,7 +408,7 @@ function renderStandaloneSeconds(ir) {
|
|
|
277
408
|
if (segs.length === 1 && first.kind === "step" && first.startToken === "*") {
|
|
278
409
|
return cadence(first.interval, UNITS.second);
|
|
279
410
|
}
|
|
280
|
-
return "\u6BCF\u5206\u949F\u7B2C" + valueText(segs) + "\u79D2";
|
|
411
|
+
return strideFromSegments(segs, "\u79D2", "\u79D2", "\u6BCF\u5206\u949F") ?? "\u6BCF\u5206\u949F\u7B2C" + valueText(segs) + "\u79D2";
|
|
281
412
|
}
|
|
282
413
|
function renderSecondPastMinute(ir) {
|
|
283
414
|
return "\u6BCF\u5206\u949F\u7B2C" + valueText(fieldSegments(ir, "second")) + "\u79D2";
|
|
@@ -300,7 +431,7 @@ function secondClause(ir) {
|
|
|
300
431
|
if (segs.length === 1 && first.kind === "step" && first.startToken === "*") {
|
|
301
432
|
return cadence(first.interval, UNITS.second);
|
|
302
433
|
}
|
|
303
|
-
return "\u7B2C" + valueText(segs) + "\u79D2";
|
|
434
|
+
return strideFromSegments(segs, "\u79D2", "\u79D2", "\u6BCF\u5206\u949F") ?? "\u7B2C" + valueText(segs) + "\u79D2";
|
|
304
435
|
}
|
|
305
436
|
function minuteClause(ir) {
|
|
306
437
|
if (ir.pattern.minute === "*") {
|
|
@@ -317,15 +448,36 @@ function isHourCadence(ir) {
|
|
|
317
448
|
function composeSecondsOnHour(ir, plan, opts) {
|
|
318
449
|
const sec = secondClause(ir);
|
|
319
450
|
const { rest } = plan;
|
|
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);
|
|
460
|
+
}
|
|
320
461
|
const restText = render(ir, rest, opts);
|
|
321
|
-
if (
|
|
322
|
-
|
|
462
|
+
if (rest.kind === "clockTimes" || rest.kind === "compactClockTimes") {
|
|
463
|
+
if (isDaily(ir)) {
|
|
464
|
+
return "\u6BCF\u5929" + restText + sec;
|
|
465
|
+
}
|
|
323
466
|
}
|
|
324
467
|
if (rest.kind === "singleMinute") {
|
|
325
468
|
return restText + "\uFF0C" + sec;
|
|
326
469
|
}
|
|
327
470
|
return restText + sec;
|
|
328
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
|
+
}
|
|
329
481
|
function composeSecondsCadence(ir) {
|
|
330
482
|
const sec = secondClause(ir);
|
|
331
483
|
const tail = minuteClause(ir) + sec;
|
|
@@ -336,13 +488,24 @@ function composeSecondsCadence(ir) {
|
|
|
336
488
|
return hourWord(hourFires(ir)[0]) + "\u7684" + tail;
|
|
337
489
|
}
|
|
338
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
|
+
}
|
|
339
497
|
return sec + "\uFF0C" + minuteClause(ir);
|
|
340
498
|
}
|
|
341
499
|
return hourFrame(ir) + tail;
|
|
342
500
|
}
|
|
343
501
|
function composeSecondsListed(ir) {
|
|
344
502
|
const sec = secondClause(ir);
|
|
345
|
-
const minutes =
|
|
503
|
+
const minutes = minuteHourClause(ir);
|
|
504
|
+
if (ir.shapes.hour === "single" && sec === "\u6BCF\u79D2") {
|
|
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";
|
|
508
|
+
}
|
|
346
509
|
if (ir.shapes.hour === "wildcard") {
|
|
347
510
|
return minutes + "\uFF0C" + sec;
|
|
348
511
|
}
|
|
@@ -352,10 +515,13 @@ function composeSecondsListed(ir) {
|
|
|
352
515
|
return hourFrame(ir) + minutes + "\uFF0C" + sec;
|
|
353
516
|
}
|
|
354
517
|
function renderComposeSeconds(ir, plan, opts) {
|
|
355
|
-
|
|
518
|
+
const { rest } = plan;
|
|
519
|
+
const composedClock = rest.kind === "clockTimes" || rest.kind === "compactClockTimes";
|
|
520
|
+
if (ir.pattern.minute === "0" || composedClock && ir.shapes.minute === "single") {
|
|
356
521
|
return composeSecondsOnHour(ir, plan, opts);
|
|
357
522
|
}
|
|
358
|
-
|
|
523
|
+
const minuteCadence = ir.pattern.minute === "*" || ir.shapes.minute === "step" && stepSegment(ir, "minute").startToken === "*";
|
|
524
|
+
if (minuteCadence) {
|
|
359
525
|
return composeSecondsCadence(ir);
|
|
360
526
|
}
|
|
361
527
|
return composeSecondsListed(ir);
|
|
@@ -555,11 +721,16 @@ function composeCadence(ir, core) {
|
|
|
555
721
|
function composeWindow(ir, core) {
|
|
556
722
|
return qualifier(ir) + core;
|
|
557
723
|
}
|
|
724
|
+
function hourCadenceApplies(ir) {
|
|
725
|
+
return ir.shapes.minute === "single" && hourCadence(ir) !== null;
|
|
726
|
+
}
|
|
558
727
|
function describe(ir, opts) {
|
|
559
728
|
const { kind } = ir.plan;
|
|
560
729
|
const core = render(ir, ir.plan, opts);
|
|
561
730
|
let composed = core;
|
|
562
|
-
if (
|
|
731
|
+
if (hourCadenceApplies(ir)) {
|
|
732
|
+
composed = composeCadence(ir, core);
|
|
733
|
+
} else if (kind === "clockTimes" || kind === "compactClockTimes" && ir.pattern.minute === "0") {
|
|
563
734
|
composed = composePoint(ir, core);
|
|
564
735
|
} else if (kind === "hourStep" || kind === "minuteFrequency" || kind === "minuteSpanAcrossHourStep" || kind === "compactClockTimes") {
|
|
565
736
|
composed = composeCadence(ir, core);
|