Skip to content

Instantly share code, notes, and snippets.

@davidglezz
Last active May 24, 2021 07:48
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 davidglezz/0f784b543c02d70087723d47571b8c9d to your computer and use it in GitHub Desktop.
Save davidglezz/0f784b543c02d70087723d47571b8c9d to your computer and use it in GitHub Desktop.
RelativeTime formatter inspired by DayJs
import {relativeTime} from './RelativeTime.ts'
console.log(relativeTime(new Date(), new Date(Date.now()-(15*1000))));
// -> "a few seconds ago"
/**
* Locale strings
* You can get it from https://github.com/iamkun/dayjs/blob/dev/src/locale/
*/
const loc = {
future: 'in %s',
past: '%s ago',
s: 'a few seconds',
m: 'a minute',
mm: '%d minutes',
h: 'an hour',
hh: '%d hours',
d: 'a day',
dd: '%d days',
M: 'a month',
MM: '%d months',
y: 'a year',
yy: '%d years'
} as const
/**
* Thresholds
* l: locale string
* r: max value displayed with current locale string
* d: divisor to convert from the previous unit to the current one
*
* @example :
* We start with milliseconds. Thresholds[0]:
* then we convert it to seconds dividing it by d=1000 and up to r=44 seconds we show the string of the locale l="s" (a few seconds)
* next: Thresholds[1]:
* we do not convert or div by d=1, and up to r=89 seconds we show the locale l="m" (a minute)
* etc...
*/
const Thresholds = [
{ l: 's', r: 44, d: 1000 },
{ l: 'm', r: 89, d: 1 },
{ l: 'mm', r: 44, d: 60 },
{ l: 'h', r: 89, d: 1 },
{ l: 'hh', r: 21, d: 60 },
{ l: 'd', r: 35, d: 1 },
{ l: 'dd', r: 25, d: 24 },
{ l: 'M', r: 45, d: 1 },
{ l: 'MM', r: 10, d: 365/12 },
{ l: 'y', r: 17, d: 1 },
{ l: 'yy', r: Number.MAX_VALUE, d: 12 }
] as const;
export function relativeTime(from = new Date(), to = new Date()): string {
let result = to.getTime() - from.getTime();
for (const { l: localeString, r: max, d: divider } of Thresholds) {
result /= divider;
let abs = Math.round(Math.abs(result));
if (abs <= max) {
return (result > 0 ? loc.future : loc.past).replace('%s', loc[localeString].replace('%d', abs.toString()));
}
}
throw new Error('Invalid Threshold object');
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment