@bbn/bbn 2.0.30 → 2.0.32

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,34 +1 @@
1
- type Style = 'full' | 'long' | 'medium' | 'short';
2
- type CommonFormats = {
3
- date: Array<{
4
- style: Style;
5
- pattern: string;
6
- sample: string;
7
- options: Intl.DateTimeFormatOptions;
8
- }>;
9
- time: Array<{
10
- style: Style;
11
- pattern: string;
12
- sample: string;
13
- options: Intl.DateTimeFormatOptions;
14
- }>;
15
- datetime: Array<{
16
- dateStyle: Style;
17
- timeStyle: Style;
18
- pattern: string;
19
- sample: string;
20
- options: Intl.DateTimeFormatOptions;
21
- }>;
22
- };
23
- /**
24
- * Get all common date/time/datetime formats for a given locale using Intl.DateTimeFormat.
25
- *
26
- * - Date formats: dateStyle only (full/long/medium/short)
27
- * - Time formats: timeStyle only
28
- * - Datetime formats: all combinations of dateStyle × timeStyle
29
- *
30
- * Returns tokens using your convention: YYYY, MM, DD, HH, II, SS, A, etc.
31
- */
32
- export declare function getCommonFormatsForLocale(lng: string | string[]): CommonFormats;
33
1
  export default function buildLocaleFromIntl(): void;
34
- export {};
@@ -5,22 +5,18 @@ import numProperties from "../../fn/object/numProperties.js";
5
5
  */
6
6
  function partsToPattern(parts, hourCycle) {
7
7
  let pattern = '';
8
- // If we see a dayPeriod in parts, it's definitely 12-hour clock
9
8
  const hasDayPeriod = parts.some(p => p.type === 'dayPeriod');
10
9
  const is12h = hasDayPeriod || hourCycle === 'h12' || hourCycle === 'h11';
11
10
  for (const p of parts) {
12
11
  switch (p.type) {
13
12
  case 'year':
14
- // Usually "2000" → "YYYY"
15
13
  pattern += 'YYYY';
16
14
  break;
17
15
  case 'month':
18
16
  if (/^\d+$/.test(p.value)) {
19
- // numeric month
20
17
  pattern += p.value.length === 2 ? 'MM' : 'M';
21
18
  }
22
19
  else {
23
- // textual month
24
20
  pattern += p.value.length > 3 ? 'MMMM' : 'MMM';
25
21
  }
26
22
  break;
@@ -28,16 +24,13 @@ function partsToPattern(parts, hourCycle) {
28
24
  pattern += p.value.length === 2 ? 'DD' : 'D';
29
25
  break;
30
26
  case 'weekday':
31
- // You can refine this if you care about full vs short
32
27
  pattern += p.value.length > 3 ? 'dddd' : 'ddd';
33
28
  break;
34
29
  case 'hour':
35
30
  if (is12h) {
36
- // 12-hour clock
37
31
  pattern += p.value.length === 2 ? 'hh' : 'h';
38
32
  }
39
33
  else {
40
- // 24-hour clock
41
34
  pattern += p.value.length === 2 ? 'HH' : 'H';
42
35
  }
43
36
  break;
@@ -48,11 +41,9 @@ function partsToPattern(parts, hourCycle) {
48
41
  pattern += 'SS';
49
42
  break;
50
43
  case 'dayPeriod':
51
- // AM/PM
52
44
  pattern += 'A';
53
45
  break;
54
46
  case 'timeZoneName':
55
- // You may want 'z' or 'Z' depending on your conventions
56
47
  pattern += 'z';
57
48
  break;
58
49
  case 'literal':
@@ -64,70 +55,110 @@ function partsToPattern(parts, hourCycle) {
64
55
  return pattern;
65
56
  }
66
57
  /**
67
- * Get all common date/time/datetime formats for a given locale using Intl.DateTimeFormat.
68
- *
69
- * - Date formats: dateStyle only (full/long/medium/short)
70
- * - Time formats: timeStyle only
71
- * - Datetime formats: all combinations of dateStyle × timeStyle
72
- *
73
- * Returns tokens using your convention: YYYY, MM, DD, HH, II, SS, A, etc.
58
+ * Returns common date / time / datetime formats for a locale, including
59
+ * all reasonable combinations of weekday, year, month and day.
74
60
  */
75
- export function getCommonFormatsForLocale(lng) {
76
- const dateStyles = ['full', 'long', 'medium', 'short'];
61
+ const getCommonFormatsForLocale = function (lng) {
77
62
  const timeStyles = ['full', 'long', 'medium', 'short'];
78
- // A fixed sample date to generate patterns.
79
- // 2 Jan 2000, 13:45:30 avoids 01/01 ambiguity and crosses 12h/24h boundaries.
80
- const sampleDate = new Date(Date.UTC(2000, 0, 2, 13, 45, 30));
63
+ // Fixed sample: 2 Jan 2000, 13:45:30 UTC
64
+ const sample = new Date(Date.UTC(2000, 0, 2, 13, 45, 30));
81
65
  const date = [];
82
66
  const time = [];
83
67
  const datetime = [];
84
- // --- Date-only formats ---
85
- for (const ds of dateStyles) {
86
- const options = { dateStyle: ds };
87
- const fmt = new Intl.DateTimeFormat(lng, options);
88
- const parts = fmt.formatToParts(sampleDate);
89
- const pattern = partsToPattern(parts, fmt.resolvedOptions().hourCycle);
90
- date.push({
91
- style: ds,
92
- pattern,
93
- sample: fmt.format(sampleDate),
94
- options
95
- });
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 ---
73
+ const weekdayOptions = [
74
+ undefined,
75
+ 'short',
76
+ 'long'
77
+ ];
78
+ const yearOptions = [
79
+ undefined,
80
+ 'numeric',
81
+ '2-digit'
82
+ ];
83
+ const monthOptions = [undefined, 'numeric', '2-digit', 'short', 'long'];
84
+ const dayOptions = [
85
+ undefined,
86
+ 'numeric',
87
+ '2-digit'
88
+ ];
89
+ const dateOptionsList = [];
90
+ for (const weekday of weekdayOptions) {
91
+ for (const year of yearOptions) {
92
+ for (const month of monthOptions) {
93
+ for (const day of dayOptions) {
94
+ // Skip combos with no actual date fields
95
+ if (!year && !month && !day) {
96
+ continue;
97
+ }
98
+ const options = {};
99
+ if (weekday)
100
+ options.weekday = weekday;
101
+ if (year)
102
+ options.year = year;
103
+ if (month)
104
+ options.month = month;
105
+ if (day)
106
+ options.day = day;
107
+ // Build formatter and pattern
108
+ const fmt = new Intl.DateTimeFormat(lng, options);
109
+ const parts = fmt.formatToParts(sample);
110
+ const resolved = fmt.resolvedOptions();
111
+ 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
+ }
121
+ }
122
+ }
123
+ }
96
124
  }
97
- // --- Time-only formats ---
125
+ // --- 2) TIME formats via timeStyle only ---
98
126
  for (const ts of timeStyles) {
99
127
  const options = { timeStyle: ts };
100
128
  const fmt = new Intl.DateTimeFormat(lng, options);
101
- const parts = fmt.formatToParts(sampleDate);
102
- const pattern = partsToPattern(parts, fmt.resolvedOptions().hourCycle);
103
- time.push({
104
- style: ts,
105
- pattern,
106
- sample: fmt.format(sampleDate),
107
- options
108
- });
109
- }
110
- // --- Date + time formats (all combinations) ---
111
- for (const ds of dateStyles) {
112
- for (const ts of timeStyles) {
113
- const options = {
114
- dateStyle: ds,
115
- timeStyle: ts
116
- };
117
- const fmt = new Intl.DateTimeFormat(lng, options);
118
- const parts = fmt.formatToParts(sampleDate);
119
- const pattern = partsToPattern(parts, fmt.resolvedOptions().hourCycle);
120
- datetime.push({
121
- dateStyle: ds,
122
- timeStyle: ts,
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,
123
136
  pattern,
124
- sample: fmt.format(sampleDate),
137
+ sample: fmt.format(sample),
125
138
  options
126
139
  });
127
140
  }
128
141
  }
142
+ // --- 3) DATETIME formats: each date option × each timeStyle ---
143
+ for (const dateOpts of dateOptionsList) {
144
+ for (const ts of timeStyles) {
145
+ const options = Object.assign(Object.assign({}, dateOpts), { timeStyle: ts });
146
+ const fmt = new Intl.DateTimeFormat(lng, options);
147
+ const parts = fmt.formatToParts(sample);
148
+ const resolved = fmt.resolvedOptions();
149
+ 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
+ }
158
+ }
159
+ }
129
160
  return { date, time, datetime };
130
- }
161
+ };
131
162
  export default function buildLocaleFromIntl() {
132
163
  if (numProperties(bbn.dt.locales)) {
133
164
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bbn/bbn",
3
- "version": "2.0.30",
3
+ "version": "2.0.32",
4
4
  "description": "Javascript toolkit",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",