Skip to content

Instantly share code, notes, and snippets.

@liamnewmarch
Last active May 6, 2026 15:11
Show Gist options
  • Select an option

  • Save liamnewmarch/a345fbf0c4fdf938d9844b82a4f127ab to your computer and use it in GitHub Desktop.

Select an option

Save liamnewmarch/a345fbf0c4fdf938d9844b82a4f127ab to your computer and use it in GitHub Desktop.
Relative time strings using the web platform
/**
* The target language. Try the document language[1], if set, and use the
* browser's language[2] as a fallback.
*
* [1]: https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/lang
* [2]: https://developer.mozilla.org/en-US/docs/Web/API/NavigatorLanguage/language
*
* @type {string}
*/
const language = Intl.getCanonicalLocales([
document.documentElement.lang,
])[0] ?? navigator.language;
/**
* Instance of the relative time format object for the target language. As of
* 2020, [browser support for this][3] is good.
*
* [3]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/RelativeTimeFormat
* @type {Intl.RelativeTimeFormat}
*/
const formatter = new Intl.RelativeTimeFormat(language, {
numeric: "auto",
style: "long",
});
/**
* Mapping from a Intl.RelativeTimeFormat unit string to the equivalent value
* in milliseconds.
*
* @type {{[unit: string]: number}}
*/
const units = {
year: 31_557_600_000, // Approx. 86,400 seconds per day * 365.25 days.
month: 2_629_800_000, // Approx. 31,557,600 seconds per year / 12 months.
day: 86_400_000,
hour: 3_600_000,
minute: 60_000,
second: 1_000,
};
/**
* Return an Intl.RelativeTimeFormat string without having to specify units.
*
* @param {Date} when
* @returns {string}
*/
export function formatRelative(when) {
const ms = when - Date.now();
for (const [unit, value] of Object.entries(units)) {
const amount = Math.ceil(ms / value);
if (amount || unit === 'second') {
return formatter.format(amount, unit);
}
}
}
@vhoyer
Copy link
Copy Markdown

vhoyer commented May 17, 2020

but the "just now" is hard coded, don't we have a equivalent in the Intl?

@liamnewmarch
Copy link
Copy Markdown
Author

liamnewmarch commented May 17, 2020

Ah, good point. Hard coding the "just now" string means it can’t be translated. Intl doesn’t provide a string like that. You could use a translation/localisation library, or pass the translated value through HTML using a data attribute. Since this example is just JavaScript, I’ll return seconds as a fallback.

@vhoyer
Copy link
Copy Markdown

vhoyer commented May 19, 2020

yeah, I wanted a "just now" equivalent haha, but I guess the seconds are fine 😅

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment