const KEY = "faucet-tz";
export function getTz() {
try { return localStorage.getItem(KEY) || "local"; } catch { return "local"; }
}
export function setTz(z) {
try { localStorage.setItem(KEY, z); } catch { }
}
const LOCAL_ZONE = (() => {
try { return Intl.DateTimeFormat().resolvedOptions().timeZone || ""; } catch { return ""; }
})();
export const TZ_OPTIONS = [
{ value: "local", label: `Local${LOCAL_ZONE ? ` - ${LOCAL_ZONE}` : ""}` },
{ value: "UTC", label: "UTC" },
{ value: "America/Los_Angeles", label: "Los Angeles" },
{ value: "America/New_York", label: "New York" },
{ value: "Europe/London", label: "London" },
{ value: "Europe/Berlin", label: "Berlin" },
{ value: "Asia/Kolkata", label: "Kolkata" },
{ value: "Asia/Singapore", label: "Singapore" },
{ value: "Asia/Tokyo", label: "Tokyo" },
{ value: "Australia/Sydney", label: "Sydney" },
];
export function tzShort() {
const tz = getTz();
return tz === "local" ? "local" : tz;
}
const zoneOpt = (tz) => (tz === "local" ? {} : { timeZone: tz });
export function formatTs(value) {
if (!value) return "—";
const d = new Date(value);
if (isNaN(d.getTime())) return "—";
try {
return new Intl.DateTimeFormat("en-US", {
year: "numeric", month: "2-digit", day: "2-digit",
hour: "2-digit", minute: "2-digit", second: "2-digit", hour12: true,
...zoneOpt(getTz()),
}).format(d);
} catch {
return d.toLocaleString();
}
}
export function formatTsSplit(value) {
const d = value ? new Date(value) : null;
if (!d || isNaN(d.getTime())) return null;
const fmt = (opts) => {
try {
return new Intl.DateTimeFormat("en-US", { ...opts, ...zoneOpt(getTz()) }).format(d);
} catch {
return new Intl.DateTimeFormat("en-US", opts).format(d);
}
};
return {
time: fmt({ hour: "2-digit", minute: "2-digit", second: "2-digit", hour12: true }),
date: fmt({ year: "numeric", month: "short", day: "numeric" }),
};
}
function partsInZone(date, tz, withSeconds) {
const p = new Intl.DateTimeFormat("en-US", {
timeZone: tz, year: "numeric", month: "2-digit", day: "2-digit",
hour: "2-digit", minute: "2-digit", ...(withSeconds ? { second: "2-digit" } : {}),
hour12: false,
}).formatToParts(date).reduce((a, x) => { a[x.type] = x.value; return a; }, {});
return p;
}
export function zonedWallToUtc(y, mo, d, h, mi) {
const tz = getTz();
if (tz === "local") return new Date(y, mo, d, h, mi);
const asUtc = Date.UTC(y, mo, d, h, mi);
const p = partsInZone(new Date(asUtc), tz, true);
const shown = Date.UTC(+p.year, +p.month - 1, +p.day, +p.hour % 24, +p.minute, +p.second);
return new Date(asUtc - (shown - asUtc)); }
export function utcToZonedWall(date) {
const tz = getTz();
if (tz === "local") {
return { y: date.getFullYear(), mo: date.getMonth(), d: date.getDate(), h: date.getHours(), mi: date.getMinutes() };
}
const p = partsInZone(date, tz, false);
return { y: +p.year, mo: +p.month - 1, d: +p.day, h: +p.hour % 24, mi: +p.minute };
}