Date / time format

This commit is contained in:
binwiederhier
2026-06-29 22:24:04 -04:00
parent 4c0bd70408
commit c873064cad
46 changed files with 420 additions and 69 deletions
+59 -6
View File
@@ -7,7 +7,7 @@ import pop from "../sounds/pop.mp3";
import popSwoosh from "../sounds/pop-swoosh.mp3";
import config from "./config";
import emojisMapped from "./emojisMapped";
import { THEME } from "./Prefs";
import { THEME, DATE_FORMAT, TIME_FORMAT } from "./Prefs";
export const tiersUrl = (baseUrl) => `${baseUrl}/v1/tiers`;
export const shortUrl = (url) => url.replaceAll(/https?:\/\//g, "");
@@ -151,14 +151,67 @@ export const hashCode = (s) => {
*/
export const getKebabCaseLangStr = (language) => (typeof language === "string" && language.length > 0 ? language.replace(/_/g, "-") : "en");
export const formatShortDateTime = (timestamp, language) =>
new Intl.DateTimeFormat(getKebabCaseLangStr(language), {
dateStyle: "short",
// Date/time display is intentionally NOT tied to the UI translation language; it follows the
// dedicated dateFormat/timeFormat prefs (see Prefs.js). SYSTEM modes pass no locale to Intl so it
// uses the browser's default (the user's OS region/format settings). DMY/MDY force the day/month
// order; ISO8601 forces an unambiguous, locale-independent and always-24-hour format. The clock
// (12h/24h) is chosen independently via timeFormat. All variants render local time.
const pad2 = (n) => String(n).padStart(2, "0");
// Per-format date builders (only ISO zero-pads; the rest drop leading zeros). The router below
// (formatDate) picks one of these for a fixed-order format, or falls back to the browser locale.
const formatDateIso = (date) => `${date.getFullYear()}-${pad2(date.getMonth() + 1)}-${pad2(date.getDate())}`;
const formatDateDmy = (date) => `${date.getDate()}/${date.getMonth() + 1}/${date.getFullYear()}`;
const formatDateDmyDot = (date) => `${date.getDate()}.${date.getMonth() + 1}.${date.getFullYear()}`;
const formatDateMdy = (date) => `${date.getMonth() + 1}/${date.getDate()}/${date.getFullYear()}`;
// ISO date-time is always YYYY-MM-DD HH:mm (24-hour), independent of the timeFormat pref.
const formatDateTimeIso = (date) => `${formatDateIso(date)} ${pad2(date.getHours())}:${pad2(date.getMinutes())}`;
// undefined lets the locale decide the clock; true/false force a 12- or 24-hour clock. Passing
// hour12: undefined to Intl is equivalent to omitting it (and avoids an object spread that would
// otherwise widen the sibling dateStyle/timeStyle string literals).
const hour12For = (timeFormat) => {
if (timeFormat === TIME_FORMAT.H12) return true;
if (timeFormat === TIME_FORMAT.H24) return false;
return undefined;
};
// The date router: delegates to a fixed-order builder, or falls back to the browser locale (SYSTEM).
export const formatDate = (timestamp, dateFormat = DATE_FORMAT.SYSTEM) => {
const date = new Date(timestamp * 1000);
switch (dateFormat) {
case DATE_FORMAT.ISO8601:
return formatDateIso(date);
case DATE_FORMAT.DMY:
return formatDateDmy(date);
case DATE_FORMAT.DMY_DOT:
return formatDateDmyDot(date);
case DATE_FORMAT.MDY:
return formatDateMdy(date);
default:
return new Intl.DateTimeFormat(undefined, { dateStyle: "short" }).format(date);
}
};
export const formatTime = (timestamp, timeFormat = TIME_FORMAT.SYSTEM) =>
new Intl.DateTimeFormat(undefined, {
timeStyle: "short",
hour12: hour12For(timeFormat),
}).format(new Date(timestamp * 1000));
export const formatShortDate = (timestamp, language) =>
new Intl.DateTimeFormat(getKebabCaseLangStr(language), { dateStyle: "short" }).format(new Date(timestamp * 1000));
export const formatDateTime = (timestamp, dateFormat = DATE_FORMAT.SYSTEM, timeFormat = TIME_FORMAT.SYSTEM) => {
if (dateFormat === DATE_FORMAT.ISO8601) {
return formatDateTimeIso(new Date(timestamp * 1000));
} else if ([DATE_FORMAT.DMY, DATE_FORMAT.DMY_DOT, DATE_FORMAT.MDY].includes(dateFormat)) {
return `${formatDate(timestamp, dateFormat)} ${formatTime(timestamp, timeFormat)}`;
}
return new Intl.DateTimeFormat(undefined, {
dateStyle: "short",
timeStyle: "short",
hour12: hour12For(timeFormat),
}).format(new Date(timestamp * 1000));
};
export const formatShortDuration = (ms, language) => {
const seconds = Math.round(ms / 1000);