components/time/time.react.tsx
47 lines and 7 functions in DrDustinEdwards/capsomer, at commit d3966cc on 2026-10-24. This file on GitHub.
Functions
| Function | Lines | Complexity | Covered | CRAP | Mutation |
|---|---|---|---|---|---|
| toMs | 14 to 16 | 3 | No data: no coverage report in this map | No data: no coverage report in this map | No data: mutation testing has not run on this repo yet |
| useClock | 19 to 28 | 1 | No data: no coverage report in this map | No data: no coverage report in this map | No data: mutation testing has not run on this repo yet |
| <anonymous:20> | 20 to 20 | 1 | No data: no coverage report in this map | No data: no coverage report in this map | No data: mutation testing has not run on this repo yet |
| <anonymous:21> | 21 to 26 | 2 | No data: no coverage report in this map | No data: no coverage report in this map | No data: mutation testing has not run on this repo yet |
| <anonymous:24> | 24 to 24 | 1 | No data: no coverage report in this map | No data: no coverage report in this map | No data: mutation testing has not run on this repo yet |
| <anonymous:25> | 25 to 25 | 1 | No data: no coverage report in this map | No data: no coverage report in this map | No data: mutation testing has not run on this repo yet |
| Time | 30 to 51 | 10 | No data: no coverage report in this map | No data: no coverage report in this map | No data: mutation testing has not run on this repo yet |
Imports
It imports components/time/time.ts. Imported by components/admin-shell/admin-shell.react.tsx, components/flag-list/flag-list.react.tsx, components/history-list/history-list.react.tsx, components/mentions-list/mentions-list.react.tsx, components/posts-list/posts-list.react.tsx, components/publish-gate/publish-gate.react.tsx.
Source
import { useEffect, useState } from "react";
import { REFRESH_MS, exactParts, parse, text, type TimeFormat } from "./time.ts";
export interface TimeProps {
// Milliseconds, a Date, or a server timestamp (a zoneless one is read as UTC).
at: number | Date | string;
// Relative in rows; exact (viewer's zone and UTC) in a detail.
format?: TimeFormat;
// A fixed "now", for a report or a test, or the server's now when its clock and the
// browser's disagree (serverNow). Without it the text refreshes every 30 s.
now?: number;
}
function toMs(at: TimeProps["at"]): number {
return typeof at === "number" ? at : at instanceof Date ? at.getTime() : parse(at);
}
// The clock, ticking every 30 seconds while a relative time is shown.
function useClock(enabled: boolean): number {
const [now, setNow] = useState(() => Date.now());
useEffect(() => {
if (!enabled) return;
setNow(Date.now());
const t = window.setInterval(() => setNow(Date.now()), REFRESH_MS);
return () => window.clearInterval(t);
}, [enabled]);
return now;
}
export function Time({ at, format = "relative", now }: TimeProps) {
const t = toMs(at);
const clock = useClock(format === "relative" && now === undefined);
const iso = Number.isFinite(t) ? new Date(t).toISOString() : undefined;
// A time that cannot be read is said in words and is not a <time> (it has no datetime).
if (!iso) return <span className="cap-time">{text(t, format)}</span>;
// The server's words can differ from the browser's (its clock, its zone); the browser's
// win without a warning.
const p = format === "exact" ? exactParts(t) : null;
return (
<time className="cap-time" dateTime={iso} data-format={format === "exact" ? "exact" : undefined} suppressHydrationWarning>
{p ? (
<>
{p.utc ? `${p.local} ` : p.local}
{p.utc ? <span className="cap-time-utc">{p.utc}</span> : null}
</>
) : (
text(t, format, now ?? clock)
)}
</time>
);
}