RelativeTime
relative-timeFormats timestamps as continuously updated human-readable relative time.
Usage
Basic usage
If the timestamp is passed, it will be rendered as "3 minutes ago". If base is omitted, it will be refreshed in real time. Hover to see the absolute time.
tsx
<RelativeTime value={publishedAt} />Fixed datum
Pass base with fixed reference to "now", SSR/list unified reference, not real-time tick.
tsx
<>
<RelativeTime value={ago(45)} base={now} />
<RelativeTime value={ago(5 * 3600)} base={now} />
<RelativeTime value={ago(8 * 86400)} base={now} />
</>Future time
The target time is later than the base time and is rendered as "10 minutes later/tomorrow".
tsx
<>
<RelativeTime value={after(10 * 60)} base={now} />
<RelativeTime value={after(86400 + 60)} base={now} />
</>English locale
locale="en" outputs "5m ago / in 5m" compact English format.
tsx
<RelativeTime value={publishedAt} locale="en" />When to use
Use RelativeTime for changing labels such as "3 minutes ago", "yesterday", or "in 2 months". Use formatRelative and formatAbsolute directly when only a string is needed.
Import
ts
import { RelativeTime, formatRelative, formatAbsolute } from "@hulianui/ui"Props
| Name | Type | Default | Description |
|---|---|---|---|
| value* | Date | string | number | - | Date, ISO string, or millisecond timestamp to display. |
| base | Date | string | number | - | Fixed reference time; supplying it disables live ticks for deterministic SSR, tests, or lists. |
| updateInterval | number | 60000 | Live refresh interval in milliseconds; zero disables updates. |
| locale | "zh" | "en" | "zh" | Output language. |
| withTitle | boolean | true | Shows absolute time in the hover title. |
| className | string | - | Custom class name. |
Pitfalls
- Without
base, every instance uses a live client timer. Set a shared fixed base for deterministic SSR, tests, or a synchronized list. - Without
basethe first frame renders the absolute time (YYYY-MM-DD HH:mm) and swaps to the relative string after mount. This is deliberate: reading the system clock during render bakes the build moment into SSR or static-export output, so a page visited months later still claims "1 minute ago", whereas the absolute time depends only onvalueand stays true at any moment. The other candidate, usingvalueas its own reference so the first frame reads "just now", was rejected because crawlers and readers without JavaScript would take that falsehood at face value. The swap happens before the browser paints (layout effect), so no visible jump; passbaseif you need the relative string in the first frame. - The
suppressHydrationWarningon<time>now only covers a `value` that differs between server and client (such asvalue={new Date()}, where thedateTimeattribute is already two different values). The component itself no longer introduces a mismatch, so do not read it as permission to pass an unstablevalue. - Large lists create one 60-second timer per instance. Set
updateInterval={0}or passbaseto reduce rerenders. - The default
locale="zh"uses runtime tokens"\u521a\u521a"("just now"),"\u79d2"("second"),"\u5206\u949f"("minute"),"\u5c0f\u65f6"("hour"),"\u5929"("day"),"\u4e2a\u6708"("month"),"\u5e74"("year"),"\u524d"("ago"),"\u540e"("later"),"\u6628\u5929"("yesterday"), and"\u660e\u5929"("tomorrow"). Setlocale="en"for English UI.
Related
Sparkline · ImageViewer · LiveProductCard · DiffStat · ScoreRing · Badge
Playground
<RelativeTime value={publishedAt} />