repos
/ orchard main

orchard

mirror

Every site I host, in one repo, along with the Cloudflare Tunnel and Caddy that front them. It's all Go, Vite, and SQLite, and it runs on a desktop at home with nothing listening on an inbound port.

blogbuncaddycloudflare-tunneldockergogolanghomelabhtml-templatemonorepoself-hostedseosqlitestatic-sitetypstuptime-monitoringviteweb-analytics

1.7 KB · 51 lines · JavaScript Raw History
 1// The clock ticks without the server, since a second hand over a stream would
 2// be a frame a second for something the browser already knows. UTC sits beside
 3// local because every timestamp the server logs is UTC.
 4const utc = document.querySelector("[data-clock-utc]");
 5const zone = document.querySelector("[data-clock-zone]");
 6const local = document.querySelector("[data-clock-local]");
 7const date = document.querySelector("[data-clock-date]");
 8
 9if (utc && local && date) {
10  const hms = (tz) =>
11    new Intl.DateTimeFormat("en-GB", {
12      hour: "2-digit",
13      minute: "2-digit",
14      second: "2-digit",
15      hour12: false,
16      ...(tz ? { timeZone: tz } : {}),
17    });
18
19  const utcFmt = hms("UTC");
20  const localFmt = hms(null);
21  const dateFmt = new Intl.DateTimeFormat("en-GB", {
22    weekday: "short",
23    day: "2-digit",
24    month: "short",
25  });
26
27  // "LOCAL" on its own does not say local to what, and the answer differs per
28  // viewer, so the label carries the browser's actual zone abbreviation. Intl
29  // gives the short name for today, which is what handles daylight saving
30  // without a table.
31  if (zone) {
32    const now = new Date();
33    const parts = new Intl.DateTimeFormat("en-US", {
34      timeZoneName: "short",
35    }).formatToParts(now);
36    const named = parts.find((p) => p.type === "timeZoneName");
37    zone.textContent = named ? named.value.toUpperCase() : "LOCAL";
38    zone.title = Intl.DateTimeFormat().resolvedOptions().timeZone || "";
39  }
40
41  const tick = () => {
42    const now = new Date();
43    utc.textContent = utcFmt.format(now);
44    local.textContent = localFmt.format(now);
45    date.textContent = dateFmt.format(now).toUpperCase();
46  };
47
48  tick();
49  setInterval(tick, 1000);
50}