Skip to content

Where people and agents ship software together. The open-source git platform for the whole job: issues, agents, checks and deploys to the edge.

g1t.sh
119 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 sidebar asks billing whether it is on, not for the account, so no page waits on the card processor1/**
2 * Times in the staff member's own zone, on every page (components/ui.tsx
3 * `When`) and in the forms that take a time. sudo ships no script, so the
4 * zone comes from the request: the `sudo_tz` cookie when someone chose one
5 * (/timezone), else Cloudflare's guess (`request.cf.timezone`), else UTC.
6 * Every time shown says its zone's abbreviation, and `<time datetime>`
7 * plus the hover title keep the UTC instant. No Workers or React imports,
8 * so it is tested under Node.
9 */
10
11export const ZONE_COOKIE = "sudo_tz";
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
24/** A cookie's value from a Cookie header. */
25export function readCookie(header: string | null | undefined, name: string): string | null {
26 for (const part of (header ?? "").split(";")) {
27 const [k, ...v] = part.trim().split("=");
28 if (k === name) {
29 try {
30 return decodeURIComponent(v.join("="));
31 } catch {
32 return null;
33 }
34 }
35 }
36 return null;
37}
38
39/** The zone a request's pages use, and where it came from. */
40export function readZone(cookieHeader: string | null | undefined, cfTimezone: unknown): { zone: string; chosen: boolean } {
41 const chosen = readCookie(cookieHeader, ZONE_COOKIE);
42 if (validZone(chosen)) return { zone: chosen, chosen: true };
43 return { zone: validZone(cfTimezone) ? cfTimezone : "UTC", chosen: false };
44}
45
46/** The zone's short name at that moment: "PDT", "CEST", "BST", or "UTC+9" where there is no common one. */
47export function zoneAbbr(date: Date, tz: string): string {
48 if (tz === "UTC" || tz === "Etc/UTC" || tz === "Etc/GMT") return "UTC";
49 let offset = "";
50 for (const locale of ["en-US", "en-GB"]) {
51 const name = new Intl.DateTimeFormat(locale, { timeZone: tz, timeZoneName: "short" }).formatToParts(date).find((p) => p.type === "timeZoneName")?.value ?? "";
52 if (name && !/^(GMT|UTC)[+-−]/.test(name)) return name;
53 offset ||= name;
54 }
55 return offset.replace(/^GMT/, "UTC") || "UTC";
56}
57
58const formats = new Map<string, Intl.DateTimeFormat>();
59function format(tz: string, time: boolean): Intl.DateTimeFormat {
60 const key = `${tz}|${time}`;
61 let f = formats.get(key);
62 if (!f) {
63 f = new Intl.DateTimeFormat("en-US", time ? { dateStyle: "medium", timeStyle: "short", timeZone: tz } : { dateStyle: "medium", timeZone: tz });
64 formats.set(key, f);
65 }
66 return f;
67}
68
69/**
70 * A moment for a page: "Oct 6, 2026, 12:27 AM" and "PDT" (shown apart, the
71 * zone quieter), or just the day. `utc` is the same moment in UTC, for the
72 * hover title.
73 */
74export function when(at: Date, tz: string, time: boolean): { text: string; zone: string | null; utc: string } {
75 const zone = validZone(tz) ? tz : "UTC";
76 return {
77 text: format(zone, time).format(at),
78 zone: time ? zoneAbbr(at, zone) : null,
79 utc: `${format("UTC", true).format(at)} UTC`,
80 };
81}
82
83/** Minutes the zone is ahead of UTC at that moment. */
84function offsetMinutes(ms: number, tz: string): number {
85 const p = Object.fromEntries(
86 new Intl.DateTimeFormat("en-US", { timeZone: tz, year: "numeric", month: "numeric", day: "numeric", hour: "numeric", minute: "numeric", second: "numeric", hourCycle: "h23" })
87 .formatToParts(new Date(ms))
88 .map((x) => [x.type, Number(x.value)]),
89 );
90 const wall = Date.UTC(p.year!, p.month! - 1, p.day!, p.hour!, p.minute!, p.second!);
91 return Math.round((wall - Math.floor(ms / 1000) * 1000) / 60_000);
92}
93
94/**
95 * A `datetime-local` value (`2026-10-05T14:00`), read as a wall-clock time
96 * in `tz`; an ISO time with its own offset is taken as it is. UTC ISO, or
97 * null when it is not a time.
98 */
99export function fromLocalInput(raw: string, tz = "UTC"): string | null {
100 const value = raw.trim();
101 if (!value) return null;
102 if (/Z$|[+-]\d\d:\d\d$/.test(value)) return Number.isNaN(Date.parse(value)) ? null : new Date(value).toISOString();
103 const m = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})(?::(\d{2}))?$/.exec(value);
104 if (!m) return null;
105 const wall = Date.UTC(Number(m[1]), Number(m[2]) - 1, Number(m[3]), Number(m[4]), Number(m[5]), Number(m[6] ?? 0));
106 if (Number.isNaN(wall)) return null;
107 const zone = validZone(tz) ? tz : "UTC";
108 // The offset at the guess, then again at the answer: right across a change of clocks.
109 let at = wall - offsetMinutes(wall, zone) * 60_000;
110 at = wall - offsetMinutes(at, zone) * 60_000;
111 return new Date(at).toISOString();
112}
113
114/** A moment as a `datetime-local` value in `tz`: `2026-10-05T07:00`. */
115export function toLocalInput(at: Date | string, tz = "UTC"): string {
116 const ms = new Date(at).getTime();
117 const zone = validZone(tz) ? tz : "UTC";
118 return new Date(ms + offsetMinutes(ms, zone) * 60_000).toISOString().slice(0, 16);
119}

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