patternjavascriptTip
Intl.RelativeTimeFormat for human-readable relative time
Viewed 0 times
Node.js 12+, ES2020
RelativeTimeFormatrelative timetime agolocale pluralIntl
browsernode
Problem
Displaying 'X minutes ago' or 'in 3 days' requires locale-specific pluralisation rules that differ across languages. Most hand-rolled implementations only handle English.
Solution
Use Intl.RelativeTimeFormat for locale-aware relative time formatting.
const rtf = new Intl.RelativeTimeFormat('en', { numeric: 'auto' });
rtf.format(-1, 'day'); // 'yesterday'
rtf.format(-3, 'hour'); // '3 hours ago'
rtf.format(2, 'week'); // 'in 2 weeks'
new Intl.RelativeTimeFormat('fr').format(-2, 'day'); // 'il y a 2 jours'
const rtf = new Intl.RelativeTimeFormat('en', { numeric: 'auto' });
rtf.format(-1, 'day'); // 'yesterday'
rtf.format(-3, 'hour'); // '3 hours ago'
rtf.format(2, 'week'); // 'in 2 weeks'
new Intl.RelativeTimeFormat('fr').format(-2, 'day'); // 'il y a 2 jours'
Why
Pluralisation rules vary widely across languages. Intl.RelativeTimeFormat uses CLDR rules for 50+ locales correctly, eliminating the need for a library.
Gotchas
- You must compute the value and unit yourself — the API does not parse timestamps
- numeric: 'auto' enables 'yesterday'/'tomorrow'; numeric: 'always' gives '-1 day'
- Valid units: second, minute, hour, day, week, month, quarter, year
- Available in Node.js 12+ and all modern browsers
Code Snippets
timeAgo helper using Intl.RelativeTimeFormat
function timeAgo(date, locale = 'en') {
const rtf = new Intl.RelativeTimeFormat(locale, { numeric: 'auto' });
const diffMs = date.getTime() - Date.now();
const diffSecs = Math.round(diffMs / 1000);
const diffMins = Math.round(diffSecs / 60);
const diffHours = Math.round(diffMins / 60);
const diffDays = Math.round(diffHours / 24);
if (Math.abs(diffSecs) < 60) return rtf.format(diffSecs, 'second');
if (Math.abs(diffMins) < 60) return rtf.format(diffMins, 'minute');
if (Math.abs(diffHours) < 24) return rtf.format(diffHours, 'hour');
return rtf.format(diffDays, 'day');
}Revisions (0)
No revisions yet.