Relative Time

"3 minutes ago" that stays current, in any language, with a server fallback.

zweiundeins <sb-relative-time> time date relative intl i18n Since 2026-09-22 1.8 kB0Open in playground Edit on GitHub

Playground

Shows a moment relative to now, like "3 minutes ago" or "in 2 days", with the browser's Intl.RelativeTimeFormat. It keeps itself current (one timer for every instance on the page, each updated only when its text changes). Hovering shows the full date.

Put a server-formatted date inside it: that is what shows before the component loads, for search engines, and without JavaScript.

Examples

Live

This page was opened just now.
<div data-signals="{_loaded: Date.now()}">
  This page was opened <sb-relative-time data-attr:datetime="$_loaded" data-preserve-attr="datetime">just now</sb-relative-time>.
</div>

Past and future

datetime takes ISO 8601 or Unix time (seconds or milliseconds).

  • Launch: 21 Sep 2026
  • Next window: 15 Jan 2027
  • First light: 5 Mar 2026
<ul>
  <li>Launch: <sb-relative-time datetime="2026-09-21T09:30:00Z">21 Sep 2026</sb-relative-time></li>
  <li>Next window: <sb-relative-time datetime="2027-01-15T12:00:00Z" format="short">15 Jan 2027</sb-relative-time></li>
  <li>First light: <sb-relative-time datetime="1772668800" numeric="always">5 Mar 2026</sb-relative-time></li>
</ul>

Languages

The page's lang (or the lang attribute) picks the words.

<ul>
  <li><sb-relative-time lang="de" datetime="2026-09-21T09:30:00Z"></sb-relative-time></li>
  <li><sb-relative-time lang="fr" datetime="2026-09-21T09:30:00Z"></sb-relative-time></li>
  <li><sb-relative-time lang="ja" datetime="2026-09-21T09:30:00Z"></sb-relative-time></li>
</ul>

A date after a while

With threshold="7", anything more than a week away shows as a date.

1 Jan 2026
<sb-relative-time threshold="7" datetime="2026-01-01T00:00:00Z">1 Jan 2026</sb-relative-time>

From the server

The datetime attribute belongs to the server. When a Datastar stream re-renders it with a new moment, the text follows:

<p>Last paint <sb-relative-time datetime="2026-09-22T08:14:03Z">08:14</sb-relative-time></p>

Accessibility

It renders a <time datetime="…"> with the full date as its title, so the precise moment is available to assistive technology and on hover.

Installation

Add Datastar with Rocket and the Starbase autoloader once per page, then use the tag. The autoloader imports each component the first time its tag appears, including tags added later by a Datastar morph.

<!-- Once per page: Datastar with Rocket, and the Starbase autoloader.
     It loads every <sb-…> component the first time its tag appears. -->
<script type="importmap">
  { "imports": { "datastar": "https://cdn.jsdelivr.net/gh/starfederation/datastar@v1.0.4/bundles/datastar-rocket.js" } }
</script>
<script type="module" src="https://starbase.zweiundeins.gmbh/c/autoloader.js"></script>
<!-- Optional, no flash of undefined elements: class="sb-cloak" on <html>, and -->
<style>.sb-cloak :not(:defined) { visibility: hidden }</style>

<sb-relative-time datetime="2026-09-22T08:00:00Z" numeric="always">22 Sep 2026</sb-relative-time>

<!-- In production, pin today's catalog instead of the latest: the browser then
     refuses any file that changed. Add "integrity" to the import map above: the
     hashes from https://starbase.zweiundeins.gmbh/c/@0a1ad1bf98a4/importmap.json and Datastar's, below. -->
<!--
<script type="importmap">
  { "imports": { "datastar": "https://cdn.jsdelivr.net/gh/starfederation/datastar@v1.0.4/bundles/datastar-rocket.js" },
    "integrity": { "https://cdn.jsdelivr.net/gh/starfederation/datastar@v1.0.4/bundles/datastar-rocket.js": "sha384-vUxZojLrF1Ar3de5h7VINqhJXBgjyZS4U49pHvGa87kum6j5Xn6JRziuARNw5ELG", "…": "…from importmap.json" } }
</script>
<script type="module" src="https://starbase.zweiundeins.gmbh/c/@0a1ad1bf98a4/autoloader.js" integrity="sha384-IvSCUjEWPS+wwXunU+48x96KmyWDx/Y4LeCwCL8cWFqJ/zHmTsTOsSMrzTOcpW3D"></script>
-->

<!-- Or load just this component, pinned to this version: -->
<!-- <script type="module" src="https://starbase.zweiundeins.gmbh/c/relative-time@1e5606a7512d/relative-time.js" integrity="sha384-v7g88TrzuNuhDTMRrBfBg6fcxu9fukTNi9o+LEQSzeEMhhy9a6l2CMuzq5PuBBNI"></script> -->

Size

Each file compressed on its own, the way it is served (gzip -9, brotli -11). Datastar and Rocket are shared by every component and not counted.

FileOriginalgzipbrotli
relative-time.js 4.4 kB2.0 kB1.8 kB

API reference

Props

AttributeTypeDefaultDescription
datetimestring""The moment: ISO 8601 (2026-09-22T08:00:00Z) or Unix time (seconds or ms).
numeric"auto" | "always""auto""auto" allows words like "yesterday"; "always" says "1 day ago".
format"long" | "short" | "narrow""long"Length of the units ("3 minutes" / "3 min." / "3m").
langstring""Locale (default: the page's lang, then the browser's).
thresholdnumber0After this many days, show the date instead (0: always relative).
syncbooleantrueKeep the text current while the page is open.