Relative Time strings

Handling dates in Javascript has always been considered a tricky task, which led to the rise of date-handling libraries such as Moment.js. One of the most common uses of Moment.js is converting dates to relative time, such as “a few seconds ago” or “a month from now”.

Now this can be partially achieved natively in browsers using Intl.RelativeTimeFormat. It takes an amount of time as a number, and formats it as a relative time in the user’s language. This offers a great space saving as you will no longer need to include extra language files on your site to handle all these cases.

Usage

To use the formatter, we create an instance, and then can call the format function as needed. The formatter accepts two optional arguments. The first is the locale - if not specified, it defaults to the browser’s locale. The second is an options object which allows for some customisation of the output string.

The format function takes two arguments. The first is a numeric value, and the second is the time unit it refers to. Possible options for the time unit are second, minute, hour, day, week, month, quarter and year. These units can also be written in the plural (such as seconds). There is no difference in operation, so singular or plural is down to personal preference.

Below is the most basic use case, formatting using all the defaults.

const formatter = new Intl.RelativeTimeFormat();

formatter.format(-1, 'day');  // "1 day ago"
formatter.format(1, 'day');   // "in 1 day"
formatter.format(1, 'month'); // "in 1 month"
formatter.format(2, 'year');  // "in 2 years"

Some of the results above sound a bit unnatural. For example, it would be better if “1 day ago” instead said “yesterday”. This can be changed by setting the numeric option to auto.

const locale = navigator.language;
const options = {
  numeric: 'auto' // default is 'always'
};
const formatter = new Intl.RelativeTimeFormat(locale, options);

formatter.format(-1, 'day');  // "yesterday"
formatter.format(1, 'day');   // "tomorrow"
formatter.format(1, 'month'); // "next month"
formatter.format(2, 'year');  // "in 2 years"

The real power of RelativeTimeFormat is that it supports many languages. For example, we can format in Spanish simply by passing in es-ES as the locale. For users whose browser is already set to Spanish, this would be the automatically chosen language. So, you get multilingual support without needing to add any libraries.

const locale = 'es-ES';
const options = {
  numeric: 'auto' // default is 'always'
};
const formatter = new Intl.RelativeTimeFormat(locale, options);

formatter.format(-1, 'day');  // "ayer"
formatter.format(1, 'day');   // "mañana"
formatter.format(1, 'month'); // "el próximo mes"
formatter.format(2, 'year');  // "dentro de 2 años"

Using with dates

The RelativeTimeFormat API is only concerned with the formatting of strings. This means you will still need to do date calculations yourself.

const MS_IN_DAY = 86400000;
const now = Date.now();
const futureDate = now + (MS_IN_DAY * 3);
const msDiff = futureDate - now;
const dayDiff = Math.ceil(msDiff / MS_IN_DAY);

const formatter = new Intl.RelativeTimeFormat();
formatter.format(dayDiff, 'day'); // "in 3 days"

Support

Chrome supports RelativeTimeFormat since Chrome 71. It will be supported in Firefox 65, to be released on January 29th, 2019. Or, as RelativeTimeFormat itself says: RelativeTimeFormat not supported in this browser. It is not currently supported in Safari or Edge.

Other recent posts: