Overview

anywhen is a ~800b gzip date formatting library built entirely on the native Intl browser API. No locale files, no plugins, no config — just three functions that cover the most common date formatting needs.

The browser already knows how to format dates in 200+ languages. anywhen just makes that API pleasant to use.

import { anydate, anywhen, anyago, anywhere } from 'anywhen'

anydate(date, 'en')   // "Feb 5, 2016"
anywhen(date, 'en')   // "yesterday, 2:35 PM"
anyago(date,  'en')   // "3 hours ago"

Install

current stable:v0.1.4→ all releases
npm install anywhen
# or
pnpm add anywhen
# or
yarn add anywhen

anydate()

Always returns an absolute date string. Pass any Intl.DateTimeFormat options to control the format.

anydate(input, locale, options?)

anydate(date, 'en')
// "Feb 5, 2016"

anydate(date, 'en', { weekday: 'long', month: 'long', day: 'numeric', year: 'numeric' })
// "Friday, February 5, 2016"

anydate(date, 'en', { hour: '2-digit', minute: '2-digit' })
// "2:35 PM"

anydate(date, 'en', { month: 'long', year: 'numeric' })
// "February 2016"
inputDate | number | string

The date to format. Accepts a Date object, unix timestamp in ms, or ISO string.

localestring

Any valid BCP 47 locale tag — 'en', 'en-US', 'zh-TW', 'pt-BR'.

optionsIntl.DateTimeFormatOptionsdefault: { day, month, year }

Any options accepted by Intl.DateTimeFormat. Defaults to a short date.

anywhen()

Smart context picker. Chooses the most readable format based on distance from now — covers past and future.

anywhen(input, locale, time?)

anywhen(date, 'en')         // "just now"
anywhen(date, 'en')         // "10 minutes ago"
anywhen(date, 'en')         // "today, 2:35 PM"
anywhen(date, 'en')         // "yesterday, 9:00 AM"
anywhen(date, 'en')         // "Wednesday, 11:20 AM"
anywhen(date, 'en')         // "Feb 5, 2016"
anywhen(date, 'en')         // "in 2 weeks"

anywhen(date, 'en', false)  // "yesterday"  — no clock

switching logic

< 45s→ "just now"
< 1 hour→ "10 minutes ago"
future > 1h→ "in 2 weeks"
same day→ "today, 14:35"
yesterday→ "yesterday, 09:00"
< 7 days→ "Wednesday, 11:20"
older→ "Feb 5, 2016"
inputDate | number | string

The date to format.

localestring

Any valid BCP 47 locale tag.

timebooleandefault: true

Whether to include clock time in today/yesterday/weekday output. Pass false to omit.

anyago()

Always relative. Past and future. Never switches to an absolute date.

anyago(input, locale, numeric?)

anyago(date, 'en')          // "3 hours ago"
anyago(date, 'en')          // "yesterday"
anyago(date, 'en')          // "in 2 weeks"

anyago(date, 'en', true)    // "1 day ago"   — numeric mode, no "yesterday"
anyago(date, 'en', true)    // "1 week ago"  — numeric mode, no "last week"
inputDate | number | string

The date to format.

localestring

Any valid BCP 47 locale tag.

numericbooleandefault: false

Force numeric output — disables auto-phrases like 'yesterday' or 'last week'.

anywhere()

Returns a locale-bound instance — useful when formatting many dates in the same locale.

import { anywhere } from 'anywhen'

const t = anywhere('en')

t.anydate(date)                                         // "Feb 5, 2016"
t.anywhen(date)                                         // "yesterday, 2:35 PM"
t.anyago(date)                                          // "3 hours ago"
t.anydate(date, { weekday: 'long', month: 'long',
                  day: 'numeric', year: 'numeric' })    // "Friday, February 5, 2016"

Input types

All functions accept three input formats interchangeably.

// Date object
anydate(new Date(), 'en')

// Unix timestamp (milliseconds)
anydate(Date.now(), 'en')
anydate(1704499200000, 'en')

// ISO string
anydate('2016-02-05T14:00:00Z', 'en')
anydate('2016-02-05', 'en')

Locales

All output is in English in the examples above. Here's the same calls in a few other languages — no extra setup required.

anydate(date, 'de')   // "5. Feb. 2016"
anydate(date, 'ja')   // "2016年2月5日"
anydate(date, 'ar')   // "٥ فبراير ٢٠١٦"
anydate(date, 'ru')   // "5 февр. 2016 г."
anydate(date, 'fr')   // "5 févr. 2016"
anydate(date, 'zh')   // "2016年2月5日"

anyago(date, 'de')    // "vor 3 Stunden"
anyago(date, 'fr')    // "il y a 3 heures"
anyago(date, 'tr')    // "3 saat önce"
anyago(date, 'ru')    // "3 часа назад"
anyago(date, 'ar')    // "منذ 3 ساعات"

anywhen(date, 'de')   // "gestern, 14:35"
anywhen(date, 'ru')   // "вчера, 14:35"
anywhen(date, 'fr')   // "hier, 14:35"

Pass any valid BCP 47 language tag — including regional variants like en-GB, zh-TW, or pt-BR.

Compatibility

anywhen uses Intl.RelativeTimeFormat and Intl.DateTimeFormat — both widely supported.

Node.js13+full ICU included by default
Chrome71+
Firefox65+
Safari14+
Edge79+
Vercel Edge Runtime
Cloudflare Workers
Deno

Limitations

A few things worth knowing before you ship:

Output depends on the runtime's Intl data

anywhen delegates all formatting to native Intl. Exact output — punctuation, spacing, abbreviated month names — may vary between Node versions, browsers, and OSes. Don't hardcode expected strings in tests; use pattern matching instead.

No custom format strings

anydate() accepts Intl.DateTimeFormat options, so you control the pieces. But if you need 'DD/MM/YYYY' with literal slashes — use a formatting library with explicit pattern strings instead.

anywhen cutoff is fixed at 7 days

The switch from weekday ('Wednesday, 11:20') to absolute date happens at 7 days and is not configurable. Need a custom cutoff? Use anyago() and anydate() directly.

Node.js < 13

Older Node versions shipped with small-icu — only the 'en' locale was guaranteed. Node 13+ includes full ICU. On older versions, install the full-icu package separately.