@bbn/bbn 2.0.28 → 2.0.30
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/dist/bbn.js +1 -1
- package/dist/bbn.js.map +1 -1
- package/dist/dt/functions/buildLocaleFromIntl.js +4 -1
- package/dist/dt/functions/guessFormat.d.ts +12 -0
- package/dist/dt/functions/guessFormat.js +120 -0
- package/dist/dt.d.ts +2 -0
- package/dist/dt.js +2 -0
- package/package.json +1 -1
|
@@ -155,12 +155,15 @@ export default function buildLocaleFromIntl() {
|
|
|
155
155
|
weekdaysLong.push(fmtWeekLong.format(d));
|
|
156
156
|
weekdaysShort.push(fmtWeekShort.format(d));
|
|
157
157
|
}
|
|
158
|
-
const { date, time } = getCommonFormatsForLocale(langs);
|
|
158
|
+
const { date, time, datetime } = getCommonFormatsForLocale(langs);
|
|
159
159
|
extend(bbn.dt.locales, {
|
|
160
160
|
monthsLong,
|
|
161
161
|
monthsShort,
|
|
162
162
|
weekdaysLong,
|
|
163
163
|
weekdaysShort,
|
|
164
|
+
date,
|
|
165
|
+
time,
|
|
166
|
+
datetime
|
|
164
167
|
});
|
|
165
168
|
}
|
|
166
169
|
;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Guess a date format string for the given input.
|
|
3
|
+
*
|
|
4
|
+
* - If `formats` is provided, it will try those formats in order and return
|
|
5
|
+
* the first one that successfully parses.
|
|
6
|
+
* - If `formats` is not provided, it will try a set of built-in common formats
|
|
7
|
+
* (MySQL, ISO/JS, EU/US, full-text using bbn.dt.locales).
|
|
8
|
+
* - Returns `null` if no format matches.
|
|
9
|
+
*
|
|
10
|
+
* NOTE: It relies on `this.parse(input, format)` NOT throwing when the format is correct.
|
|
11
|
+
*/
|
|
12
|
+
export default function guessFormat(input: string, formats?: string[] | string): string | null;
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import buildLocaleFromIntl from './buildLocaleFromIntl.js';
|
|
2
|
+
import parse from './parse.js';
|
|
3
|
+
/**
|
|
4
|
+
* Guess a date format string for the given input.
|
|
5
|
+
*
|
|
6
|
+
* - If `formats` is provided, it will try those formats in order and return
|
|
7
|
+
* the first one that successfully parses.
|
|
8
|
+
* - If `formats` is not provided, it will try a set of built-in common formats
|
|
9
|
+
* (MySQL, ISO/JS, EU/US, full-text using bbn.dt.locales).
|
|
10
|
+
* - Returns `null` if no format matches.
|
|
11
|
+
*
|
|
12
|
+
* NOTE: It relies on `this.parse(input, format)` NOT throwing when the format is correct.
|
|
13
|
+
*/
|
|
14
|
+
export default function guessFormat(input, formats) {
|
|
15
|
+
var _a;
|
|
16
|
+
const str = input.trim();
|
|
17
|
+
if (!str) {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
const tryFormats = (formatsToTry) => {
|
|
21
|
+
for (const fmt of formatsToTry) {
|
|
22
|
+
try {
|
|
23
|
+
// We only care that it parses without throwing
|
|
24
|
+
parse(str, fmt);
|
|
25
|
+
return fmt;
|
|
26
|
+
}
|
|
27
|
+
catch (_a) {
|
|
28
|
+
// ignore
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return null;
|
|
32
|
+
};
|
|
33
|
+
// If user provided formats, restrict to those only
|
|
34
|
+
if (formats) {
|
|
35
|
+
const list = Array.isArray(formats) ? formats : [formats];
|
|
36
|
+
return tryFormats(list);
|
|
37
|
+
}
|
|
38
|
+
// -------- Autodetection mode (no user-provided formats) --------
|
|
39
|
+
const lower = str.toLowerCase();
|
|
40
|
+
// Access locales for full-text formats (months / weekdays)
|
|
41
|
+
buildLocaleFromIntl();
|
|
42
|
+
const loc = ((_a = bbn === null || bbn === void 0 ? void 0 : bbn.dt) === null || _a === void 0 ? void 0 : _a.locales) || {};
|
|
43
|
+
const monthsLong = loc.monthsLong || [];
|
|
44
|
+
const monthsShort = loc.monthsShort || [];
|
|
45
|
+
const weekdaysLong = loc.weekdaysLong || [];
|
|
46
|
+
const weekdaysShort = loc.weekdaysShort || [];
|
|
47
|
+
const timeFormats = loc.time || [];
|
|
48
|
+
const dateFormats = loc.date || [];
|
|
49
|
+
const datetimeFormats = loc.datetime || [];
|
|
50
|
+
const hasMonthName = monthsLong.some(m => lower.includes(m.toLowerCase())) ||
|
|
51
|
+
monthsShort.some(m => lower.includes(m.toLowerCase()));
|
|
52
|
+
const hasWeekdayName = weekdaysLong.some(w => lower.includes(w.toLowerCase())) ||
|
|
53
|
+
weekdaysShort.some(w => lower.includes(w.toLowerCase()));
|
|
54
|
+
const hasLetterTZ = /gmt|utc|[+-]\d{2}:?\d{2}|z$/i.test(str);
|
|
55
|
+
const looksISO = /^\d{4}-\d{2}-\d{2}t\d{2}:\d{2}:\d{2}(\.\d+)?(z|[+\-]\d{2}:?\d{2})?$/i.test(str);
|
|
56
|
+
const looksMySQLDateTime = /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}(:\d{2}(\.\d+)?)?$/i.test(str);
|
|
57
|
+
const looksMySQLDate = /^\d{4}-\d{2}-\d{2}$/.test(str);
|
|
58
|
+
const looksTimeOnly = /^\d{2}:\d{2}(:\d{2}(\.\d+)?)?$/.test(str);
|
|
59
|
+
// Start building candidate formats (most specific first)
|
|
60
|
+
const candidates = [
|
|
61
|
+
...datetimeFormats.map(f => f.pattern),
|
|
62
|
+
];
|
|
63
|
+
// --- Full-text / locale-based formats ---
|
|
64
|
+
if (hasMonthName || hasWeekdayName) {
|
|
65
|
+
// e.g. "Monday 15 January 2024"
|
|
66
|
+
candidates.push('dddd, DD MMMM YYYY HH:II:SSZ', 'dddd, DD MMMM YYYY HH:II:SS', 'dddd, DD MMMM YYYY', 'DD MMMM YYYY HH:II:SSZ', 'DD MMMM YYYY HH:II:SS', 'DD MMMM YYYY', 'ddd, DD MMM YYYY HH:II:SSZ', 'ddd, DD MMM YYYY HH:II:SS', 'ddd, DD MMM YYYY');
|
|
67
|
+
// JS Date.toString() / toUTCString()-like
|
|
68
|
+
// "Tue Oct 29 2024 14:30:00 GMT+0200"
|
|
69
|
+
candidates.push('ddd MMM DD YYYY HH:II:SSZ', 'ddd, DD MMM YYYY HH:II:SS z');
|
|
70
|
+
}
|
|
71
|
+
// --- ISO / JS-like default formats ---
|
|
72
|
+
if (looksISO || str.includes('T')) {
|
|
73
|
+
candidates.push('YYYY-MM-DDTHH:II:SS.msZ', 'YYYY-MM-DDTHH:II:SSZ', 'YYYY-MM-DDTHH:II:SS.ms', 'YYYY-MM-DDTHH:II:SS', 'YYYY-MM-DDTHH:II:Z', 'YYYY-MM-DDTHH:II');
|
|
74
|
+
}
|
|
75
|
+
// --- MySQL classic formats ---
|
|
76
|
+
if (looksMySQLDateTime) {
|
|
77
|
+
candidates.push('YYYY-MM-DD HH:II:SS.msZ', 'YYYY-MM-DD HH:II:SSZ', 'YYYY-MM-DD HH:II:SS.ms', 'YYYY-MM-DD HH:II:SS', 'YYYY-MM-DD HH:II');
|
|
78
|
+
}
|
|
79
|
+
if (looksMySQLDate) {
|
|
80
|
+
candidates.push('YYYY-MM-DD');
|
|
81
|
+
}
|
|
82
|
+
// --- Time-only strings ---
|
|
83
|
+
if (looksTimeOnly) {
|
|
84
|
+
candidates.push(...timeFormats.map(f => f.pattern), 'HH:II:SS.msZ', 'HH:II:SS.ms', 'HH:II:SS', 'HH:II');
|
|
85
|
+
}
|
|
86
|
+
// --- Common EU / US formats ---
|
|
87
|
+
candidates.push(...dateFormats.map(f => f.pattern),
|
|
88
|
+
// European style
|
|
89
|
+
'DD/MM/YYYY HH:II:SSZ', 'DD/MM/YYYY HH:II:SS', 'DD/MM/YYYY HH:II', 'DD/MM/YYYY', 'DD-MM-YYYY HH:II:SSZ', 'DD-MM-YYYY HH:II:SS', 'DD-MM-YYYY HH:II', 'DD-MM-YYYY',
|
|
90
|
+
// US style
|
|
91
|
+
'MM/DD/YYYY HH:II:SSZ', 'MM/DD/YYYY HH:II:SS', 'MM/DD/YYYY HH:II', 'MM/DD/YYYY',
|
|
92
|
+
// Dot-separated
|
|
93
|
+
'YYYY.MM.DD HH:II:SSZ', 'YYYY.MM.DD HH:II:SS', 'YYYY.MM.DD',
|
|
94
|
+
// MySQL-ish (if we haven't already pushed them by detection)
|
|
95
|
+
'YYYY-MM-DD HH:II:SSZ', 'YYYY-MM-DD HH:II:SS', 'YYYY-MM-DD HH:II', 'YYYY-MM-DD');
|
|
96
|
+
// If we see clear timezone indicators, prioritize formats with Z / z
|
|
97
|
+
if (hasLetterTZ) {
|
|
98
|
+
const withTZ = candidates.filter(f => f.includes('Z') || f.includes('z'));
|
|
99
|
+
const withoutTZ = candidates.filter(f => !f.includes('Z') && !f.includes('z'));
|
|
100
|
+
const reordered = [...withTZ, ...withoutTZ];
|
|
101
|
+
const fmt = tryFormats(reordered);
|
|
102
|
+
if (fmt) {
|
|
103
|
+
return fmt;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
const fmt = tryFormats(candidates);
|
|
108
|
+
if (fmt) {
|
|
109
|
+
return fmt;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
// --- Last resort: native JS parsing ---
|
|
113
|
+
const jsDate = new Date(str);
|
|
114
|
+
if (!isNaN(jsDate.getTime())) {
|
|
115
|
+
// You can treat "native" as a special keyword meaning:
|
|
116
|
+
// "use Date/Temporal to parse directly".
|
|
117
|
+
return 'native';
|
|
118
|
+
}
|
|
119
|
+
return null;
|
|
120
|
+
}
|
package/dist/dt.d.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import parse from './dt/functions/parse.js';
|
|
2
|
+
import guessFormat from './dt/functions/guessFormat.js';
|
|
2
3
|
declare const dt: {
|
|
3
4
|
(value: any, inputFormat?: null | String): void;
|
|
4
5
|
locales: any;
|
|
5
6
|
parse: typeof parse;
|
|
7
|
+
guessFormat: typeof guessFormat;
|
|
6
8
|
time(): void;
|
|
7
9
|
date(): void;
|
|
8
10
|
dateTime(): void;
|
package/dist/dt.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import parse from './dt/functions/parse.js';
|
|
2
|
+
import guessFormat from './dt/functions/guessFormat.js';
|
|
2
3
|
const patterns = [
|
|
3
4
|
// MariaDB DATETIME "YYYY-MM-DD HH:MM:SS"
|
|
4
5
|
{
|
|
@@ -191,6 +192,7 @@ const dt = (value, inputFormat = null) => {
|
|
|
191
192
|
};
|
|
192
193
|
dt.locales = Object.create(null);
|
|
193
194
|
dt.parse = parse;
|
|
195
|
+
dt.guessFormat = guessFormat;
|
|
194
196
|
dt.time = () => { };
|
|
195
197
|
dt.date = () => { };
|
|
196
198
|
dt.dateTime = () => { };
|