UNPKG

@technobuddha/library

Version:
106 lines (97 loc) 3.15 kB
import { addTime } from './add-time.ts'; import { secondsPerDay, secondsPerHour, secondsPerMinute, ticksPerSecond } from './date.ts'; import { floor } from './floor.ts'; import { formatDate } from './format-date.ts'; import { isSameDay } from './is-same-day.ts'; import { plural } from './plural.ts'; import { space } from './unicode.ts'; /** * Options for the {@link relativeTime} function * @group Time * @category Relative Time */ export type RelativeTimeOptions = { /** Describe the time difference as a time on a nearby day */ todayTomorrowYesterday?: boolean; /** Passed to {@link formatDate} to display a time */ timeFormat?: string; /** Passed to {@link formatDate} to display a year, month and day */ ymdFormat?: string; /** Passed to {@link formatDate} to display a month and day */ mdFormat?: string; }; /** * Describe the difference between two dates in a simple format * @param input - The date * @param relativeTo - The date to compare to * @param options - see {@link RelativeTimeOptions} * @returns string describing the time difference between the two dates * @group Time * @category Relative Time */ export function relativeTime( input: Date, relativeTo: Date, { todayTomorrowYesterday = false, timeFormat = 'H:mm TT', ymdFormat = 'MMMM D YYYY', mdFormat = 'MMMM D', }: RelativeTimeOptions = {}, ): string { const text = [] as string[]; if (todayTomorrowYesterday) { if (isSameDay(input, relativeTo)) { text.push(`today ${formatDate(input, timeFormat)} -`); } else if (isSameDay(input, addTime(relativeTo, { days: 1 }))) { text.push(`tomorrow ${formatDate(input, timeFormat)} -`); } else if (isSameDay(input, addTime(relativeTo, { days: -1 }))) { text.push(`yesterday ${formatDate(input, timeFormat)} -`); } } let diff = (input.getTime() - relativeTo.getTime()) / ticksPerSecond; let sign = 1; if (diff < 0) { sign = -1; diff = Math.abs(diff); } const d = floor(diff / secondsPerDay, { tolerance: 0.05 }); const h = floor((diff - d * secondsPerDay) / secondsPerHour, { tolerance: 0.05 }); const m = floor((diff - d * secondsPerDay - h * secondsPerHour) / secondsPerMinute, { tolerance: 0.05, }); const s = floor(diff - d * secondsPerDay - h * secondsPerHour - m * secondsPerMinute, { tolerance: 0.05, }); if (d > 90) { text.push(formatDate(input, ymdFormat)); sign = 0; } else if (d > 30) { text.push(formatDate(input, mdFormat)); sign = 0; } else if (d > 0) { text.push(plural('day', d, true)); if (d < 4 && h > 1) { text.push(plural('hour', h, true)); } } else if (h > 0) { text.push(plural('hour', h, true)); if (h < 4 && m > 0) { text.push(plural('minute', m, true)); } } else if (m > 0) { text.push(plural('minute', m, true)); if (m < 4 && s > 0) { text.push(plural('second', s, true)); } } else if (s > 0) { text.push(plural('second', s, true)); } if (sign === -1) { text.push('ago'); } if (sign === 1) { text.push(d || h || m || s ? 'from now' : 'now'); } return text.join(space); }