clone

a personal forge on plain git: static pages, stacked-diff reviews, signed local ci, repo sites and releases

main
forge / test / scenarios / times-relative.sh
times-relative.sh 2.3K
1# ui.ts says each <time> relative to now: compact in a column ("now", "5m",2# "40m", "5h", "1d", "3w", then "Aug 24", or "2025-03-01" from an earlier3# year), as a sentence where it has data-ago ("just now", "5m ago", then4# "Mar 1, 2025"), with the full local date and time as its title. Run here5# in node against a stand-in page, at a fixed now, in UTC and en-US.6. "$(dirname "$0")/../lib.sh"7got=$(cd "$T_HOME" && TZ=UTC LC_ALL=en_US.UTF-8 node -e '8 const fs = require("node:fs"), vm = require("node:vm"), { stripTypeScriptTypes } = require("node:module");9 const now = Date.parse("2026-10-18T12:00:00Z");10 const ages = [["10s", 10], ["in 2m", -120], ["5m", 300], ["40m", 2400], ["5h", 5 * 3600], ["26h", 26 * 3600], ["6d", 6 * 86400], ["21d", 21 * 86400]];11 const cases = [...ages.map(([n, s]) => [n, new Date(now - s * 1000).toISOString()]), ["this year", "2026-08-24T09:00:00Z"], ["last year", "2025-03-01T12:00:00Z"]];12 const els = [];13 for (const [name, iso] of cases) for (const ago of [false, true]) els.push({ name: name + (ago ? ", in a sentence" : ""), dateTime: iso, textContent: "", title: "", hasAttribute: (a) => ago && a === "data-ago" });14 const noop = () => {};15 const document = { addEventListener: noop, querySelector: () => null, querySelectorAll: (s) => (s === "time[datetime]" ? els : []), body: { classList: { toggle: noop } } };16 const page = vm.createContext({ document, window: { addEventListener: noop }, localStorage: { getItem: () => null, setItem: noop }, matchMedia: () => ({ matches: false }), location: { hash: "" }, setInterval: noop, setTimeout: noop, navigator: {} });17 vm.runInContext("Date.now = () => " + now, page);18 vm.runInContext(stripTypeScriptTypes(fs.readFileSync("site/assets/ui.ts", "utf8")), page);19 for (const e of els) console.log(e.name + ": " + e.textContent);20 console.log("title: " + els.find((e) => e.dateTime.startsWith("2025")).title);21')22eq "$got" "10s: now2310s, in a sentence: just now24in 2m: now25in 2m, in a sentence: just now265m: 5m275m, in a sentence: 5m ago2840m: 40m2940m, in a sentence: 40m ago305h: 5h315h, in a sentence: 5h ago3226h: 1d3326h, in a sentence: 1d ago346d: 6d356d, in a sentence: 6d ago3621d: 3w3721d, in a sentence: 3w ago38this year: Aug 2439this year, in a sentence: Aug 2440last year: 2025-03-0141last year, in a sentence: Mar 1, 202542title: Mar 1, 2025, 12:00 PM UTC"