@bbn/bbn 2.0.32 → 2.0.34

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.
@@ -1 +1,31 @@
1
+ type CommonFormats = {
2
+ date: Array<{
3
+ pattern: string;
4
+ sample: string;
5
+ options: Intl.DateTimeFormatOptions;
6
+ }>;
7
+ time: Array<{
8
+ pattern: string;
9
+ sample: string;
10
+ options: Intl.DateTimeFormatOptions;
11
+ }>;
12
+ datetime: Array<{
13
+ pattern: string;
14
+ sample: string;
15
+ options: Intl.DateTimeFormatOptions;
16
+ }>;
17
+ };
18
+ /**
19
+ * Enumerate common date, time and datetime formats for a locale, by iterating
20
+ * over combinations of:
21
+ * - weekday / year / month / day
22
+ * - hour / minute / second / timeZoneName
23
+ *
24
+ * Constraints:
25
+ * - no minutes/seconds if you don't have hours
26
+ * - no seconds if you don't have minutes
27
+ * - no timezone if you don't have time
28
+ */
29
+ export declare function getCommonFormatsForLocale(lng: string | string[]): CommonFormats;
1
30
  export default function buildLocaleFromIntl(): void;
31
+ export {};
@@ -1,7 +1,7 @@
1
1
  import extend from "../../fn/object/extend.js";
2
2
  import numProperties from "../../fn/object/numProperties.js";
3
3
  /**
4
- * Build a token pattern like "DD/MM/YYYY HH:II:SS" from Intl.DateTimeFormat parts.
4
+ * Build a token pattern (YYYY, MM, DD, dddd, HH, II, SS, A, z) from Intl parts.
5
5
  */
6
6
  function partsToPattern(parts, hourCycle) {
7
7
  let pattern = '';
@@ -55,21 +55,28 @@ function partsToPattern(parts, hourCycle) {
55
55
  return pattern;
56
56
  }
57
57
  /**
58
- * Returns common date / time / datetime formats for a locale, including
59
- * all reasonable combinations of weekday, year, month and day.
58
+ * Enumerate common date, time and datetime formats for a locale, by iterating
59
+ * over combinations of:
60
+ * - weekday / year / month / day
61
+ * - hour / minute / second / timeZoneName
62
+ *
63
+ * Constraints:
64
+ * - no minutes/seconds if you don't have hours
65
+ * - no seconds if you don't have minutes
66
+ * - no timezone if you don't have time
60
67
  */
61
- const getCommonFormatsForLocale = function (lng) {
62
- const timeStyles = ['full', 'long', 'medium', 'short'];
68
+ export function getCommonFormatsForLocale(lng) {
63
69
  // Fixed sample: 2 Jan 2000, 13:45:30 UTC
64
70
  const sample = new Date(Date.UTC(2000, 0, 2, 13, 45, 30));
65
71
  const date = [];
66
72
  const time = [];
67
73
  const datetime = [];
68
- // To avoid duplicates
69
- const seenDatePatterns = new Set();
70
- const seenTimePatterns = new Set();
71
- const seenDateTimePatterns = new Set();
72
- // --- 1) DATE formats via combinations of weekday/year/month/day ---
74
+ // Dedupe by options (not just pattern), so we don't lose combinations like
75
+ // { day: "numeric", month: "short", year: "numeric" }.
76
+ const seenDateOptions = new Set();
77
+ const seenTimeOptions = new Set();
78
+ const seenDateTimeOptions = new Set();
79
+ // ---- 1) DATE formats: combinations of weekday/year/month/day ----
73
80
  const weekdayOptions = [
74
81
  undefined,
75
82
  'short',
@@ -104,61 +111,100 @@ const getCommonFormatsForLocale = function (lng) {
104
111
  options.month = month;
105
112
  if (day)
106
113
  options.day = day;
107
- // Build formatter and pattern
114
+ const key = JSON.stringify(options);
115
+ if (seenDateOptions.has(key)) {
116
+ continue;
117
+ }
118
+ seenDateOptions.add(key);
108
119
  const fmt = new Intl.DateTimeFormat(lng, options);
109
120
  const parts = fmt.formatToParts(sample);
110
121
  const resolved = fmt.resolvedOptions();
111
122
  const pattern = partsToPattern(parts, resolved.hourCycle);
112
- if (!seenDatePatterns.has(pattern)) {
113
- seenDatePatterns.add(pattern);
114
- dateOptionsList.push(options); // keep for datetime combos later
115
- date.push({
116
- pattern,
117
- sample: fmt.format(sample),
118
- options
119
- });
120
- }
123
+ dateOptionsList.push(options);
124
+ date.push({
125
+ pattern,
126
+ sample: fmt.format(sample),
127
+ options
128
+ });
121
129
  }
122
130
  }
123
131
  }
124
132
  }
125
- // --- 2) TIME formats via timeStyle only ---
126
- for (const ts of timeStyles) {
127
- const options = { timeStyle: ts };
128
- const fmt = new Intl.DateTimeFormat(lng, options);
129
- const parts = fmt.formatToParts(sample);
130
- const resolved = fmt.resolvedOptions();
131
- const pattern = partsToPattern(parts, resolved.hourCycle);
132
- if (!seenTimePatterns.has(pattern)) {
133
- seenTimePatterns.add(pattern);
134
- time.push({
135
- style: ts,
136
- pattern,
137
- sample: fmt.format(sample),
138
- options
139
- });
133
+ const hourOptions = ['numeric', '2-digit'];
134
+ const minuteOptions = [
135
+ undefined,
136
+ 'numeric',
137
+ '2-digit'
138
+ ];
139
+ const secondOptions = [
140
+ undefined,
141
+ 'numeric',
142
+ '2-digit'
143
+ ];
144
+ const tzNameOptions = [
145
+ undefined,
146
+ 'short',
147
+ 'long'
148
+ ];
149
+ const timeOptionsList = [];
150
+ for (const hour of hourOptions) {
151
+ for (const minute of minuteOptions) {
152
+ for (const second of secondOptions) {
153
+ for (const tzName of tzNameOptions) {
154
+ // Constraints:
155
+ // - we always have hour (by design)
156
+ // - if we have second, we must have minute
157
+ if (second && !minute) {
158
+ continue;
159
+ }
160
+ const options = { hour };
161
+ if (minute)
162
+ options.minute = minute;
163
+ if (second)
164
+ options.second = second;
165
+ if (tzName)
166
+ options.timeZoneName = tzName;
167
+ const key = JSON.stringify(options);
168
+ if (seenTimeOptions.has(key)) {
169
+ continue;
170
+ }
171
+ seenTimeOptions.add(key);
172
+ const fmt = new Intl.DateTimeFormat(lng, options);
173
+ const parts = fmt.formatToParts(sample);
174
+ const resolved = fmt.resolvedOptions();
175
+ const pattern = partsToPattern(parts, resolved.hourCycle);
176
+ timeOptionsList.push(options);
177
+ time.push({
178
+ pattern,
179
+ sample: fmt.format(sample),
180
+ options
181
+ });
182
+ }
183
+ }
140
184
  }
141
185
  }
142
- // --- 3) DATETIME formats: each date option × each timeStyle ---
186
+ // ---- 3) DATETIME formats: each dateOption × each timeOption ----
143
187
  for (const dateOpts of dateOptionsList) {
144
- for (const ts of timeStyles) {
145
- const options = Object.assign(Object.assign({}, dateOpts), { timeStyle: ts });
188
+ for (const timeOpts of timeOptionsList) {
189
+ const options = Object.assign(Object.assign({}, dateOpts), timeOpts);
190
+ const key = JSON.stringify(options);
191
+ if (seenDateTimeOptions.has(key)) {
192
+ continue;
193
+ }
194
+ seenDateTimeOptions.add(key);
146
195
  const fmt = new Intl.DateTimeFormat(lng, options);
147
196
  const parts = fmt.formatToParts(sample);
148
197
  const resolved = fmt.resolvedOptions();
149
198
  const pattern = partsToPattern(parts, resolved.hourCycle);
150
- if (!seenDateTimePatterns.has(pattern)) {
151
- seenDateTimePatterns.add(pattern);
152
- datetime.push({
153
- pattern,
154
- sample: fmt.format(sample),
155
- options
156
- });
157
- }
199
+ datetime.push({
200
+ pattern,
201
+ sample: fmt.format(sample),
202
+ options
203
+ });
158
204
  }
159
205
  }
160
206
  return { date, time, datetime };
161
- };
207
+ }
162
208
  export default function buildLocaleFromIntl() {
163
209
  if (numProperties(bbn.dt.locales)) {
164
210
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bbn/bbn",
3
- "version": "2.0.32",
3
+ "version": "2.0.34",
4
4
  "description": "Javascript toolkit",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",