@bbn/bbn 2.0.36 → 2.0.38
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.
|
@@ -23,12 +23,6 @@ type CommonFormats = {
|
|
|
23
23
|
* - Date: only sensible combos (Y-M-D ± weekday, Y-M, M-D).
|
|
24
24
|
* - Time: hour / hour:minute / hour:minute:second (+ optional TZ).
|
|
25
25
|
* - Datetime: only full dates (Y-M-D ± weekday) combined with time.
|
|
26
|
-
*
|
|
27
|
-
* Fully numeric date forms (like "1/1/1970") are explicitly included via:
|
|
28
|
-
* { year: 'numeric', month: 'numeric', day: 'numeric' }
|
|
29
|
-
* { year: '2-digit', month: 'numeric', day: 'numeric' }
|
|
30
|
-
* { year: 'numeric', month: '2-digit', day: '2-digit' }
|
|
31
|
-
* { year: '2-digit', month: '2-digit', day: '2-digit' }
|
|
32
26
|
*/
|
|
33
27
|
export declare function getCommonFormatsForLocale(lng: string | string[]): CommonFormats;
|
|
34
28
|
export default function buildLocaleFromIntl(): void;
|
|
@@ -3,31 +3,50 @@ import numProperties from "../../fn/object/numProperties.js";
|
|
|
3
3
|
/**
|
|
4
4
|
* Build a token pattern (YYYY, MM, DD, dddd, HH, II, SS, A, z) from Intl parts.
|
|
5
5
|
* Uses Intl options to distinguish MMM vs MMMM, ddd vs dddd, etc.
|
|
6
|
-
* All literal chunks are wrapped in square brackets so they can't be mistaken
|
|
7
|
-
* for tokens by the parser.
|
|
8
6
|
*/
|
|
9
7
|
function partsToPattern(parts, hourCycle, opts) {
|
|
10
8
|
let pattern = '';
|
|
11
9
|
const hasDayPeriod = parts.some(p => p.type === 'dayPeriod');
|
|
12
10
|
const is12h = hasDayPeriod || hourCycle === 'h12' || hourCycle === 'h11';
|
|
11
|
+
// ---- detect "all numeric date" ----
|
|
12
|
+
const yearIsNumeric = opts.year === 'numeric' || opts.year === '2-digit';
|
|
13
|
+
const monthIsNumeric = opts.month === 'numeric' || opts.month === '2-digit';
|
|
14
|
+
const dayIsNumeric = opts.day === 'numeric' || opts.day === '2-digit';
|
|
15
|
+
const hasYear = !!opts.year;
|
|
16
|
+
const hasMonth = !!opts.month;
|
|
17
|
+
const hasDay = !!opts.day;
|
|
18
|
+
const hasWeekday = !!opts.weekday;
|
|
19
|
+
const hasTextMonth = opts.month === 'short' || opts.month === 'long';
|
|
20
|
+
const isAllNumericDate = hasYear && hasMonth && hasDay &&
|
|
21
|
+
yearIsNumeric && monthIsNumeric && dayIsNumeric &&
|
|
22
|
+
!hasWeekday && !hasTextMonth;
|
|
13
23
|
for (const p of parts) {
|
|
14
24
|
switch (p.type) {
|
|
15
25
|
case 'year':
|
|
16
|
-
|
|
26
|
+
if (opts.year === '2-digit') {
|
|
27
|
+
pattern += 'YY';
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
pattern += 'YYYY';
|
|
31
|
+
}
|
|
17
32
|
break;
|
|
18
33
|
case 'month':
|
|
19
|
-
if (
|
|
34
|
+
if (isAllNumericDate) {
|
|
35
|
+
// normalize to single M when date is fully numeric
|
|
36
|
+
pattern += 'M';
|
|
37
|
+
}
|
|
38
|
+
else if (opts.month === 'short') {
|
|
20
39
|
pattern += 'MMM';
|
|
21
40
|
}
|
|
22
41
|
else if (opts.month === 'long') {
|
|
23
42
|
pattern += 'MMMM';
|
|
24
43
|
}
|
|
25
44
|
else if (opts.month === 'numeric' || opts.month === '2-digit') {
|
|
26
|
-
// numeric month
|
|
45
|
+
// non "all numeric" case (e.g., month+year or month+day only)
|
|
27
46
|
pattern += /^\d{2}$/.test(p.value) ? 'MM' : 'M';
|
|
28
47
|
}
|
|
29
48
|
else {
|
|
30
|
-
// Fallback
|
|
49
|
+
// Fallback
|
|
31
50
|
if (/^\d+$/.test(p.value)) {
|
|
32
51
|
pattern += p.value.length === 2 ? 'MM' : 'M';
|
|
33
52
|
}
|
|
@@ -37,7 +56,13 @@ function partsToPattern(parts, hourCycle, opts) {
|
|
|
37
56
|
}
|
|
38
57
|
break;
|
|
39
58
|
case 'day':
|
|
40
|
-
|
|
59
|
+
if (isAllNumericDate) {
|
|
60
|
+
// normalize to single D when date is fully numeric
|
|
61
|
+
pattern += 'D';
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
pattern += p.value.length === 2 ? 'DD' : 'D';
|
|
65
|
+
}
|
|
41
66
|
break;
|
|
42
67
|
case 'weekday':
|
|
43
68
|
if (opts.weekday === 'short' || opts.weekday === 'narrow') {
|
|
@@ -71,7 +96,7 @@ function partsToPattern(parts, hourCycle, opts) {
|
|
|
71
96
|
pattern += 'z';
|
|
72
97
|
break;
|
|
73
98
|
case 'literal': {
|
|
74
|
-
// Wrap
|
|
99
|
+
// Wrap literals in [ ... ] so your parser doesn't confuse them
|
|
75
100
|
if (p.value.length) {
|
|
76
101
|
const v = p.value.replace(/]/g, '\\]');
|
|
77
102
|
pattern += `[${v}]`;
|
|
@@ -79,7 +104,6 @@ function partsToPattern(parts, hourCycle, opts) {
|
|
|
79
104
|
break;
|
|
80
105
|
}
|
|
81
106
|
default:
|
|
82
|
-
// Fallback, should be rare
|
|
83
107
|
pattern += p.value;
|
|
84
108
|
break;
|
|
85
109
|
}
|
|
@@ -94,12 +118,6 @@ function partsToPattern(parts, hourCycle, opts) {
|
|
|
94
118
|
* - Date: only sensible combos (Y-M-D ± weekday, Y-M, M-D).
|
|
95
119
|
* - Time: hour / hour:minute / hour:minute:second (+ optional TZ).
|
|
96
120
|
* - Datetime: only full dates (Y-M-D ± weekday) combined with time.
|
|
97
|
-
*
|
|
98
|
-
* Fully numeric date forms (like "1/1/1970") are explicitly included via:
|
|
99
|
-
* { year: 'numeric', month: 'numeric', day: 'numeric' }
|
|
100
|
-
* { year: '2-digit', month: 'numeric', day: 'numeric' }
|
|
101
|
-
* { year: 'numeric', month: '2-digit', day: '2-digit' }
|
|
102
|
-
* { year: '2-digit', month: '2-digit', day: '2-digit' }
|
|
103
121
|
*/
|
|
104
122
|
export function getCommonFormatsForLocale(lng) {
|
|
105
123
|
const sample = new Date(Date.UTC(2000, 0, 2, 13, 45, 30));
|
|
@@ -110,14 +128,11 @@ export function getCommonFormatsForLocale(lng) {
|
|
|
110
128
|
const seenTimePatterns = new Set();
|
|
111
129
|
const seenDateTimePatterns = new Set();
|
|
112
130
|
// ---- 1) DATE: curated list of useful patterns ----
|
|
113
|
-
//
|
|
131
|
+
// Includes your important one: { day: "numeric", month: "short", year: "numeric" }
|
|
114
132
|
const dateOptionsList = [
|
|
115
|
-
//
|
|
116
|
-
{ year: 'numeric', month: 'numeric', day: 'numeric' },
|
|
133
|
+
// Full dates
|
|
117
134
|
{ year: 'numeric', month: '2-digit', day: '2-digit' },
|
|
118
|
-
{ year: '
|
|
119
|
-
{ year: '2-digit', month: '2-digit', day: '2-digit' },
|
|
120
|
-
// Full dates with textual month
|
|
135
|
+
{ year: 'numeric', month: 'numeric', day: 'numeric' },
|
|
121
136
|
{ year: 'numeric', month: 'short', day: 'numeric' },
|
|
122
137
|
{ year: 'numeric', month: 'long', day: 'numeric' },
|
|
123
138
|
// Full dates with weekday
|
|
@@ -131,7 +146,7 @@ export function getCommonFormatsForLocale(lng) {
|
|
|
131
146
|
// Month–day (no year)
|
|
132
147
|
{ month: 'numeric', day: 'numeric' },
|
|
133
148
|
{ month: '2-digit', day: '2-digit' },
|
|
134
|
-
{ month: 'short', day: 'numeric' },
|
|
149
|
+
{ month: 'short', day: 'numeric' }, // ← e.g. "22 janv."
|
|
135
150
|
{ month: 'long', day: 'numeric' }
|
|
136
151
|
];
|
|
137
152
|
const fullDateOptions = []; // Y+M+D (± weekday)
|
|
@@ -176,7 +191,7 @@ export function getCommonFormatsForLocale(lng) {
|
|
|
176
191
|
});
|
|
177
192
|
}
|
|
178
193
|
}
|
|
179
|
-
// ---- 3) DATETIME: only full dates (Y-M-D ± weekday) × time
|
|
194
|
+
// ---- 3) DATETIME: only full dates (Y-M-D ± weekday) × time
|
|
180
195
|
for (const dOpts of fullDateOptions) {
|
|
181
196
|
for (const tOpts of timeOptionsList) {
|
|
182
197
|
const opts = Object.assign(Object.assign({}, dOpts), tOpts);
|