Last active
May 6, 2026 15:11
-
-
Save liamnewmarch/a345fbf0c4fdf938d9844b82a4f127ab to your computer and use it in GitHub Desktop.
Relative time strings using the web platform
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * 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); | |
| } | |
| } | |
| } |
Author
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.
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
but the "just now" is hard coded, don't we have a equivalent in the Intl?