Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ibrahimcesar/535a4338464e6ed643d1f1b879c06e18 to your computer and use it in GitHub Desktop.
Save ibrahimcesar/535a4338464e6ed643d1f1b879c06e18 to your computer and use it in GitHub Desktop.
Simplified getRelativeTimeString
// from https://twitter.com/Steve8708/status/1504131981444980739
// simplified to a function body of 8 tidy lines
// no loop needed, no 2d array of 3-tuples needed
// just 2 arrays, a findIndex call, and some indexing :)
export function getRelativeTimeString(
date: Date | number,
lang = "en"
): string {
const timeMs = typeof date === "number" ? date : date.getTime();
const deltaSeconds = Math.round((timeMs - Date.now()) / 1000);
const cutoffs = [60, 3600, 86400, 86400 * 7, 86400 * 30, 86400 * 365, Infinity];
const units: Intl.RelativeTimeFormatUnit[] = ["second", "minute", "hour", "day", "week", "month", "year"];
const unitIndex = cutoffs.findIndex(cutoff => cutoff > Math.abs(deltaSeconds));
const divisor = unitIndex ? cutoffs[unitIndex - 1] : 1;
const rtf = new Intl.RelativeTimeFormat(lang, { numeric: "auto" });
return rtf.format(Math.floor(deltaSeconds / divisor), units[unitIndex]);
}
// alternate: init the arrays + RTF only once, keep in closure
// worthwhile if doing lots of calls, RTF init isn't free
// this is probably how I would actually do this for prod shipped code I guess
export function makeRelativeTimeStringGetter(lang = "en") {
const cutoffs = [60, 3600, 86400, 86400 * 7, 86400 * 30, 86400 * 365, Infinity];
const units: Intl.RelativeTimeFormatUnit[] = ["second", "minute", "hour", "day", "week", "month", "year"];
const rtf = new Intl.RelativeTimeFormat(lang, { numeric: "auto" });
return function getRelativeTimeString(date: Date | number): string {
const timeMs = typeof date === "number" ? date : date.getTime();
const deltaSeconds = Math.round((timeMs - Date.now()) / 1000);
const unitIndex = cutoffs.findIndex(cutoff => cutoff > Math.abs(deltaSeconds));
const divisor = unitIndex ? cutoffs[unitIndex - 1] : 1;
return rtf.format(Math.floor(deltaSeconds / divisor), units[unitIndex]);
}
}
console.log(getRelativeTimeString(Date.now() - 100)); // now
console.log(getRelativeTimeString(Date.now() - 10000)); // 10 seconds ago
console.log(getRelativeTimeString(Date.now() - 100000)); // 2 minutes ago
console.log(getRelativeTimeString(Date.now() - 10000000)); // 3 hours ago
console.log(getRelativeTimeString(Date.now() + 10000)); // in 10 seconds
console.log(getRelativeTimeString(Date.now() + 100000)); // in 1 minute
console.log(getRelativeTimeString(Date.now() + 10000000)); // in 2 hours
console.log(getRelativeTimeString(Date.now() + 100000000)); // tomorrow
console.log(getRelativeTimeString(Date.now() + 1000000000)); // next week
console.log(getRelativeTimeString(Date.now() + 10000000000)); // in 3 months
console.log(getRelativeTimeString(Date.now() + 100000000000)); // in 3 years
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment