diff --git a/dashboard.html b/dashboard.html
index 2bfa9ef..dc40bfc 100644
--- a/dashboard.html
+++ b/dashboard.html
@@ -349,31 +349,53 @@
return "green";
}
+ // Parse the wall-clock date/time directly from an ISO-8601 string that
+ // already carries an offset (e.g. "2026-03-31T10:00:00-03:00").
+ // We never let the browser re-interpret it into its own timezone.
+ function parseISOParts(dateTimeStr) {
+ // Matches: YYYY-MM-DDTHH:MM:SS(±HH:MM or Z)
+ const m = dateTimeStr.match(
+ /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})(?::\d{2})?/,
+ );
+ if (!m) return null;
+ return {
+ year: parseInt(m[1], 10),
+ month: parseInt(m[2], 10),
+ day: parseInt(m[3], 10),
+ hour: parseInt(m[4], 10),
+ minute: parseInt(m[5], 10),
+ };
+ }
+
function formatLocalTime(dateTimeStr) {
- const d = new Date(dateTimeStr);
- return d.toLocaleTimeString([], {
- hour: "2-digit",
- minute: "2-digit",
- hour12: false,
- });
+ const p = parseISOParts(dateTimeStr);
+ if (!p) return "";
+ const h = String(p.hour).padStart(2, "0");
+ const m = String(p.minute).padStart(2, "0");
+ return `${h}:${m}`;
}
function formatLocalDate(dateTimeStr) {
- const d = new Date(dateTimeStr);
+ const p = parseISOParts(dateTimeStr);
+ if (!p) return "";
+ // Build a UTC date just for the locale label so day/month names are correct
+ const d = new Date(Date.UTC(p.year, p.month - 1, p.day));
return d.toLocaleDateString([], {
weekday: "short",
month: "short",
day: "numeric",
+ timeZone: "UTC",
});
}
function isToday(dateTimeStr) {
const now = new Date();
- const d = new Date(dateTimeStr);
+ const p = parseISOParts(dateTimeStr);
+ if (!p) return false;
return (
- d.getFullYear() === now.getFullYear() &&
- d.getMonth() === now.getMonth() &&
- d.getDate() === now.getDate()
+ p.year === now.getFullYear() &&
+ p.month === now.getMonth() + 1 &&
+ p.day === now.getDate()
);
}