Last active
May 24, 2021 07:48
-
-
Save davidglezz/0f784b543c02d70087723d47571b8c9d to your computer and use it in GitHub Desktop.
RelativeTime formatter inspired by DayJs
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
import {relativeTime} from './RelativeTime.ts' | |
console.log(relativeTime(new Date(), new Date(Date.now()-(15*1000)))); | |
// -> "a few seconds ago" |
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
/** | |
* 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