Dates and numbers Optional
Show relative times with the exact time beside them
Put each relative time, such as "5 minutes ago", in a <time> element with the exact time in datetime. Show the exact time on hover and focus.
How to do it
Format the words with Intl.RelativeTimeFormat or a library such as Babel, never by joining strings, so plurals come out right. Switch to an exact date after 7 days. Refresh relative times once a minute while the tab is visible. Never use relative times in exports, emails or audit logs.
Example
const UNITS: [Intl.RelativeTimeFormatUnit, number][] = [['day', 86_400], ['hour', 3_600], ['minute', 60], ['second', 1]];
export function relativeTime(isoUtc: string, locale: string, now = Date.now()): string {
const seconds = Math.round((Date.parse(isoUtc) - now) / 1000);
const [unit, size] = UNITS.find(([, size]) => Math.abs(seconds) >= size) ?? UNITS.at(-1)!;
return new Intl.RelativeTimeFormat(locale, { numeric: 'auto' }).format(Math.round(seconds / size), unit);
}
from datetime import datetime, timezone
from babel.dates import format_timedelta
def relative_time(moment: datetime, locale: str) -> str:
return format_timedelta(moment - datetime.now(timezone.utc), add_direction=True, locale=locale)
<time datetime="2026-11-02T09:15:04Z" title="2 Nov 2026, 10:15 CET">5 minutes ago</time>
How to check
A component test renders a time from 90 seconds ago. It shows "2 minutes ago" or "1 minute ago", and the <time> element carries the full ISO time.
For agents: if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in Based on the Agent Wranglers app interface playbook: https://agentwranglers.se/playbook/app-ui/dates-and-numbers/relative-times.