Files
dockhand-upstream/src/lib/utils/date-format.ts
T
2026-06-27 15:15:54 +02:00

85 lines
2.5 KiB
TypeScript

/**
* Pure date/time formatting helpers — no SvelteKit / store imports.
*
* settings.ts wraps these with cached preferences and a reactive subscription;
* keeping the implementation here lets the formatters be unit-tested without
* dragging in $app/environment or svelte/store.
*/
export type TimeFormat = '12h' | '24h';
export type DateFormat = 'MM/DD/YYYY' | 'DD/MM/YYYY' | 'YYYY-MM-DD' | 'DD.MM.YYYY';
export interface DateTimeFormatters {
date: Intl.DateTimeFormat;
time: Intl.DateTimeFormat;
}
// Intl.DateTimeFormat construction is expensive; the caller caches one pair per
// timezone and rebuilds only when the timezone setting changes.
export function buildFormatters(timeZone: string | undefined): DateTimeFormatters {
const tz = timeZone || undefined;
return {
date: new Intl.DateTimeFormat('en-GB', {
timeZone: tz,
year: 'numeric',
month: '2-digit',
day: '2-digit'
}),
time: new Intl.DateTimeFormat('en-GB', {
timeZone: tz,
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: false
})
};
}
function pickPart(parts: Intl.DateTimeFormatPart[], type: Intl.DateTimeFormatPartTypes): string {
return parts.find((p) => p.type === type)?.value ?? '';
}
export function formatDatePartWith(d: Date, dateFormatter: Intl.DateTimeFormat, dateFormat: DateFormat): string {
const parts = dateFormatter.formatToParts(d);
const day = pickPart(parts, 'day');
const month = pickPart(parts, 'month');
const year = pickPart(parts, 'year');
switch (dateFormat) {
case 'MM/DD/YYYY':
return `${month}/${day}/${year}`;
case 'DD/MM/YYYY':
return `${day}/${month}/${year}`;
case 'YYYY-MM-DD':
return `${year}-${month}-${day}`;
case 'DD.MM.YYYY':
default:
return `${day}.${month}.${year}`;
}
}
export function formatTimePartWith(
d: Date,
timeFormatter: Intl.DateTimeFormat,
timeFormat: TimeFormat,
includeSeconds = false
): string {
const parts = timeFormatter.formatToParts(d);
const hours = parseInt(pickPart(parts, 'hour'), 10);
const minutes = pickPart(parts, 'minute');
const seconds = pickPart(parts, 'second');
if (timeFormat === '12h') {
const hour12 = hours === 0 ? 12 : hours > 12 ? hours - 12 : hours;
const ampm = hours >= 12 ? 'PM' : 'AM';
return includeSeconds
? `${hour12}:${minutes}:${seconds} ${ampm}`
: `${hour12}:${minutes} ${ampm}`;
} else {
const hour24 = hours.toString().padStart(2, '0');
return includeSeconds
? `${hour24}:${minutes}:${seconds}`
: `${hour24}:${minutes}`;
}
}