Skip to content
79 linesCodeBlameRaw

Pick any line to see why it is the way it is: the commit, the pull request and issue it came from, and what the agent was thinking.

The runner base keeps its old comment, so the pushed base image still matches its folder1/**
2 * Times in the reader's own zone. The zone comes from Cloudflare's guess
3 * for the request (`request.cf.timezone`), or a `g1t_tz` cookie when the
4 * reader has one; anything unknown is UTC. Every time shown carries its
5 * zone's abbreviation, and `<time datetime>` keeps the UTC instant. No
6 * Workers imports, so it is tested under Node.
7 */
8
9export const ZONE_COOKIE = "g1t_tz";
10
11const MONTHS = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
12
13/** Whether `tz` is a time zone this runtime knows. */
14export function validZone(tz: unknown): tz is string {
15 if (typeof tz !== "string" || !tz || tz.length > 64) return false;
16 try {
17 new Intl.DateTimeFormat("en-US", { timeZone: tz });
18 return true;
19 } catch {
20 return false;
21 }
22}
23
24function cookie(header: string | null | undefined, name: string): string | null {
25 for (const part of (header ?? "").split(";")) {
26 const [k, ...v] = part.trim().split("=");
27 if (k === name) {
28 try {
29 return decodeURIComponent(v.join("="));
30 } catch {
31 return null;
32 }
33 }
34 }
35 return null;
36}
37
38/** The reader's zone: their cookie, else Cloudflare's guess, else UTC. */
39export function readZone(cookieHeader: string | null | undefined, cfTimezone: unknown): string {
40 const chosen = cookie(cookieHeader, ZONE_COOKIE);
41 if (validZone(chosen)) return chosen;
42 return validZone(cfTimezone) ? cfTimezone : "UTC";
43}
44
45/** The zone's short name at that moment: "PDT", "CEST", "BST", or "UTC+9" where there is no common one. */
46export function zoneAbbr(date: Date, tz: string): string {
47 if (tz === "UTC" || tz === "Etc/UTC" || tz === "Etc/GMT") return "UTC";
48 let offset = "";
49 for (const locale of ["en-US", "en-GB"]) {
50 const name = new Intl.DateTimeFormat(locale, { timeZone: tz, timeZoneName: "short" }).formatToParts(date).find((p) => p.type === "timeZoneName")?.value ?? "";
51 if (name && !/^(GMT|UTC)[+-−]/.test(name)) return name;
52 offset ||= name;
53 }
54 return offset.replace(/^GMT/, "UTC") || "UTC";
55}
56
57/** The wall-clock parts of a moment in a zone. */
58function parts(date: Date, tz: string) {
59 const got = Object.fromEntries(
60 new Intl.DateTimeFormat("en-US", { timeZone: tz, year: "numeric", month: "numeric", day: "numeric", hour: "2-digit", minute: "2-digit", hourCycle: "h23" })
61 .formatToParts(date)
62 .map((p) => [p.type, p.value]),
63 );
64 return { year: Number(got.year), month: Number(got.month), day: Number(got.day), hh: String(got.hour).padStart(2, "0"), mm: got.minute };
65}
66
67/** "6 Oct 2026, 00:25 PDT". */
68export function timeIn(at: string | Date, tz = "UTC"): string {
69 const date = new Date(at);
70 const p = parts(date, tz);
71 return `${p.day} ${MONTHS[p.month - 1]} ${p.year}, ${p.hh}:${p.mm} ${zoneAbbr(date, tz)}`;
72}
73
74/** "6 Oct 00:25 PDT": shorter, for lines that already say the year. */
75export function stampIn(at: string | Date, tz = "UTC"): string {
76 const date = new Date(at);
77 const p = parts(date, tz);
78 return `${p.day} ${MONTHS[p.month - 1]} ${p.hh}:${p.mm} ${zoneAbbr(date, tz)}`;
79}

This file's history is long; its oldest lines are credited to the oldest commit read.