The IntL. RelativeTimeFormat API

Modern Web applications often use phrases like “yesterday,” “42 seconds ago,” or “3 months” instead of full date and time stamps. This relative time format has become so common that several popular libraries have implemented localized formatted functions. (Examples include moment.js, Globalize and date-fns.)

One problem with implementing localized relative time formatting is that you need to provide a list of idioms or phrases (such as “yesterday” or “last quarter”) for each language. Unicode CLDR provides this data, but to use it in JavaScript, it must be provided along with it embedded in the library code. Unfortunately, this undoubtedly increases the package size of these libraries, which can affect script load time, parsing/compilation cost, and memory consumption.

The new Intl.RelativeTimeFormat API shifts this burden to the JavaScript engine, which can provide locale data and make it directly available to JavaScript developers. Intl.RelativeTimeFormat implements localized formatting of relative time without sacrificing performance.

Usage and Examples

The following example shows how to create a relative time formatter in English.

const rtf = new Intl.RelativeTimeFormat('en');

rtf.format(3.14.'second');
// → 'in 3.14 seconds'

rtf.format(- 15.'minute');
// → '15 minutes ago'

rtf.format(8.'hour');
// → 'in 8 hours'

rtf.format(2 -.'day');
// → 2 days ago

rtf.format(3.'week');
// → 'in 3 weeks'

rtf.format(- 5.'month');
// → '5 months ago'

rtf.format(2.'quarter');
// → 'in 2 quarters'

rtf.format(- 42.'year');
// → '42 years ago'
Copy the code

Note that the argument passed to the intl.relativeTimeFormat constructor must be either a BCP 47 language tag, or an array of language tags.

Here are some examples of using other languages (Simplified Chinese for Chinese) :

const rtf = new Intl.RelativeTimeFormat('zh'); / / or 'useful - Hans - CN'

rtf.format(3.14.'second');
// → '3.14 seconds later '

rtf.format(- 15.'minute');
// → '15 minutes ago '

rtf.format(8.'hour');
// → '8 hours later '

rtf.format(2 -.'day');
// → 2 days ago

rtf.format(3.'week');
// → '3 weeks later '

rtf.format(- 5.'month');
// → '5 months ago '

rtf.format(2.'quarter');
// → '2 quarters later '

rtf.format(- 42.'year');
// → '42 years ago '
Copy the code

In addition, the intl. RelativeTimeFormat constructor accepts an optional options argument that provides fine-grained control over the output. To illustrate flexibility, let’s look at more output from the default Settings:

// Create a simplified Chinese relative time format example, using the default Settings.
// In this example, we pass in the default parameters explicitly
const rtf = new Intl.RelativeTimeFormat('zh', {
 localeMatcher: 'best fit'.// Other values: 'lookup'
 style: 'long'.// Other values: 'short' or 'narrow'
 numeric: 'always'.// Other values: 'auto'
});

rtf.format(- 1.'day');
// → '1 day ago '

rtf.format(0.'day');
// → '0 days later '

rtf.format(1.'day');
// → '1 day later '

rtf.format(- 1.'week');
// → '1 week ago '

rtf.format(0.'week');
// → '0 week later '

rtf.format(1.'week');
// → '1 week later '
Copy the code

You may have noticed that the formatter above generates the string ‘1 day ago ‘instead of’ yesterday ‘and the slightly dumber ‘0 weeks later’ instead of ‘this week’. This happens because, by default, the formatter outputs numeric values.

To change this behavior, set the numeric option to’ auto’ (default is ‘always’) :

const rtf = new Intl.RelativeTimeFormat('zh', { numeric: 'auto' });

rtf.format(- 1.'day');
// → 'yesterday'

rtf.format(2 -.'day');
// → 'day before yesterday'

rtf.format(0.'day');
// → 'today'

rtf.format(1.'day');
// → 'tomorrow'

rtf.format(2.'day');
// → 'day after tomorrow'

rtf.format(- 1.'week');
// → 'last week'

rtf.format(0.'week');
// → 'this week'

rtf.format(1.'week');
// → 'next week'
Copy the code

Analogous to other Intl classes, Intl.RelativeTimeFormat has a formatToParts method in addition to the format method. Although format covers the most common use case, formatToParts can be helpful if you need access to the individual parts of the generated output:

Like the other Intl classes, intl. RelativeTimeFormat has a formatToParts method in addition to the format method. Although format covers the most common use cases, formatToParts can be helpful if you need access to various parts of the generated output:

const rtf = new Intl.RelativeTimeFormat('zh', { numeric: 'auto' });

rtf.format(- 1.'day');
// → 'yesterday'

rtf.formatToParts(- 1.'day');
// → [{type: 'literal', value: 'yesterday'}]

rtf.format(3.'week');
// → '3 weeks later '

rtf.formatToParts(3.'week');
/ / - > [
// { type: 'integer', value: '3', unit: 'week' },
// {type: 'literal', value: 'literal'}
// ]
Copy the code

For more information about the remaining options and their behavior, see API Docs in the Proposal Repository.

conclusion

RelativeTimeFormat is available by default in V8 V7.1.179 and Chrome 71. As this API becomes more widely available, you’ll find libraries such as moment.js, Globalize, date-fns, and the like remove their dependency on hard-coded CLDR databases from the code base, using native relative time formatting capabilities, This improves load-time performance, analysis and compile time performance, runtime performance, and memory usage.

A link to the

  • Intl.RelativeTimeFormat Spec Proposal
  • The ECMAScript Internationalization API