89 lines
2.7 KiB
Plaintext
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>
|