Skip to content
Timer

useTimeAgo

Reactive human-readable time-ago string that auto-updates (powered by date-fns)

Returns a ReadonlyObservable<string> with a human-readable relative time string (e.g. “5 minutes ago”, “in 2 days”) that auto-updates at a configurable interval.

Formatting is delegated to date-fns/formatDistance, enabling full i18n locale support.

Also exports formatTimeAgo as a standalone pure function for one-off formatting.

Time Ago
just now

Drag the slider to shift time offset.

0ms

import {
import useTimeAgo
useTimeAgo
} from "@usels/web";
function
function Component(): JSX.Element
Component
() {
const
const timeAgo: any
timeAgo
=
import useTimeAgo
useTimeAgo
(new
any
Date
("2024-01-01"));
return <
JSX.IntrinsicElements.div: DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>
div
>{
const timeAgo: any
timeAgo
.
any
get
()}</
JSX.IntrinsicElements.div: DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>
div
>;
// timeAgo.get() → "about 3 months ago"
}
import { observable, useTimeAgo } from "@usels/web";
function Component() {
const time$ = observable(new Date());
const timeAgo = useTimeAgo(time$);
// time$.set(new Date("2020-01-01")) → "about 4 years ago"
}
import { useTimeAgo } from "@usels/web";
function Component() {
const { timeAgo$, isActive$, pause, resume } = useTimeAgo(new Date(), {
controls: true,
});
}
import { useTimeAgo } from "@usels/web";
function Component() {
// Update every 10 seconds instead of every 30
const timeAgo = useTimeAgo(new Date(), { updateInterval: 10_000 });
}

When showSecond: true, times under 1 minute are shown in detail (maps to date-fns includeSeconds). When showSecond: false (default), times within 45 s show "just now".

import { useTimeAgo } from "@usels/web";
function Component() {
const timeAgo = useTimeAgo(new Date(Date.now() - 30_000), { showSecond: true });
// → "half a minute ago"
}
import { useTimeAgo } from "@usels/web";
function Component() {
const timeAgo = useTimeAgo(new Date("2020-01-01"), {
max: "month",
fullDateFormatter: (d) => d.toLocaleDateString(),
});
// dates older than ~11 months → formatted date string
}

Pass any date-fns locale to the locale option.

import { useTimeAgo } from "@usels/web";
import { ko } from "date-fns/locale";
function Component() {
const timeAgo = useTimeAgo(new Date(), { locale: ko });
// → "방금 전"
}
import { useTimeAgo } from "@usels/web";
import { ja } from "date-fns/locale";
const timeAgo = useTimeAgo(new Date("2024-01-01"), { locale: ja });
// → "約1年前"

You can also use formatTimeAgo with a locale:

import { formatTimeAgo } from "@usels/web";
import { fr } from "date-fns/locale";
const str = formatTimeAgo(new Date("2024-01-01"), { locale: fr }, new Date("2024-06-01"));
// → "il y a environ 5 mois"
import { formatTimeAgo } from "@usels/web";
const str = formatTimeAgo(new Date("2024-01-01"), {}, new Date("2024-06-01"));
// → "about 5 months ago"
ParameterTypeDescription
timeMaybeObservable<string | number | Date>-
optionsTimeAgoOptions & { controls: true; }-
OptionTypeDefaultDescription
updateIntervalnumber30_000Update interval in ms — mount-time-only
localeLocale-date-fns Locale for i18n — mount-time-only
maxnumber | UseTimeAgoUnitNamesDefault-Max diff before fullDateFormatter is used — reactive
fullDateFormatter((date: Date) => string)-Formatter for dates exceeding max — function hint
showSecondbooleanfalseShow detailed seconds for recent times. When false, times within 45s show “just now”.
controlsboolean-Expose pause/resume controls — mount-time-only

Pausable & { timeAgo$: ObservablePrimitive<string>; }

NameTypeDescription
isActive$ReadonlyObservable<boolean>-
pauseFn-
resumeFn-
timeAgo$ObservablePrimitive<string>-

View on GitHub