Formatting Relative Time with JavaScript’s RelativeTimeFormat Constructor
John Au-Yeung
Posted on February 6, 2020
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 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:
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:
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:
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:
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:
[
{
"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:
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:
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:
{
"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:
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.
Posted on February 6, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.