Add timezone preference and fix all date handling to be timezone-aware
Build and push image / build (push) Successful in 56s
Build and push image / build (push) Successful in 56s
Dates were computed using browser/server local time with no explicit timezone, causing inconsistencies when server runs in UTC. Now all "today" computations and date formatting use the user's chosen IANA timezone, persisted in localStorage and selectable from Settings. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
+19
-10
@@ -1,4 +1,9 @@
|
||||
// fmt.* — verbatim port from primitives.jsx
|
||||
import { getToday } from "./tz.js";
|
||||
|
||||
function parseDate(s: string): Date {
|
||||
return new Date(s.length === 10 ? s + "T12:00:00" : s);
|
||||
}
|
||||
|
||||
export const fmt = {
|
||||
g(n: number | null | undefined): string {
|
||||
if (n == null) return "—";
|
||||
@@ -17,22 +22,26 @@ export const fmt = {
|
||||
if (n == null) return "—";
|
||||
return `${(+n).toFixed(1)}%`;
|
||||
},
|
||||
date(s: string | null | undefined): string {
|
||||
date(s: string | null | undefined, tz?: string): string {
|
||||
if (!s) return "—";
|
||||
const d = new Date(s);
|
||||
return d.toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" });
|
||||
const opts: Intl.DateTimeFormatOptions = { month: "short", day: "numeric", year: "numeric" };
|
||||
if (tz) opts.timeZone = tz;
|
||||
return parseDate(s).toLocaleDateString("en-US", opts);
|
||||
},
|
||||
dateShort(s: string | null | undefined): string {
|
||||
dateShort(s: string | null | undefined, tz?: string): string {
|
||||
if (!s) return "—";
|
||||
const d = new Date(s);
|
||||
return d.toLocaleDateString("en-US", { month: "short", day: "numeric" });
|
||||
const opts: Intl.DateTimeFormatOptions = { month: "short", day: "numeric" };
|
||||
if (tz) opts.timeZone = tz;
|
||||
return parseDate(s).toLocaleDateString("en-US", opts);
|
||||
},
|
||||
daysAgo(s: string | null | undefined): string {
|
||||
daysAgo(s: string | null | undefined, tz?: string): string {
|
||||
if (!s) return "—";
|
||||
const ms = Date.now() - new Date(s).getTime();
|
||||
const d = Math.floor(ms / 86_400_000);
|
||||
const todayMs = +parseDate(tz ? getToday(tz) : new Date().toISOString().slice(0, 10));
|
||||
const thenMs = +parseDate(s);
|
||||
const d = Math.floor((todayMs - thenMs) / 86_400_000);
|
||||
if (d === 0) return "today";
|
||||
if (d === 1) return "yesterday";
|
||||
if (d < 0) return "in the future";
|
||||
if (d < 30) return `${d}d ago`;
|
||||
if (d < 365) return `${Math.floor(d / 30)}mo ago`;
|
||||
return `${Math.floor(d / 365)}y ago`;
|
||||
|
||||
Reference in New Issue
Block a user