snippetjavascriptTip
Formatting relative time in JavaScript
Viewed 0 times
formattingjavascripttimerelative
Problem
<baseline-support featureId="intl-relative-time-format">
</baseline-support>
I've recently stumbled upon the
The first step in this process is to create a new
The locale is a string that specifies the locale (language & region or just language) to use for formatting. The options object accepts a
</baseline-support>
I've recently stumbled upon the
Intl.RelativeTimeFormat API, and was surprised how simple it makes solving an age-old problem: how to format relative time. This is a common task in web development, and while there are many libraries that do this, it's nice to see that JavaScript has a built-in way to do it. The browser support is great, too, and has been for a while now. So, let's take a look at how to use it!The first step in this process is to create a new
Intl.RelativeTimeFormat object. This object takes two arguments: the locale and an options object.The locale is a string that specifies the locale (language & region or just language) to use for formatting. The options object accepts a
numeric property, which can be either always or auto and a style property, which can be either long, narrow, or short.Solution
const formatter = new Intl.RelativeTimeFormat('en', {
numeric: 'auto',
style: 'long',
});I've recently stumbled upon the
Intl.RelativeTimeFormat API, and was surprised how simple it makes solving an age-old problem: how to format relative time. This is a common task in web development, and while there are many libraries that do this, it's nice to see that JavaScript has a built-in way to do it. The browser support is great, too, and has been for a while now. So, let's take a look at how to use it!The first step in this process is to create a new
Intl.RelativeTimeFormat object. This object takes two arguments: the locale and an options object.The locale is a string that specifies the locale (language & region or just language) to use for formatting. The options object accepts a
numeric property, which can be either always or auto and a style property, which can be either long, narrow, or short.| Options | Sample output |
| --- | --- |
|
{ numeric: 'always', style: 'long' } | 1 day ago |Code Snippets
const formatter = new Intl.RelativeTimeFormat('en', {
numeric: 'auto',
style: 'long',
});// Assuming a formatter has been created
formatter.format(-1, 'day'); // 'yesterday'
formatter.format(0, 'year'); // 'this year'
formatter.format(1, 'month'); // 'in 1 month'
formatter.format(2, 'week'); // 'in 2 weeks'const dateDifferenceInYears = (a, b) => dateDifferenceInMonths(a, b) / 12;
const dateDifferenceInMonths = (a, b) =>
(b.getFullYear() - a.getFullYear()) * 12 + b.getMonth() - a.getMonth();
const dateDifferenceInWeeks = (a, b) => (b - a) / 604_800_000;
const dateDifferenceInDays = (a, b) => (b - a) / 86_400_000;
const dateDifferenceInHours = (a, b) => (b - a) / 3_600_000;
const dateDifferenceInMinutes = (a, b) => (b - a) / 60_000;
const dateDifferenceInSeconds = (a, b) => (b - a) / 1_000;
const formatDifference = (difference, unit) => {
const formatter = new Intl.RelativeTimeFormat('en', {
numeric: 'auto',
style: 'long',
});
// Strip the decimal part of the number
return formatter.format(Number.parseInt(difference, 10), unit);
}
const formatDateDifference = date => {
// Use the current date as the reference point for the diff.
const now = new Date();
// Calculate the difference in years, months, weeks and days
const diffInYears = dateDifferenceInYears(now, date);
const diffInMonths = dateDifferenceInMonths(now, date);
const diffInWeeks = dateDifferenceInWeeks(now, date);
const diffInDays = dateDifferenceInDays(now, date);
// Calculate absolute values of the differences
const days = Math.abs(diffInDays);
const years = Math.abs(diffInYears);
// < 1 day: format as hours, minutes or seconds
// 1-14 days: format as days
// 2 weeks - 2 years: format as months, except if exactly 1 or 2 years
// 2+ years: format as years
if (days >= 1)
if (days <= 14)
return formatDifference(Math.round(diffInDays), 'day');
else if (days <= 30)
return formatDifference(diffInWeeks, 'week');
else if (years <= 2 && diffInMonths % 12 !== 0)
return formatDifference(diffInMonths, 'month');
else
return formatDifference(diffInYears, 'year');
// Calculate the difference in hours, minutes and seconds
const diffInHours = dateDifferenceInHours(now, date);
const diffInMinutes = dateDifferenceInMinutes(now, date);
const diffInSeconds = dateDifferenceInSeconds(now, date);
const hours = Math.abs(diffInHours);
const minutes = Math.abs(diffInMinutes);
// 12+ hours: format as days
// 1-12 hours: format as hours
// < 1 hour: format as minutes
// < 1 minutes: format as seconds
if (Math.floor(hours) !== 0)
if (hours >= 12)
return formatDifference(Math.sign(diffInHours) * 1, 'day');
else
return formatDifference(diffInHours, 'hour');
else if (Math.floor(minutes) !== 0)
return formatDifference(diffInMinutes, 'minute');
else if (diffInSeconds % 60 !== 0)
return formatDifference(diffInSeconds, 'second');
};
// Assuming today's date is 2025-03-31 11:00:00
formatDateDifference(new Date('2025-03-30')); // 'yesterday'
formatDateDifference(new Date('2025-04-01')); // 'tomorrow'
formatDateDifference(new Date('2025-04-02')); // 'in 2 days'
formatDateDifference(new Date('2025-04-15')); // 'in 2 weeks'
formatDateDifferContext
From 30-seconds-of-code: relative-time-formatting
Revisions (0)
No revisions yet.