Skip to content

fromNow()

Returns a human-readable relative-time string such as "3 hours ago" or "in 2 days", built on the native Intl.RelativeTimeFormat — no manual thresholds, fully localized.

Signature

ts
function fromNow(
  temporalObj: RelativeTemporalType,
  reference?: Temporal.Instant,
  locale?: string
): string

type RelativeTemporalType =
  | Temporal.PlainDate
  | Temporal.PlainDateTime
  | Temporal.ZonedDateTime
  | Temporal.Instant

Temporal.PlainTime is not supported — without a date there is no way to tell whether a time is past or future.

Parameters

ParameterTypeDefaultDescription
temporalObjRelativeTemporalTyperequiredThe target time to describe.
referenceTemporal.InstantTemporal.Now.*The "now" to measure against. Pass an explicit value for deterministic output.
localestringruntime defaultBCP 47 tag controlling the language of the result.

When reference is omitted, moment-less reads the current time internally, which makes output non-deterministic — always pass an explicit reference in tests.

Unit selection

The output unit is chosen from the absolute difference, then rendered with Intl.RelativeTimeFormat's numeric: 'auto' mode (which produces words like "yesterday" and "last week" where a locale defines them):

DifferenceUnitExample output
< 60 secondsseconds"30 seconds ago", "now"
< 60 minutesminutes"3 minutes ago", "1 minute ago"
< 24 hourshours"3 hours ago", "1 hour ago"
< 7 daysdays"2 days ago", "yesterday", "tomorrow"
< 30 daysweeks"3 weeks ago", "last week", "next week"
< 365 daysmonths"3 months ago", "last month"
≥ 365 daysyears"2 years ago", "last year"

Months and years use approximate boundaries (30 and 365 days). Values are rounded, so an exact ±1 boundary renders via the auto words ("yesterday", "last week", …).

PlainDate is compared by calendar day. A PlainDate has no clock, so moment-less measures the whole-day difference against the reference date instead of folding it through a UTC-midnight instant. That keeps fromNow(today) reliably "today" and fromNow(tomorrow) reliably "tomorrow", independent of the time of day or time zone.

Examples

Past — by unit

ts
import { fromNow } from 'moment-less'

const now = Temporal.Instant.from('2026-04-09T14:00:00Z')

fromNow(now.subtract({ seconds: 30 }), now) // → "30 seconds ago"
fromNow(now.subtract({ minutes: 1 }), now)  // → "1 minute ago"
fromNow(now.subtract({ hours: 3 }), now)    // → "3 hours ago"
fromNow(now.subtract({ hours: 24 }), now)   // → "yesterday"
fromNow(now.subtract({ hours: 24 * 7 }), now)   // → "last week"
fromNow(now.subtract({ hours: 24 * 30 }), now)  // → "last month"
fromNow(now.subtract({ hours: 24 * 365 }), now) // → "last year"

Future

ts
import { fromNow } from 'moment-less'

const now = Temporal.Instant.from('2026-04-09T14:00:00Z')

fromNow(now.add({ minutes: 5 }), now)    // → "in 5 minutes"
fromNow(now.add({ hours: 2 }), now)      // → "in 2 hours"
fromNow(now.add({ hours: 24 }), now)     // → "tomorrow"
fromNow(now.add({ hours: 24 * 7 }), now) // → "next week"

PlainDate (calendar-day diffing)

ts
import { fromNow } from 'moment-less'

const ref = Temporal.Instant.from('2026-04-09T12:00:00Z') // → UTC date 2026-04-09

fromNow(Temporal.PlainDate.from('2026-04-09'), ref) // → "today"
fromNow(Temporal.PlainDate.from('2026-04-10'), ref) // → "tomorrow"
fromNow(Temporal.PlainDate.from('2026-04-08'), ref) // → "yesterday"
fromNow(Temporal.PlainDate.from('2026-04-02'), ref) // → "last week"
fromNow(Temporal.PlainDate.from('2025-04-09'), ref) // → "last year"

Deterministic reference (for tests)

ts
import { fromNow } from 'moment-less'

const posted = Temporal.Instant.from('2026-04-09T08:00:00Z')
const viewed = Temporal.Instant.from('2026-04-09T12:30:00Z')

fromNow(posted, viewed) // → "4 hours ago"  (stable regardless of when the test runs)

Locale examples

Localization is zero-cost — Intl.RelativeTimeFormat ships with the platform, so there are no locale bundles to import.

ts
import { fromNow } from 'moment-less'

const now  = Temporal.Instant.from('2026-04-09T14:00:00Z')
const past = now.subtract({ hours: 3 })

fromNow(past, now)         // → "3 hours ago"
fromNow(past, now, 'fr')   // → "il y a 3 heures"
fromNow(past, now, 'es')   // → "hace 3 horas"
fromNow(past, now, 'de')   // → "vor 3 Stunden"
fromNow(past, now, 'ja')   // → "3 時間前"
fromNow(past, now, 'ar')   // → "قبل 3 ساعات"

Supported Temporal types

TypeSupportedNotes
Temporal.PlainDateCompared by calendar day (no time-of-day).
Temporal.PlainDateTimeTreated as UTC wall-clock against the reference instant.
Temporal.ZonedDateTimeConverted to its absolute instant.
Temporal.InstantCompared directly.
Temporal.PlainTimeThrows — no date context.

Released under the MIT License.