@andrian.yablonskyy/thub-common 1.0.18 → 1.0.20
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/package.json +1 -1
- package/src/datetime.js +53 -0
- package/src/index.js +1 -0
package/package.json
CHANGED
package/src/datetime.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file packages/shared/src/datetime.js
|
|
3
|
+
* @description The one human-readable date/time format used everywhere: dd/mm/yyyy HH:MM:SS, 24-hour
|
|
4
|
+
*
|
|
5
|
+
* @author Andrian Yablonskyy
|
|
6
|
+
* @copyright Copyright (c) 2026 Andrian Yablonskyy. All rights reserved.
|
|
7
|
+
*
|
|
8
|
+
* This file is part of TestHub and is proprietary and confidential.
|
|
9
|
+
* Unauthorized copying, modification, distribution, or use of this file,
|
|
10
|
+
* via any medium, is strictly prohibited without prior written permission
|
|
11
|
+
* from AdSystem.PRO.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
'use strict';
|
|
15
|
+
|
|
16
|
+
// One formatter per time zone — building an Intl.DateTimeFormat is the
|
|
17
|
+
// expensive part, and a dashboard page formats many timestamps.
|
|
18
|
+
const formatters = new Map();
|
|
19
|
+
|
|
20
|
+
function formatterFor(timeZone){
|
|
21
|
+
const key = timeZone || '';
|
|
22
|
+
if (!formatters.has(key)){
|
|
23
|
+
formatters.set(key, new Intl.DateTimeFormat('en-GB', {
|
|
24
|
+
...(timeZone ? { timeZone } : {}),
|
|
25
|
+
day: '2-digit',
|
|
26
|
+
month: '2-digit',
|
|
27
|
+
year: 'numeric',
|
|
28
|
+
hour: '2-digit',
|
|
29
|
+
minute: '2-digit',
|
|
30
|
+
second: '2-digit',
|
|
31
|
+
hourCycle: 'h23' // 00-23, never "24:00:00" at midnight
|
|
32
|
+
}));
|
|
33
|
+
}
|
|
34
|
+
return formatters.get(key);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// "28/09/2026 14:05:03" for a Date, ISO string or epoch ms, in `timeZone`
|
|
38
|
+
// (IANA name; omitted = this process's local zone). Built from parts, so
|
|
39
|
+
// the result doesn't depend on the ICU version's punctuation. `fallback`
|
|
40
|
+
// for an empty or unparseable value.
|
|
41
|
+
function formatDateTime(value, { timeZone, fallback = '—' } = {}){
|
|
42
|
+
if (value === null || value === undefined || value === ''){
|
|
43
|
+
return fallback;
|
|
44
|
+
}
|
|
45
|
+
const date = value instanceof Date ? value : new Date(value);
|
|
46
|
+
if (Number.isNaN(date.getTime())){
|
|
47
|
+
return fallback;
|
|
48
|
+
}
|
|
49
|
+
const p = Object.fromEntries(formatterFor(timeZone).formatToParts(date).map(({ type, value: v }) => [type, v]));
|
|
50
|
+
return `${p.day}/${p.month}/${p.year} ${p.hour}:${p.minute}:${p.second}`;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
module.exports = { formatDateTime };
|