cronli5 0.1.5 → 0.1.6
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 +28 -0
- package/cronli5.min.js +2 -2
- package/dist/cronli5.cjs +117 -20
- package/dist/cronli5.js +117 -20
- package/dist/lang/de.cjs +94 -19
- package/dist/lang/de.js +94 -19
- package/dist/lang/en.cjs +117 -20
- package/dist/lang/en.js +117 -20
- package/dist/lang/es.cjs +89 -14
- package/dist/lang/es.js +89 -14
- package/dist/lang/fi.cjs +107 -19
- package/dist/lang/fi.js +107 -19
- package/dist/lang/zh.cjs +90 -53
- package/dist/lang/zh.js +90 -53
- package/package.json +2 -2
- package/src/lang/de/index.ts +238 -51
- package/src/lang/en/index.ts +280 -46
- package/src/lang/es/index.ts +222 -31
- package/src/lang/fi/index.ts +245 -39
- package/src/lang/zh/index.ts +209 -94
package/src/lang/es/index.ts
CHANGED
|
@@ -259,9 +259,24 @@ function composeHourCadence(
|
|
|
259
259
|
const clockRest = plan.rest.kind === 'clockTimes' ||
|
|
260
260
|
plan.rest.kind === 'compactClockTimes';
|
|
261
261
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
262
|
+
if (!clockRest || ir.shapes.minute !== 'single') {
|
|
263
|
+
return null;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
const minute = +ir.pattern.minute;
|
|
267
|
+
|
|
268
|
+
return hourCadence(ir, minute, opts) ?? hourRangeCadence(ir, minute, opts);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// A wildcard or stepped second with a fixed minute across one or more specific
|
|
272
|
+
// hours: the seconds confine to the clock time(s), each minute named.
|
|
273
|
+
function isPinnedMinuteSeconds(
|
|
274
|
+
ir: IR,
|
|
275
|
+
plan: Extract<PlanNode, {kind: 'composeSeconds'}>
|
|
276
|
+
): plan is Extract<PlanNode, {kind: 'composeSeconds'}> &
|
|
277
|
+
{rest: Extract<PlanNode, {kind: 'clockTimes'}>} {
|
|
278
|
+
return plan.rest.kind === 'clockTimes' &&
|
|
279
|
+
(ir.shapes.second === 'wildcard' || ir.shapes.second === 'step');
|
|
265
280
|
}
|
|
266
281
|
|
|
267
282
|
function renderComposeSeconds(
|
|
@@ -281,8 +296,7 @@ function renderComposeSeconds(
|
|
|
281
296
|
|
|
282
297
|
// A wildcard or stepped second with the minute pinned to a single value
|
|
283
298
|
// across one or more specific hours: the seconds confine to the clock time.
|
|
284
|
-
if (plan
|
|
285
|
-
(ir.shapes.second === 'wildcard' || ir.shapes.second === 'step')) {
|
|
299
|
+
if (isPinnedMinuteSeconds(ir, plan)) {
|
|
286
300
|
return pinnedMinuteSeconds(ir, plan.rest, opts);
|
|
287
301
|
}
|
|
288
302
|
|
|
@@ -317,7 +331,15 @@ function renderComposeSeconds(
|
|
|
317
331
|
return secondsLeadClause(ir, opts) + ' de ' + render(ir, plan.rest, opts);
|
|
318
332
|
}
|
|
319
333
|
|
|
320
|
-
|
|
334
|
+
// A compact clock-time rest folds a meaningful SINGLE second into its own
|
|
335
|
+
// leading clause, so the composer must not prepend a second lead that would
|
|
336
|
+
// double it. A wildcard or stepped second is not folded there (no
|
|
337
|
+
// clockSecond), so it still leads its own clause here.
|
|
338
|
+
const restOwnsLead = plan.rest.kind === 'compactClockTimes' &&
|
|
339
|
+
ir.analyses.clockSecond;
|
|
340
|
+
const lead = restOwnsLead ? '' : secondsLeadClause(ir, opts) + ', ';
|
|
341
|
+
|
|
342
|
+
return lead + render(ir, plan.rest, opts);
|
|
321
343
|
}
|
|
322
344
|
|
|
323
345
|
// A wildcard second over an unoffset minute */2 with a wildcard hour: the two
|
|
@@ -354,7 +376,12 @@ function pinnedMinuteSeconds(
|
|
|
354
376
|
const dayTrail = leadingQualifier(ir, opts).trimEnd();
|
|
355
377
|
const trail = dayTrail ? ', ' + dayTrail : '';
|
|
356
378
|
|
|
357
|
-
|
|
379
|
+
// The "durante un minuto a las 9" duration form drops the clock minute, so it
|
|
380
|
+
// is correct only when the minute is a SINGLE 0 — every clock time at :00. A
|
|
381
|
+
// minute LIST whose first value is 0 (e.g. */45 → :00, :45) must name each
|
|
382
|
+
// minute, never collapse to the bare hour (which once repeated it, "a las 9 y
|
|
383
|
+
// 9"), so it takes the explicit clock list.
|
|
384
|
+
if (+rest.times[0].minute === 0 && ir.shapes.minute === 'single') {
|
|
358
385
|
return secondsLeadClause(ir, opts) + ' durante un minuto ' +
|
|
359
386
|
durationHourList(rest.times, opts) + trail;
|
|
360
387
|
}
|
|
@@ -555,11 +582,20 @@ function renderMinuteFrequency(
|
|
|
555
582
|
'hora', opts);
|
|
556
583
|
|
|
557
584
|
if (plan.hours.kind === 'during') {
|
|
558
|
-
//
|
|
559
|
-
//
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
585
|
+
// A uneven hour stride confines the minute cadence to its own bounded hour
|
|
586
|
+
// cadence ("cada 15 minutos, cada cinco horas de las 00:00 a las 20:00").
|
|
587
|
+
const cadence = unevenHourCadence(ir, opts);
|
|
588
|
+
|
|
589
|
+
if (cadence) {
|
|
590
|
+
phrase += ', ' + cadence;
|
|
591
|
+
}
|
|
592
|
+
else {
|
|
593
|
+
// An offset step (e.g. 1/2) arrives here; a single step reads as a
|
|
594
|
+
// confinement, not the verbose window list.
|
|
595
|
+
phrase += singleHourStep(ir.analyses.segments.hour) ?
|
|
596
|
+
', ' + stepHourSpan(stepSegment(ir.analyses.segments.hour), opts) :
|
|
597
|
+
' ' + hourSpanFromTimes(ir, plan.hours.times, opts);
|
|
598
|
+
}
|
|
563
599
|
}
|
|
564
600
|
else if (plan.hours.kind === 'window') {
|
|
565
601
|
phrase += ' ' + hourWindow(plan.hours, opts);
|
|
@@ -602,7 +638,15 @@ function renderMinutesAcrossHours(
|
|
|
602
638
|
plan: Extract<PlanNode, {kind: 'minutesAcrossHours'}>,
|
|
603
639
|
opts: Opts
|
|
604
640
|
): string {
|
|
641
|
+
// A uneven hour stride reads as a cadence, not a wall of hour columns: the
|
|
642
|
+
// minute lead, then "cada N horas de las X a las Y".
|
|
643
|
+
const cadence = unevenHourCadence(ir, opts);
|
|
644
|
+
|
|
605
645
|
if (plan.form === 'wildcard') {
|
|
646
|
+
if (cadence !== null) {
|
|
647
|
+
return 'cada minuto, ' + cadence + trailingQualifier(ir, opts);
|
|
648
|
+
}
|
|
649
|
+
|
|
606
650
|
if (singleHourStep(ir.analyses.segments.hour)) {
|
|
607
651
|
return 'cada minuto, ' +
|
|
608
652
|
stepHourSpan(stepSegment(ir.analyses.segments.hour), opts) +
|
|
@@ -617,6 +661,10 @@ function renderMinutesAcrossHours(
|
|
|
617
661
|
minuteRangeLead(ir.pattern.minute) :
|
|
618
662
|
minutesList(ir, opts);
|
|
619
663
|
|
|
664
|
+
if (cadence !== null) {
|
|
665
|
+
return lead + ', ' + cadence + trailingQualifier(ir, opts);
|
|
666
|
+
}
|
|
667
|
+
|
|
620
668
|
return lead + ', ' + atHourTimes(ir, plan.times, opts) +
|
|
621
669
|
trailingQualifier(ir, opts);
|
|
622
670
|
}
|
|
@@ -627,9 +675,12 @@ function renderMinuteSpanAcrossHourStep(
|
|
|
627
675
|
opts: Opts
|
|
628
676
|
): string {
|
|
629
677
|
const segment = stepSegment(ir.analyses.segments.hour);
|
|
678
|
+
// A bounded or uneven hour step reads as its endpoint-pinning cadence; an
|
|
679
|
+
// offset-clean step keeps its confinement / per-step phrasing.
|
|
680
|
+
const cadence = unevenHourCadence(ir, opts);
|
|
630
681
|
|
|
631
|
-
// A wildcard minute (a cadence) is reached only for a clean stride
|
|
632
|
-
//
|
|
682
|
+
// A wildcard minute (a cadence) is reached only for a clean stride (a bounded
|
|
683
|
+
// or uneven step routes through minutesAcrossHours instead) and is confined.
|
|
633
684
|
if (plan.form === 'wildcard') {
|
|
634
685
|
return 'cada minuto, ' + stepHourSpan(segment, opts) +
|
|
635
686
|
trailingQualifier(ir, opts);
|
|
@@ -642,7 +693,8 @@ function renderMinuteSpanAcrossHourStep(
|
|
|
642
693
|
minutesList(ir, opts) :
|
|
643
694
|
minuteRangeLead(ir.pattern.minute);
|
|
644
695
|
|
|
645
|
-
return lead + ', ' +
|
|
696
|
+
return lead + ', ' +
|
|
697
|
+
(cadence ?? stepHours(segment, opts)) + trailingQualifier(ir, opts);
|
|
646
698
|
}
|
|
647
699
|
|
|
648
700
|
// --- Hour renderers. ---
|
|
@@ -689,6 +741,15 @@ function renderHourStep(
|
|
|
689
741
|
plan: Extract<PlanNode, {kind: 'hourStep'}>,
|
|
690
742
|
opts: Opts
|
|
691
743
|
): string {
|
|
744
|
+
// A bounded or uneven hour step reads as its endpoint-pinning cadence ("cada
|
|
745
|
+
// dos horas de las 09:00 a las 17:00"); an offset-clean step keeps its bare
|
|
746
|
+
// or "a partir de" cadence.
|
|
747
|
+
const cadence = unevenHourCadence(ir, opts);
|
|
748
|
+
|
|
749
|
+
if (cadence !== null) {
|
|
750
|
+
return cadence + trailingQualifier(ir, opts);
|
|
751
|
+
}
|
|
752
|
+
|
|
692
753
|
return stepHours(stepSegment(ir.analyses.segments.hour), opts) +
|
|
693
754
|
trailingQualifier(ir, opts);
|
|
694
755
|
}
|
|
@@ -817,10 +878,13 @@ function renderClockTimes(
|
|
|
817
878
|
plan: Extract<PlanNode, {kind: 'clockTimes'}>,
|
|
818
879
|
opts: Opts
|
|
819
880
|
): string {
|
|
820
|
-
// An hour step (or arithmetic-progression hour list) under a single
|
|
821
|
-
// minute reads as a cadence rather than a cross-product of
|
|
881
|
+
// An hour step or range (or arithmetic-progression hour list) under a single
|
|
882
|
+
// pinned minute reads as a cadence or window rather than a cross-product of
|
|
883
|
+
// clock times.
|
|
822
884
|
if (ir.shapes.minute === 'single') {
|
|
823
|
-
const
|
|
885
|
+
const minute = +ir.pattern.minute;
|
|
886
|
+
const cadence = hourCadence(ir, minute, opts) ??
|
|
887
|
+
hourRangeCadence(ir, minute, opts);
|
|
824
888
|
|
|
825
889
|
if (cadence !== null) {
|
|
826
890
|
return cadence;
|
|
@@ -1162,10 +1226,11 @@ function renderCompactClockTimes(
|
|
|
1162
1226
|
opts: Opts
|
|
1163
1227
|
): string {
|
|
1164
1228
|
if (plan.fold) {
|
|
1165
|
-
// An hour step (or arithmetic-progression hour list) under the
|
|
1166
|
-
// pinned minute reads as a cadence, not a wall of clock
|
|
1167
|
-
// null for an irregular list
|
|
1168
|
-
const cadence = hourCadence(ir, plan.minute, opts)
|
|
1229
|
+
// An hour step or range (or arithmetic-progression hour list) under the
|
|
1230
|
+
// single pinned minute reads as a cadence or window, not a wall of clock
|
|
1231
|
+
// times. (Returns null for an irregular list, which keeps folding below.)
|
|
1232
|
+
const cadence = hourCadence(ir, plan.minute, opts) ??
|
|
1233
|
+
hourRangeCadence(ir, plan.minute, opts);
|
|
1169
1234
|
|
|
1170
1235
|
if (cadence !== null) {
|
|
1171
1236
|
return cadence;
|
|
@@ -1187,8 +1252,13 @@ function renderCompactClockTimes(
|
|
|
1187
1252
|
hourSegmentTimes(ir, plan.minute, ir.analyses.clockSecond, opts);
|
|
1188
1253
|
}
|
|
1189
1254
|
|
|
1190
|
-
|
|
1191
|
-
|
|
1255
|
+
// A uneven hour stride reads as a cadence after the minute lead, not a wall
|
|
1256
|
+
// of clock-time columns.
|
|
1257
|
+
const cadence = unevenHourCadence(ir, opts);
|
|
1258
|
+
const phrase = cadence ?
|
|
1259
|
+
minutesList(ir, opts) + ', ' + cadence + trailingQualifier(ir, opts) :
|
|
1260
|
+
minutesList(ir, opts) + ', ' +
|
|
1261
|
+
hourSegmentTimes(ir, 0, null, opts) + trailingQualifier(ir, opts);
|
|
1192
1262
|
|
|
1193
1263
|
return ir.analyses.clockSecond ?
|
|
1194
1264
|
secondsLeadClause(ir, opts) + ', ' + phrase :
|
|
@@ -1373,12 +1443,75 @@ function hourStrideCadence(
|
|
|
1373
1443
|
timePhrase(last, 0, null, opts);
|
|
1374
1444
|
}
|
|
1375
1445
|
|
|
1446
|
+
// Whether an hour stride wraps the day cleanly from within its first interval
|
|
1447
|
+
// (a `*/n` from the top, or a `m/n` offset with m < n that divides 24): such a
|
|
1448
|
+
// stride has no distinct endpoint and keeps its bare or "a partir de" cadence.
|
|
1449
|
+
// Every other stride — a uneven interval, or one starting at or past its
|
|
1450
|
+
// interval (a bounded `a-b/n`) — is a bounded set the cadence pins the ends of.
|
|
1451
|
+
function offsetCleanStride(
|
|
1452
|
+
stride: {start: number; interval: number}
|
|
1453
|
+
): boolean {
|
|
1454
|
+
return stride.start < stride.interval && 24 % stride.interval === 0;
|
|
1455
|
+
}
|
|
1456
|
+
|
|
1457
|
+
// The bounded cadence for an hour stride that pins both clock-time endpoints,
|
|
1458
|
+
// or null when the hour is not such a stride. The core rewrites a uneven step
|
|
1459
|
+
// to its fire list, so a minute window/list/step crossed with it lands in the
|
|
1460
|
+
// enumerating list paths; there the bounded hour reads better as its cadence
|
|
1461
|
+
// ("…, cada cinco horas de las 00:00 a las 20:00") than as a wall of clock
|
|
1462
|
+
// times. An offset-clean stride keeps its existing confinement form, so only
|
|
1463
|
+
// the endpoint-bearing case routes here.
|
|
1464
|
+
function unevenHourCadence(ir: IR, opts: Opts): string | null {
|
|
1465
|
+
const stride = hourStride(ir);
|
|
1466
|
+
|
|
1467
|
+
if (!stride || offsetCleanStride(stride)) {
|
|
1468
|
+
return null;
|
|
1469
|
+
}
|
|
1470
|
+
|
|
1471
|
+
return hourStrideCadence(stride, opts);
|
|
1472
|
+
}
|
|
1473
|
+
|
|
1474
|
+
// An hour list's arithmetic progression, or null when its values are not a
|
|
1475
|
+
// step the renderer should speak as a cadence. The core rewrites a uneven hour
|
|
1476
|
+
// step (whose interval does not tile 24, e.g. `*/5` → 0,5,10,15,20) to its
|
|
1477
|
+
// literal fire list, indistinguishable in the IR from a hand-written list; the
|
|
1478
|
+
// renderer recovers the cadence from the values. A progression starting at zero
|
|
1479
|
+
// is a `*/n` step however short (0,7,14,21 is `*/7`); a non-zero progression is
|
|
1480
|
+
// only a step when it is too long to be a deliberate clock-time list (e.g. 9,17
|
|
1481
|
+
// is two named times, not a cadence). Interval one is a plain range, never a
|
|
1482
|
+
// step.
|
|
1483
|
+
function hourListStride(
|
|
1484
|
+
values: number[]
|
|
1485
|
+
): {start: number; interval: number; last: number} | null {
|
|
1486
|
+
if (values.length < 2) {
|
|
1487
|
+
return null;
|
|
1488
|
+
}
|
|
1489
|
+
|
|
1490
|
+
const interval = values[1] - values[0];
|
|
1491
|
+
|
|
1492
|
+
if (interval < 2) {
|
|
1493
|
+
return null;
|
|
1494
|
+
}
|
|
1495
|
+
|
|
1496
|
+
for (let i = 2; i < values.length; i += 1) {
|
|
1497
|
+
if (values[i] - values[i - 1] !== interval) {
|
|
1498
|
+
return null;
|
|
1499
|
+
}
|
|
1500
|
+
}
|
|
1501
|
+
|
|
1502
|
+
if (values[0] !== 0 && values.length < 5) {
|
|
1503
|
+
return null;
|
|
1504
|
+
}
|
|
1505
|
+
|
|
1506
|
+
return {interval, last: values[values.length - 1], start: values[0]};
|
|
1507
|
+
}
|
|
1508
|
+
|
|
1376
1509
|
// The hour field's stride, or null when the hour is not a cadence: a step
|
|
1377
1510
|
// segment yields its {start, interval, last} directly; an all-single hour
|
|
1378
|
-
// list yields one only when its values form a
|
|
1379
|
-
//
|
|
1380
|
-
//
|
|
1381
|
-
//
|
|
1511
|
+
// list yields one only when its values form a step progression (so an irregular
|
|
1512
|
+
// list like 9,17 keeps enumerating). The IR is unchanged — the renderer
|
|
1513
|
+
// recognizes the stride and speaks it as a cadence instead of the clock-time
|
|
1514
|
+
// cross-product.
|
|
1382
1515
|
function hourStride(
|
|
1383
1516
|
ir: IR
|
|
1384
1517
|
): {start: number; interval: number; last: number} | null {
|
|
@@ -1386,6 +1519,13 @@ function hourStride(
|
|
|
1386
1519
|
|
|
1387
1520
|
if (segments.length === 1 && segments[0].kind === 'step') {
|
|
1388
1521
|
const segment = segments[0];
|
|
1522
|
+
|
|
1523
|
+
// A bounded step that fires only once (e.g. `9-10/5` -> just 9) is a single
|
|
1524
|
+
// value, not a stride: it has no interval to speak and no endpoint to pin.
|
|
1525
|
+
if (segment.fires.length < 2) {
|
|
1526
|
+
return null;
|
|
1527
|
+
}
|
|
1528
|
+
|
|
1389
1529
|
const start = segment.startToken === '*' ?
|
|
1390
1530
|
0 :
|
|
1391
1531
|
+segment.startToken.split('-')[0];
|
|
@@ -1395,9 +1535,8 @@ function hourStride(
|
|
|
1395
1535
|
}
|
|
1396
1536
|
|
|
1397
1537
|
const values = singleValues(segments);
|
|
1398
|
-
const step = values && arithmeticStep(values);
|
|
1399
1538
|
|
|
1400
|
-
return
|
|
1539
|
+
return values && hourListStride(values);
|
|
1401
1540
|
}
|
|
1402
1541
|
|
|
1403
1542
|
// The second's status against a pinned minute: a wildcard or sub-minute step
|
|
@@ -1452,7 +1591,13 @@ function hourCadence(ir: IR, minute: number, opts: Opts): string | null {
|
|
|
1452
1591
|
|
|
1453
1592
|
const fires = (stride.last - stride.start) / stride.interval + 1;
|
|
1454
1593
|
|
|
1455
|
-
|
|
1594
|
+
// A short stride that spells out as few clock times stays an enumeration only
|
|
1595
|
+
// when it wraps cleanly (an offset-clean stride with no endpoint): the bare
|
|
1596
|
+
// or "a partir de" form is no shorter than the list. A bounded or uneven
|
|
1597
|
+
// stride has no clean wrap, so its endpoint-pinning cadence ("cada cinco
|
|
1598
|
+
// horas de las 00:00 a las 20:00") reads better however short.
|
|
1599
|
+
if (ir.pattern.second === '0' && fires <= maxClockTimes &&
|
|
1600
|
+
offsetCleanStride(stride)) {
|
|
1456
1601
|
return null;
|
|
1457
1602
|
}
|
|
1458
1603
|
|
|
@@ -1468,6 +1613,13 @@ function hourCadence(ir: IR, minute: number, opts: Opts): string | null {
|
|
|
1468
1613
|
stepHourSpan(confinement, opts) + trailingQualifier(ir, opts);
|
|
1469
1614
|
}
|
|
1470
1615
|
|
|
1616
|
+
// A plain top-of-the-hour fire (minute 0 with no meaningful second) has no
|
|
1617
|
+
// lead clause to fold in, so the bounded cadence stands on its own ("cada
|
|
1618
|
+
// cinco horas de las 00:00 a las 20:00").
|
|
1619
|
+
if (minute === 0 && ir.pattern.second === '0') {
|
|
1620
|
+
return hourStrideCadence(stride, opts) + trailingQualifier(ir, opts);
|
|
1621
|
+
}
|
|
1622
|
+
|
|
1471
1623
|
return hourCadenceLead(ir, minute, opts) + ', ' +
|
|
1472
1624
|
hourStrideCadence(stride, opts) + trailingQualifier(ir, opts);
|
|
1473
1625
|
}
|
|
@@ -1488,6 +1640,45 @@ function cleanStrideSegment(ir: IR): StepSegment | null {
|
|
|
1488
1640
|
return segment;
|
|
1489
1641
|
}
|
|
1490
1642
|
|
|
1643
|
+
// Whether the hour field is a range — or a list whose segments include a
|
|
1644
|
+
// range — and so forms a window rather than a cross-product of clock times.
|
|
1645
|
+
// A pure single-value list (9,17) has no range to span and still enumerates;
|
|
1646
|
+
// a step is handled by hourStride/hourCadence.
|
|
1647
|
+
function hasHourWindow(ir: IR): boolean {
|
|
1648
|
+
return hourSegments(ir).some(function range(segment) {
|
|
1649
|
+
return segment.kind === 'range';
|
|
1650
|
+
});
|
|
1651
|
+
}
|
|
1652
|
+
|
|
1653
|
+
// Render an hour range (or a list whose segments include a range) under
|
|
1654
|
+
// minute 0 and a meaningful second as the hour-range window — the lead clause,
|
|
1655
|
+
// then "de las 09:00 a las 17:00" (and any non-contiguous hour joined with
|
|
1656
|
+
// "y también") — instead of cross-multiplying the hours into a wall of clock
|
|
1657
|
+
// times. The hour-RANGE analog of hourCadence. Returns null when the hour has
|
|
1658
|
+
// no range, when the minute is non-zero (a real clock minute the existing
|
|
1659
|
+
// window form already speaks), or when a plain :00 set carries no clause.
|
|
1660
|
+
// Renderer-only; the IR is unchanged.
|
|
1661
|
+
function hourRangeCadence(ir: IR, minute: number, opts: Opts): string | null {
|
|
1662
|
+
if (minute !== 0 || !hasHourWindow(ir) || ir.pattern.second === '0') {
|
|
1663
|
+
return null;
|
|
1664
|
+
}
|
|
1665
|
+
|
|
1666
|
+
// A wildcard or sub-minute step second confined to minute 0 is the whole
|
|
1667
|
+
// minute-0 window ("durante un minuto"), confined to the hour range with the
|
|
1668
|
+
// "durante las horas …" idiom — kept distinct from the bare minute-0 window
|
|
1669
|
+
// ("cada hora de las 09:00 a las 17:00") so the confinement is never heard
|
|
1670
|
+
// as it — the hour-range analog of "durante un minuto, durante las horas
|
|
1671
|
+
// pares".
|
|
1672
|
+
if (subMinuteSecond(ir)) {
|
|
1673
|
+
return secondsClause(ir, 'minuto', opts) + ' durante un minuto, ' +
|
|
1674
|
+
'durante las horas ' + hourSegmentTimes(ir, 0, null, opts) +
|
|
1675
|
+
trailingQualifier(ir, opts);
|
|
1676
|
+
}
|
|
1677
|
+
|
|
1678
|
+
return hourCadenceLead(ir, minute, opts) + ', ' +
|
|
1679
|
+
hourSegmentTimes(ir, 0, null, opts) + trailingQualifier(ir, opts);
|
|
1680
|
+
}
|
|
1681
|
+
|
|
1491
1682
|
// --- Hour-time phrasing. ---
|
|
1492
1683
|
|
|
1493
1684
|
// "a las 9:00" / "a la 1:00" / "al mediodía" for each fire hour.
|