Formatting Relative Time with JavaScript’s RelativeTimeFormat Constructor
Tags: webdev, javascript, tutorial, codenewbie
Published: 2020-02-06 02:12:43

**Subscribe to my email list now at http://jauyeung.net/subscribe/**

**Follow me on Twitter at https://twitter.com/AuMayeung**

**Many more articles at https://medium.com/@hohanga**

**Even more articles at http://thewebdev.info/**

With the `Intl.RelativeTimeFormat` constructor, we can format relative time in a locale sensitive manner with ease. We can style in different ways and format it the manner we want. This lets us format relative time strings without the hassle that comes from manipulating strings. The constructor takes 2 arguments. The first argument is a locale string or an array of such strings. The second argument is an object which takes a variety of arguments for adjusting the relative time string to the way we want. The instance of this constructor has a few methods to return the formatted string, the formatted string as an array of substrings, and a method to return the options that we set for formatting the string.

The first argument for the `Intl.RelativeTimeFormat` constructor is the locale which should be a [BCP 47 language tag](https://github.com/libyal/libfwnt/wiki/Language-Code-identifiers) or an array of such locale strings. This is an optional argument.

The second argument accepts an object with a few properties — `localeMatcher`, `numeric`, and `style` .

The `localeMatcher` option specifies the locale matching algorithm to use. The possible values are `lookup` and `best fit`. The lookup algorithm searches for the locale until it finds the one that fits the character set of the strings that are being compared. `best fit` finds the locale that is at least but possibly more suited than the `lookup` algorithm.

The `numeric` option lets us set the option for how the formatted string’s message is outputted. The possible values are `always` which is like ‘2 days ago’, or `auto` , for example, like ‘yesterday’. The `auto` allows us to not always use numeric values for output. The `style` option lets us change the length of the internationalized message. The possible values are `long`, `short`, or `narrow`. `long` would output something like ‘in 2 months’, `short` would be something like ‘in 2 mo.’, and `narrow` would be something like in ‘in 2 mo.’ It could be similar to the `short` style in some locales.

Instances of the `Intl.RelativeTimeFormat` constructor have a few methods. It has the `format` method to get the formatted relative time string with the value and the unit according to the locale and the formatting option that’s given in the constructor. The `formatToParts` method is similar to the `format` method except that the formatted string is returned as an array instead of a string. The `resolvedOptions` method returns an object with the options that we set in the constructor for formatting the string and the locale that were set.

The `format` method takes 2 arguments. The first is the value for the quantity of the relative date and the second is the time unit in string form. For example, we can format relative dates with the `format` method like in the following code:

```
const rtf = new Intl.RelativeTimeFormat("en", {  
  localeMatcher: "best fit",  
  numeric: "always",  
  style: "long",  
});

console.log(rtf.format(-1, "day"));
```

The code above would log ‘1 day ago’ since we specified the value of the relative date to be -1, which means 1 day before today, and the time unit is `day` . We can also put in other units. For example, if we want minutes, then we get:

```javascript
const rtf = new Intl.RelativeTimeFormat("en", {  
  localeMatcher: "best fit",  
  numeric: "always",  
  style: "long",  
});

console.log(rtf.format(-10, "minute"));
```

Then we get ‘10 minutes ago’ from the `console.log` statement. We can also change the style and the length. For example, we can write:

```javascript
const rtf = new Intl.RelativeTimeFormat("en", {  
  localeMatcher: "best fit",  
  numeric: "auto",  
  style: "short",  
});  
console.log(rtf.format(10, "minute"));
```

Then we get ‘in 10 min.’ from the `console.log` statement since we have positive 10 instead of negative 10 which is 10 minutes from the current time. Also, we had the `short` style which abbreviates the unit.

We can also change the locale for different locales. For example, we can write:

```javascript
const rtf = new Intl.RelativeTimeFormat("zh-hant", {  
  localeMatcher: "best fit",  
  numeric: "auto",  
  style: "long",  
});  
console.log(rtf.format(1, "minute"));
```

This gets the relative date-time string in Chinese Traditional characters instead of English. If we run the `console.log` statement in the code above, we get ‘1 分鐘後’, which means 1 minute later.

We can get the formatted string in an array of string parts with the `formatToParts()` method. It returns an array of substrings of the formatted strings. For example, we can call it like in the following code:

```javascript
const rtf = new Intl.RelativeTimeFormat("en", {  
  localeMatcher: "best fit",  
  numeric: "always",  
  style: "long",  
});

const parts = rtf.formatToParts(-1, "day");  
console.log(parts);
```

The code above would get us:

```javascript
[  
  {  
    "type": "integer",  
    "value": "1",  
    "unit": "day"  
  },  
  {  
    "type": "literal",  
    "value": " day ago"  
  }  
]
```

with the `console.log` statement in the code above.

The method works equally well with non-English locales. For example, we can write:

```javascript
const rtf = new Intl.RelativeTimeFormat("zh-hant", {  
  localeMatcher: "best fit",  
  numeric: "auto",  
  style: "long",  
});
const parts = rtf.formatToParts(1, "minute")  
console.log(parts);
```

Then we get:

```
\[  
  {  
    "type": "integer",  
    "value": "1",  
    "unit": "minute"  
  },  
  {  
    "type": "literal",  
    "value": " 分鐘後"  
  }  
\]
```

with the `console.log` statement in the code above.

The `resolvedOptions()` method gets us an object with the options that we set in the constructor for formatting the string and the locale that was set. We can use it as in the following code:

```javascript
const rtf = new Intl.RelativeTimeFormat("zh-hant", {  
  localeMatcher: "best fit",  
  numeric: "auto",  
  style: "long",  
});  
console.log(rtf.resolvedOptions());
```

With the code above, we get the following from the `console.log` statement:

```javascript
{  
  "locale": "zh-Hant",  
  "style": "long",  
  "numeric": "auto",  
  "numberingSystem": "latn"  
}
```

The `Intl.RelativeDateFormat` constructor also has a `supportedLocalesOf` method to get us the supported locales for formatting date and time. It takes an array of BCP 47 locale strings as an argument. Unicode extension keys will be returned along with the locale code even though it has no relevance for date formatting if provided. It takes the `localeMatcher` option to specify the locale matching algorithm to use. The possible values are `lookup` and `best fit` . The lookup algorithm search for the locale until it finds the one that fits the character set of the strings that are being compared. `best fit` finds the locale that is at least but possibly more suited than the `lookup` algorithm.

For example, we can use it as in the following code:

```javascript
const locales = ['en-ca', 'id-u-co-pinyin', 'ban'];  
const options = {  
  localeMatcher: 'lookup'  
};
console.log(Intl.RelativeTimeFormat.supportedLocalesOf(locales, options));
```

Then we get `[“en-CA”, “id-u-co-pinyin”]`. This is because Balinese is similar enough to Indonesian to be considered the same for the `lookup` algorithm. Note that the Unicode extensions that are in the input array are returned along with the output even though it has no relevance in this context.

The JavaScript `Intl.RelativeTimeFormat` constructor let us format relative time in a locale-sensitive manner with ease. We can style in different ways and format it the way we want. This lets us format relative time strings without much hassle that comes from manipulating strings. The constructor takes 2 arguments. The first argument is for a locale string or an array of such strings. The second is an object which takes a variety of arguments for adjusting the relative time string to the way we want. The instance of this constructor has a few methods to return the formatted string, the formatted string as an array of substrings, and a method to return the options that we set for formatting the string. We can also check the locales that supported by the static `supportedLocalesOf` method.