cronli5 0.2.0 → 0.2.1
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/README.md +4 -4
- package/cronli5.min.js +2 -2
- package/dist/cronli5.cjs +123 -104
- package/dist/cronli5.js +123 -104
- package/dist/lang/de.cjs +65 -65
- package/dist/lang/de.js +65 -65
- package/dist/lang/en.cjs +122 -101
- package/dist/lang/en.js +122 -101
- package/dist/lang/es.cjs +71 -72
- package/dist/lang/es.js +71 -72
- package/dist/lang/fi.cjs +71 -66
- package/dist/lang/fi.js +71 -66
- package/dist/lang/zh.cjs +36 -36
- package/dist/lang/zh.js +36 -36
- package/package.json +1 -1
- package/src/core/analyze.ts +14 -13
- package/src/core/ir.ts +8 -8
- package/src/core/shapes.ts +8 -1
- package/src/core/util.ts +86 -3
- package/src/core/validate.ts +1 -1
- package/src/cronli5.ts +3 -3
- package/src/lang/de/index.ts +30 -99
- package/src/lang/en/index.ts +163 -188
- package/src/lang/es/index.ts +36 -120
- package/src/lang/fi/index.ts +33 -104
- package/src/lang/zh/index.ts +23 -48
- package/src/types.ts +2 -2
- package/types/core/analyze.d.ts +2 -2
- package/types/core/ir.d.ts +7 -7
- package/types/core/shapes.d.ts +2 -1
- package/types/core/util.d.ts +17 -2
- package/types/types.d.ts +1 -1
package/src/lang/es/index.ts
CHANGED
|
@@ -4,18 +4,20 @@
|
|
|
4
4
|
//
|
|
5
5
|
// Spanish is the pilot language for the i18n architecture
|
|
6
6
|
// (docs/i18n-design.md §7): it consumes only the IR, owns all of its
|
|
7
|
-
// words, and is free to re-
|
|
7
|
+
// words, and is free to re-plan where Spanish grammar prefers a
|
|
8
8
|
// different shape than the plan hint (e.g. wildcard minutes over hour
|
|
9
9
|
// lists render as per-hour windows).
|
|
10
10
|
|
|
11
11
|
import {clockDigits, numeral} from '../../core/format.js';
|
|
12
12
|
import {maxClockTimes, weekdayNumbers} from '../../core/specs.js';
|
|
13
|
+
import {isOpenStep} from '../../core/shapes.js';
|
|
13
14
|
import {
|
|
14
|
-
arithmeticStep, orderWeekdaysForDisplay,
|
|
15
|
+
arithmeticStep, hourListStride, offsetCleanStride, orderWeekdaysForDisplay,
|
|
16
|
+
segmentsOf, singleValues, stepSegment, toFieldNumber
|
|
15
17
|
} from '../../core/util.js';
|
|
16
18
|
import type {Cronli5Options} from '../../types.js';
|
|
17
19
|
import type {
|
|
18
|
-
|
|
20
|
+
HourTimesPlan, IR, Language, NormalizedOptions, PlanNode,
|
|
19
21
|
Segment
|
|
20
22
|
} from '../../core/ir.js';
|
|
21
23
|
import {resolveDialect, type SpanishStyle} from './dialects.js';
|
|
@@ -62,26 +64,6 @@ type NameSegment =
|
|
|
62
64
|
type RangeNameSegment = Extract<NameSegment, {kind: 'range'}>;
|
|
63
65
|
type SingleNameSegment = Extract<NameSegment, {kind: 'single'}>;
|
|
64
66
|
|
|
65
|
-
// The first (and only) segment of a step field. The plan only routes here
|
|
66
|
-
// for step shapes, whose segments list is present and step-kinded; this
|
|
67
|
-
// asserts what the analysis guarantees but the type cannot express.
|
|
68
|
-
function stepSegment(segments: Segment[] | null): StepSegment {
|
|
69
|
-
return (segments as Segment[])[0] as StepSegment;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// The hour field's classified segments. Callers reach here only for hour
|
|
73
|
-
// shapes the analysis segmented, so the list is present; the type permits
|
|
74
|
-
// null (wildcard/quartz) that these paths never carry.
|
|
75
|
-
function hourSegments(ir: IR): Segment[] {
|
|
76
|
-
return ir.analyses.segments.hour as Segment[];
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// A field's classified segments. Callers reach a segment list only when the
|
|
80
|
-
// field is non-wildcard and non-quartz, where the analysis always produced
|
|
81
|
-
// one; the type's null (those two shapes) is unreachable on these paths.
|
|
82
|
-
function fieldSegments(ir: IR, field: Field): Segment[] {
|
|
83
|
-
return ir.analyses.segments[field] as Segment[];
|
|
84
|
-
}
|
|
85
67
|
|
|
86
68
|
// Spanish number names for the integers zero through ten.
|
|
87
69
|
const numeros = [
|
|
@@ -240,9 +222,9 @@ function secondsListAtClock(
|
|
|
240
222
|
// prepend "de " to produce the genitive form "de las 09:00 y 17:00".
|
|
241
223
|
const clockList = grouped.startsWith('a ') ? grouped.slice(2) : grouped;
|
|
242
224
|
const stride =
|
|
243
|
-
strideFromSegments(
|
|
225
|
+
strideFromSegments(segmentsOf(ir, 'second'), 'segundo', '', opts);
|
|
244
226
|
const secondsPhrase = stride ?? 'en los segundos ' +
|
|
245
|
-
joinList(segmentWords(
|
|
227
|
+
joinList(segmentWords(segmentsOf(ir, 'second')));
|
|
246
228
|
const dayFrame = trailingQualifier(ir, opts);
|
|
247
229
|
|
|
248
230
|
return (dayFrame ? dayFrame.trimStart() + ', ' : '') +
|
|
@@ -318,7 +300,7 @@ function renderComposeSeconds(
|
|
|
318
300
|
const window = hourWindow(boundedWindow(restNode), opts);
|
|
319
301
|
const dayFrame = weekdayQualifier(ir) + monthScope(ir);
|
|
320
302
|
const cadence = 'cada ' +
|
|
321
|
-
numero(stepSegment(ir
|
|
303
|
+
numero(stepSegment(ir, 'second').interval, opts) +
|
|
322
304
|
' segundos del minuto ' + ir.pattern.minute;
|
|
323
305
|
|
|
324
306
|
return dayFrame + ', ' + window + ', ' + cadence;
|
|
@@ -355,7 +337,7 @@ function isEveryOtherMinuteSeconds(
|
|
|
355
337
|
return false;
|
|
356
338
|
}
|
|
357
339
|
|
|
358
|
-
const minuteStep = stepSegment(ir
|
|
340
|
+
const minuteStep = stepSegment(ir, 'minute');
|
|
359
341
|
|
|
360
342
|
return minuteStep.startToken === '*' && minuteStep.interval === 2;
|
|
361
343
|
}
|
|
@@ -411,7 +393,7 @@ function secondsClause(ir: IR, anchor: string, opts: Opts): string {
|
|
|
411
393
|
}
|
|
412
394
|
|
|
413
395
|
if (shape === 'step') {
|
|
414
|
-
return stepCycle60(stepSegment(ir
|
|
396
|
+
return stepCycle60(stepSegment(ir, 'second'), 'segundo',
|
|
415
397
|
anchor, opts);
|
|
416
398
|
}
|
|
417
399
|
|
|
@@ -426,9 +408,9 @@ function secondsClause(ir: IR, anchor: string, opts: Opts): string {
|
|
|
426
408
|
return 'en el segundo ' + secondField + ' de cada ' + anchor;
|
|
427
409
|
}
|
|
428
410
|
|
|
429
|
-
return strideFromSegments(
|
|
411
|
+
return strideFromSegments(segmentsOf(ir, 'second'), 'segundo', anchor,
|
|
430
412
|
opts) ?? 'en los segundos ' +
|
|
431
|
-
joinList(segmentWords(
|
|
413
|
+
joinList(segmentWords(segmentsOf(ir, 'second'))) +
|
|
432
414
|
' de cada ' + anchor;
|
|
433
415
|
}
|
|
434
416
|
|
|
@@ -472,9 +454,9 @@ function renderMultipleMinutes(
|
|
|
472
454
|
// enumerated to this list reads as a stride cadence when the fires form a
|
|
473
455
|
// long-enough progression.
|
|
474
456
|
function minutesList(ir: IR, opts: Opts): string {
|
|
475
|
-
return strideFromSegments(
|
|
457
|
+
return strideFromSegments(segmentsOf(ir, 'minute'), 'minuto', 'hora',
|
|
476
458
|
opts) ?? 'en los minutos ' +
|
|
477
|
-
joinList(segmentWords(
|
|
459
|
+
joinList(segmentWords(segmentsOf(ir, 'minute'))) + ' de cada hora';
|
|
478
460
|
}
|
|
479
461
|
|
|
480
462
|
// "cada minuto del 0 al 30". The standalone renderer adds "de cada hora";
|
|
@@ -496,7 +478,7 @@ function singleHourStep(segments: Segment[] | null): boolean {
|
|
|
496
478
|
// A single hour step as a confinement. A stride of two over the whole day
|
|
497
479
|
// reads idiomatically as the even ("las horas pares") or odd ("impares")
|
|
498
480
|
// hours; any other step names its active hours, which pins the schedule
|
|
499
|
-
// precisely (
|
|
481
|
+
// precisely (ordinal/colloquial forms would be imprecise here).
|
|
500
482
|
function stepHourSpan(segment: StepSegment, opts: Opts): string {
|
|
501
483
|
const bounded = segment.startToken.indexOf('-') !== -1;
|
|
502
484
|
const start = segment.startToken === '*' ? 0 : +segment.startToken;
|
|
@@ -580,7 +562,7 @@ function renderMinuteFrequency(
|
|
|
580
562
|
plan: Extract<PlanNode, {kind: 'minuteFrequency'}>,
|
|
581
563
|
opts: Opts
|
|
582
564
|
): string {
|
|
583
|
-
let phrase = stepCycle60(stepSegment(ir
|
|
565
|
+
let phrase = stepCycle60(stepSegment(ir, 'minute'), 'minuto',
|
|
584
566
|
'hora', opts);
|
|
585
567
|
|
|
586
568
|
if (plan.hours.kind === 'during') {
|
|
@@ -595,7 +577,7 @@ function renderMinuteFrequency(
|
|
|
595
577
|
// An offset step (e.g. 1/2) arrives here; a single step reads as a
|
|
596
578
|
// confinement, not the verbose window list.
|
|
597
579
|
phrase += singleHourStep(ir.analyses.segments.hour) ?
|
|
598
|
-
', ' + stepHourSpan(stepSegment(ir
|
|
580
|
+
', ' + stepHourSpan(stepSegment(ir, 'hour'), opts) :
|
|
599
581
|
' ' + hourSpanFromTimes(ir, plan.hours.times, opts);
|
|
600
582
|
}
|
|
601
583
|
}
|
|
@@ -605,7 +587,7 @@ function renderMinuteFrequency(
|
|
|
605
587
|
else if (plan.hours.kind === 'step') {
|
|
606
588
|
// A clean stride is a confinement ("las horas pares", or the active-hour
|
|
607
589
|
// list), never a juxtaposed cadence ("cada dos horas").
|
|
608
|
-
phrase += ', ' + stepHourSpan(stepSegment(ir
|
|
590
|
+
phrase += ', ' + stepHourSpan(stepSegment(ir, 'hour'), opts);
|
|
609
591
|
}
|
|
610
592
|
|
|
611
593
|
return phrase + trailingQualifier(ir, opts);
|
|
@@ -632,7 +614,7 @@ function renderMinuteSpanInHour(
|
|
|
632
614
|
trailingQualifier(ir, opts);
|
|
633
615
|
}
|
|
634
616
|
|
|
635
|
-
// A minute window under discrete hours. Spanish re-
|
|
617
|
+
// A minute window under discrete hours. Spanish re-plans the
|
|
636
618
|
// wildcard form: rather than "during the X hours", each hour reads as its
|
|
637
619
|
// own window ("de las 9:00 a las 9:59").
|
|
638
620
|
function renderMinutesAcrossHours(
|
|
@@ -651,7 +633,7 @@ function renderMinutesAcrossHours(
|
|
|
651
633
|
|
|
652
634
|
if (singleHourStep(ir.analyses.segments.hour)) {
|
|
653
635
|
return 'cada minuto, ' +
|
|
654
|
-
stepHourSpan(stepSegment(ir
|
|
636
|
+
stepHourSpan(stepSegment(ir, 'hour'), opts) +
|
|
655
637
|
trailingQualifier(ir, opts);
|
|
656
638
|
}
|
|
657
639
|
|
|
@@ -676,7 +658,7 @@ function renderMinuteSpanAcrossHourStep(
|
|
|
676
658
|
plan: Extract<PlanNode, {kind: 'minuteSpanAcrossHourStep'}>,
|
|
677
659
|
opts: Opts
|
|
678
660
|
): string {
|
|
679
|
-
const segment = stepSegment(ir
|
|
661
|
+
const segment = stepSegment(ir, 'hour');
|
|
680
662
|
// A bounded or uneven hour step reads as its endpoint-pinning cadence; an
|
|
681
663
|
// offset-clean step keeps its confinement / per-step phrasing.
|
|
682
664
|
const cadence = unevenHourCadence(ir, opts);
|
|
@@ -752,7 +734,7 @@ function renderHourStep(
|
|
|
752
734
|
return cadence + trailingQualifier(ir, opts);
|
|
753
735
|
}
|
|
754
736
|
|
|
755
|
-
return stepHours(stepSegment(ir
|
|
737
|
+
return stepHours(stepSegment(ir, 'hour'), opts) +
|
|
756
738
|
trailingQualifier(ir, opts);
|
|
757
739
|
}
|
|
758
740
|
|
|
@@ -797,7 +779,7 @@ function unionMonthLeadFull(ir: IR): string {
|
|
|
797
779
|
}
|
|
798
780
|
|
|
799
781
|
const lead = monthPhrase(ir, monthRanged(ir) ? 'de ' : 'en ');
|
|
800
|
-
const segments = flattenSteps(
|
|
782
|
+
const segments = flattenSteps(segmentsOf(ir, 'month'));
|
|
801
783
|
const isEnumeration = !monthRanged(ir) && segments.length >= 2;
|
|
802
784
|
|
|
803
785
|
return isEnumeration ? lead + ',' : lead;
|
|
@@ -819,7 +801,7 @@ function domArm(ir: IR, opts: Opts): string {
|
|
|
819
801
|
return stepDates(date, opts);
|
|
820
802
|
}
|
|
821
803
|
|
|
822
|
-
const segments =
|
|
804
|
+
const segments = segmentsOf(ir, 'date');
|
|
823
805
|
|
|
824
806
|
if (segments.length === 1 && segments[0].kind === 'range') {
|
|
825
807
|
return 'del ' + segments[0].bounds[0] + ' al ' +
|
|
@@ -848,7 +830,7 @@ function dowArm(ir: IR): string {
|
|
|
848
830
|
|
|
849
831
|
// Weekday lists display Monday-first (Sunday last); a lone range keeps its
|
|
850
832
|
// form. The IR stays canonical (Sunday=0). The helper flattens steps.
|
|
851
|
-
const segments = orderWeekdaysForDisplay(
|
|
833
|
+
const segments = orderWeekdaysForDisplay(segmentsOf(ir, 'weekday'));
|
|
852
834
|
const allSingles = segments.every(function single(segment) {
|
|
853
835
|
return segment.kind === 'single';
|
|
854
836
|
});
|
|
@@ -1245,7 +1227,7 @@ function renderCompactClockTimes(
|
|
|
1245
1227
|
return cadence;
|
|
1246
1228
|
}
|
|
1247
1229
|
|
|
1248
|
-
const ranged =
|
|
1230
|
+
const ranged = segmentsOf(ir, 'hour').some(function range(segment) {
|
|
1249
1231
|
return segment.kind === 'range';
|
|
1250
1232
|
});
|
|
1251
1233
|
|
|
@@ -1383,21 +1365,6 @@ function strideFromSegments(
|
|
|
1383
1365
|
null;
|
|
1384
1366
|
}
|
|
1385
1367
|
|
|
1386
|
-
// The sorted numeric values a field's segments cover, or null if any segment
|
|
1387
|
-
// is not a discrete single (a range or sub-step is not a plain fire list).
|
|
1388
|
-
function singleValues(segments: Segment[]): number[] | null {
|
|
1389
|
-
const values: number[] = [];
|
|
1390
|
-
|
|
1391
|
-
for (const segment of segments) {
|
|
1392
|
-
if (segment.kind !== 'single') {
|
|
1393
|
-
return null;
|
|
1394
|
-
}
|
|
1395
|
-
|
|
1396
|
-
values.push(+segment.value);
|
|
1397
|
-
}
|
|
1398
|
-
|
|
1399
|
-
return values;
|
|
1400
|
-
}
|
|
1401
1368
|
|
|
1402
1369
|
// "cada seis horas", "a las 9:00, a las 11:00 y a la 1:00", or "cada
|
|
1403
1370
|
// cinco horas a partir de las 2:00".
|
|
@@ -1452,17 +1419,6 @@ function hourStrideCadence(
|
|
|
1452
1419
|
timePhrase(last, 0, null, opts);
|
|
1453
1420
|
}
|
|
1454
1421
|
|
|
1455
|
-
// Whether an hour stride wraps the day cleanly from within its first interval
|
|
1456
|
-
// (a `*/n` from the top, or a `m/n` offset with m < n that divides 24): such a
|
|
1457
|
-
// stride has no distinct endpoint and keeps its bare or "a partir de" cadence.
|
|
1458
|
-
// Every other stride — a uneven interval, or one starting at or past its
|
|
1459
|
-
// interval (a bounded `a-b/n`) — is a bounded set the cadence pins the ends of.
|
|
1460
|
-
function offsetCleanStride(
|
|
1461
|
-
stride: {start: number; interval: number}
|
|
1462
|
-
): boolean {
|
|
1463
|
-
return stride.start < stride.interval && 24 % stride.interval === 0;
|
|
1464
|
-
}
|
|
1465
|
-
|
|
1466
1422
|
// The bounded cadence for an hour stride that pins both clock-time endpoints,
|
|
1467
1423
|
// or null when the hour is not such a stride. The core rewrites a uneven step
|
|
1468
1424
|
// to its fire list, so a minute window/list/step crossed with it lands in the
|
|
@@ -1480,41 +1436,6 @@ function unevenHourCadence(ir: IR, opts: Opts): string | null {
|
|
|
1480
1436
|
return hourStrideCadence(stride, opts);
|
|
1481
1437
|
}
|
|
1482
1438
|
|
|
1483
|
-
// An hour list's arithmetic progression, or null when its values are not a
|
|
1484
|
-
// step the renderer should speak as a cadence. The core rewrites a uneven hour
|
|
1485
|
-
// step (whose interval does not tile 24, e.g. `*/5` → 0,5,10,15,20) to its
|
|
1486
|
-
// literal fire list, indistinguishable in the IR from a hand-written list; the
|
|
1487
|
-
// renderer recovers the cadence from the values. A progression starting at zero
|
|
1488
|
-
// is a `*/n` step however short (0,7,14,21 is `*/7`); a non-zero progression is
|
|
1489
|
-
// only a step when it is too long to be a deliberate clock-time list (e.g. 9,17
|
|
1490
|
-
// is two named times, not a cadence). Interval one is a plain range, never a
|
|
1491
|
-
// step.
|
|
1492
|
-
function hourListStride(
|
|
1493
|
-
values: number[]
|
|
1494
|
-
): {start: number; interval: number; last: number} | null {
|
|
1495
|
-
if (values.length < 2) {
|
|
1496
|
-
return null;
|
|
1497
|
-
}
|
|
1498
|
-
|
|
1499
|
-
const interval = values[1] - values[0];
|
|
1500
|
-
|
|
1501
|
-
if (interval < 2) {
|
|
1502
|
-
return null;
|
|
1503
|
-
}
|
|
1504
|
-
|
|
1505
|
-
for (let i = 2; i < values.length; i += 1) {
|
|
1506
|
-
if (values[i] - values[i - 1] !== interval) {
|
|
1507
|
-
return null;
|
|
1508
|
-
}
|
|
1509
|
-
}
|
|
1510
|
-
|
|
1511
|
-
if (values[0] !== 0 && values.length < 5) {
|
|
1512
|
-
return null;
|
|
1513
|
-
}
|
|
1514
|
-
|
|
1515
|
-
return {interval, last: values[values.length - 1], start: values[0]};
|
|
1516
|
-
}
|
|
1517
|
-
|
|
1518
1439
|
// The hour field's stride, or null when the hour is not a cadence: a step
|
|
1519
1440
|
// segment yields its {start, interval, last} directly; an all-single hour
|
|
1520
1441
|
// list yields one only when its values form a step progression (so an irregular
|
|
@@ -1524,7 +1445,7 @@ function hourListStride(
|
|
|
1524
1445
|
function hourStride(
|
|
1525
1446
|
ir: IR
|
|
1526
1447
|
): {start: number; interval: number; last: number} | null {
|
|
1527
|
-
const segments =
|
|
1448
|
+
const segments = segmentsOf(ir, 'hour');
|
|
1528
1449
|
|
|
1529
1450
|
if (segments.length === 1 && segments[0].kind === 'step') {
|
|
1530
1451
|
const segment = segments[0];
|
|
@@ -1638,7 +1559,7 @@ function hourCadence(ir: IR, minute: number, opts: Opts): string | null {
|
|
|
1638
1559
|
// bounded step, an uneven stride, or an arithmetic-progression list, which
|
|
1639
1560
|
// keep the bounded cadence form).
|
|
1640
1561
|
function cleanStrideSegment(ir: IR): StepSegment | null {
|
|
1641
|
-
const segments =
|
|
1562
|
+
const segments = segmentsOf(ir, 'hour');
|
|
1642
1563
|
const segment = segments.length === 1 && segments[0];
|
|
1643
1564
|
|
|
1644
1565
|
if (!segment || segment.kind !== 'step' ||
|
|
@@ -1654,7 +1575,7 @@ function cleanStrideSegment(ir: IR): StepSegment | null {
|
|
|
1654
1575
|
// A pure single-value list (9,17) has no range to span and still enumerates;
|
|
1655
1576
|
// a step is handled by hourStride/hourCadence.
|
|
1656
1577
|
function hasHourWindow(ir: IR): boolean {
|
|
1657
|
-
return
|
|
1578
|
+
return segmentsOf(ir, 'hour').some(function range(segment) {
|
|
1658
1579
|
return segment.kind === 'range';
|
|
1659
1580
|
});
|
|
1660
1581
|
}
|
|
@@ -1697,7 +1618,7 @@ function hourRangeCadence(ir: IR, minute: number, opts: Opts): string | null {
|
|
|
1697
1618
|
// Used by the compact-clock non-fold path, where the minute is a step or list
|
|
1698
1619
|
// (a single-value minute keeps its real "a las HH:MM" clock time elsewhere).
|
|
1699
1620
|
function hourContextTimes(ir: IR, opts: Opts): string {
|
|
1700
|
-
const segments =
|
|
1621
|
+
const segments = segmentsOf(ir, 'hour');
|
|
1701
1622
|
|
|
1702
1623
|
// Collect the point hours (singles and step fires) — a range stays a window.
|
|
1703
1624
|
const points: number[] = [];
|
|
@@ -1801,7 +1722,7 @@ function hourWindowsFromTimes(
|
|
|
1801
1722
|
}));
|
|
1802
1723
|
}
|
|
1803
1724
|
|
|
1804
|
-
return joinList(
|
|
1725
|
+
return joinList(segmentsOf(ir, 'hour').map(function window(segment) {
|
|
1805
1726
|
if (segment.kind === 'range') {
|
|
1806
1727
|
return timeRange({hour: +segment.bounds[0], minute: 0},
|
|
1807
1728
|
{hour: +segment.bounds[1], minute: 59}, opts);
|
|
@@ -1830,7 +1751,7 @@ function hourSegmentTimes(
|
|
|
1830
1751
|
const pieces: string[] = [];
|
|
1831
1752
|
const fromRange: boolean[] = [];
|
|
1832
1753
|
|
|
1833
|
-
|
|
1754
|
+
segmentsOf(ir, 'hour').forEach(function clock(segment) {
|
|
1834
1755
|
if (segment.kind === 'step') {
|
|
1835
1756
|
segment.fires.forEach(function each(hour) {
|
|
1836
1757
|
pieces.push(atTime(timePhrase(hour, minute, second, opts)));
|
|
@@ -2100,7 +2021,7 @@ function dateClause(
|
|
|
2100
2021
|
return stepDates(pattern.date, opts);
|
|
2101
2022
|
}
|
|
2102
2023
|
|
|
2103
|
-
const segments =
|
|
2024
|
+
const segments = segmentsOf(ir, 'date');
|
|
2104
2025
|
|
|
2105
2026
|
if (segments.length === 1 && segments[0].kind === 'range') {
|
|
2106
2027
|
return 'del ' + segments[0].bounds[0] + ' al ' +
|
|
@@ -2118,7 +2039,7 @@ function dateClause(
|
|
|
2118
2039
|
// Whether the month field contains a range segment.
|
|
2119
2040
|
function monthRanged(ir: IR): boolean {
|
|
2120
2041
|
return ir.pattern.month !== '*' &&
|
|
2121
|
-
|
|
2042
|
+
segmentsOf(ir, 'month').some(function range(segment) {
|
|
2122
2043
|
return segment.kind === 'range';
|
|
2123
2044
|
});
|
|
2124
2045
|
}
|
|
@@ -2207,7 +2128,7 @@ function weekdayQualifier(ir: IR): string {
|
|
|
2207
2128
|
|
|
2208
2129
|
// Weekday lists display Monday-first (Sunday last); a lone range keeps its
|
|
2209
2130
|
// form. The IR stays canonical (Sunday=0). The helper flattens steps.
|
|
2210
|
-
const segments = orderWeekdaysForDisplay(
|
|
2131
|
+
const segments = orderWeekdaysForDisplay(segmentsOf(ir, 'weekday'));
|
|
2211
2132
|
const allSingles = segments.every(function single(segment) {
|
|
2212
2133
|
return segment.kind === 'single';
|
|
2213
2134
|
});
|
|
@@ -2260,7 +2181,7 @@ function flattenSteps(segments: Segment[]): NameSegment[] {
|
|
|
2260
2181
|
// ("en enero y de marzo a junio") — a bare "enero y marzo a junio" parses
|
|
2261
2182
|
// as "(enero y marzo) a junio".
|
|
2262
2183
|
function monthPhrase(ir: IR, lead: string): string {
|
|
2263
|
-
const segments = flattenSteps(
|
|
2184
|
+
const segments = flattenSteps(segmentsOf(ir, 'month'));
|
|
2264
2185
|
const ranged = segments.some(function range(segment) {
|
|
2265
2186
|
return segment.kind === 'range';
|
|
2266
2187
|
});
|
|
@@ -2423,11 +2344,6 @@ function monthName(token: NameToken): string {
|
|
|
2423
2344
|
return monthNames[+token] as string;
|
|
2424
2345
|
}
|
|
2425
2346
|
|
|
2426
|
-
// Whether a canonical field value is an open step (`*/n` or `a/n`).
|
|
2427
|
-
function isOpenStep(field: string): boolean {
|
|
2428
|
-
return field.indexOf('/') !== -1 && field.indexOf('-') === -1 &&
|
|
2429
|
-
field.indexOf(',') === -1;
|
|
2430
|
-
}
|
|
2431
2347
|
|
|
2432
2348
|
// The Spanish language module: the IR renderer plus the language-owned
|
|
2433
2349
|
// strings and option normalization.
|