In the previous post, I showed you how you can leverage the Internationalization API to format dates using the user's locale. In this post, I'll show you how you can use the same API to create relative dates.

Relative dates are very common in applications where you want show the user the amount of time that has passed or will pass until something happens rather than  the specific date and time when something happened. For example, instead of showing that a post was published on 01/11/2021, or Nov 1st, 2021, you can show: "published yesterday" or "published 1 day ago" or if it's in the future: "this post will be published in 2 days". All of this can be achieved with the Intl API, although you might need to check browser support because this feature is relatively new.

To create the relative date formatter, you need to pass two arguments: the locale and an object with options:

const formatter = new Intl.RelativeTimeFormat('en-US', {
    numeric: 'always',
    style: 'long'
})

And to actually format a date you need to pass the number which represents the relative difference (this can be positive for the future and negative for the past) and the "unit" you want your output to be displayed ("day", "month", etc...):

formatter.format(1, "day") // "in 1 day"
formatter.format(-2, "month") // "2 months ago"
formatter.format(4, "year") // "in 4 years"
formatter.format(5, "hour") // "in 5 hours"

You can also use the option: numeric: auto for a more "natural" language:

const formatter = new Intl.RelativeTimeFormat('en-US', {
    numeric: 'auto',
})

formatter.format(1, "day") // "tomorrow"
formatter.format(-1, "day") // "yesterday"
formatter.format(-1, "month") // "last month"
formatter.format(1, "year") // "next year"

An then there's the short and narrow options for style (which can be similar depending on the locale):

let formatter = new Intl.RelativeTimeFormat('en-US', {
    style: 'short',
})

formatter.format(-2, "month") // "2 mo. ago"
formatter.format(4, "year") // "in 4 yr."

formatter = new Intl.RelativeTimeFormat('en-US', {
    style: 'narrow',
})

formatter.format(-2, "month") // "2 mo. ago"
formatter.format(4, "year") // "in 4 yr."
formatter.format(-2, "minute") // "2 min. ago"

And that's it for the relative date formatter. Of course, you still have to do some of the "heavy lifting" of coming up with the date difference, but that can be as simple as:

const diff = new Date(2021, 9, 10) - new Date();
const seconds = diff / 1000; // -1937124.765
const minutes = seconds / 60; // -5158.739066666666
const hours = minutes / 60; // -85.97898444444444

const formatter = new Intl.RelativeTimeFormat('en-US', {
    numeric: 'auto',
})

formatter.format(hours, 'hour'); // 85.979 hours ago

Which you can then round or improve as per your application's requirements.

Ok, that's it for relative date formatting using the Intl API. See you on the next post!