website/src/components/Clock.astro
2026-09-09 15:21:35 -04:00

89 lines
2.7 KiB
Plaintext

---
import { Icon } from "astro-icon/components";
const TZ = "America/New_York";
const now = new Date();
const fmt = (opts: Intl.DateTimeFormatOptions) =>
new Intl.DateTimeFormat("en-US", { timeZone: TZ, ...opts }).formatToParts(now);
const t = fmt({ hour: "numeric", minute: "2-digit", hour12: true });
const hour = t.find((p) => p.type === "hour")?.value ?? "--";
const minute = t.find((p) => p.type === "minute")?.value ?? "--";
const mer = (t.find((p) => p.type === "dayPeriod")?.value ?? "").toUpperCase();
const zone = fmt({ timeZoneName: "short" }).find((p) => p.type === "timeZoneName")?.value ?? "ET";
---
<div
class="clock"
data-tz={TZ}
role="img"
aria-label={`zach's local time — ${hour}:${minute} ${mer} ${zone}`}
>
<Icon class="clock__ico" name="ph:clock" aria-hidden="true" />
<span class="clock__time" id="clock-time">{hour}:{minute}</span>
<span class="clock__mer" id="clock-mer">{mer}</span>
<span class="clock__zone" id="clock-zone">{zone}</span>
</div>
<style>
.clock {
display: inline-flex;
align-items: baseline;
gap: 0.55ch;
padding: 0.36rem 0.7rem;
background: var(--paper-2);
border: 1px solid var(--line);
border-radius: 8px;
font-family: var(--mono);
font-size: 0.82rem;
letter-spacing: 0.04em;
font-variant-numeric: tabular-nums;
}
.clock__ico {
width: 0.95em;
height: 0.95em;
flex: none;
color: var(--faint);
align-self: center;
}
.clock__time {
color: var(--ink);
}
.clock__mer,
.clock__zone {
font-size: 0.82em;
letter-spacing: 0.1em;
color: var(--faint);
}
</style>
<script>
const root = document.querySelector<HTMLElement>(".clock");
const timeEl = document.getElementById("clock-time");
const merEl = document.getElementById("clock-mer");
const zoneEl = document.getElementById("clock-zone");
if (root && timeEl) {
const tz = root.dataset.tz || "America/New_York";
const timeFmt = new Intl.DateTimeFormat("en-US", {
timeZone: tz,
hour: "numeric",
minute: "2-digit",
hour12: true,
});
const zoneFmt = new Intl.DateTimeFormat("en-US", { timeZone: tz, timeZoneName: "short" });
const tick = () => {
const d = new Date();
const p = timeFmt.formatToParts(d);
const h = p.find((x) => x.type === "hour")?.value ?? "--";
const m = p.find((x) => x.type === "minute")?.value ?? "--";
const mer = (p.find((x) => x.type === "dayPeriod")?.value ?? "").toUpperCase();
timeEl.textContent = `${h}:${m}`;
if (merEl) merEl.textContent = mer;
const z = zoneFmt.formatToParts(d).find((x) => x.type === "timeZoneName")?.value;
if (zoneEl && z) zoneEl.textContent = z;
};
tick();
setInterval(tick, 15_000);
}
</script>