diff --git a/src/Time.ts b/src/Time.ts new file mode 100644 index 0000000..fbaf98f --- /dev/null +++ b/src/Time.ts @@ -0,0 +1,93 @@ +export class TimeUnit { + public constructor( + public readonly milliseconds: number, + public readonly longName: string, + public readonly shortName: string, + ) { + } +} + +export default class Time { + public static readonly UNITS = { + MILLISECOND: { + milliseconds: 1, + longName: 'millisecond', + shortName: 'ms', + }, + SECOND: { + milliseconds: 1000, + longName: 'second', + shortName: 's', + }, + MINUTE: { + milliseconds: 60 * 1000, + longName: 'minute', + shortName: 'm', + }, + HOUR: { + milliseconds: 60 * 60 * 1000, + longName: 'hour', + shortName: 'h', + }, + DAY: { + milliseconds: 24 * 60 * 60 * 1000, + longName: 'day', + shortName: 'd', + }, + MONTH: { + milliseconds: 30 * 24 * 60 * 60 * 1000, + longName: 'month', + shortName: 'M', + }, + YEAR: { + milliseconds: 365 * 24 * 60 * 60 * 1000, + longName: 'year', + shortName: 'y', + }, + }; + + public static humanizeTimeSince( + since: Date, + short?: boolean, + skipOneUnitNumber?: boolean, + units?: TimeUnit[], + ): string { + return this.humanizeDuration(Date.now() - since.getTime(), short, skipOneUnitNumber, units); + } + + public static humanizeTimeTo( + to: Date, + short?: boolean, + skipOneUnitNumber?: boolean, + units?: TimeUnit[], + ): string { + return this.humanizeDuration(to.getTime() - Date.now(), short, skipOneUnitNumber, units); + } + + public static humanizeDuration( + duration: number, + short: boolean = false, + skipOneUnitNumber: boolean = false, + units: TimeUnit[] = [ + this.UNITS.SECOND, + this.UNITS.MINUTE, + this.UNITS.HOUR, + this.UNITS.DAY, + this.UNITS.MONTH, + this.UNITS.YEAR, + ], + ): string { + for (let i = units.length - 1; i > 0; i--) { + if (duration >= units[i - 1].milliseconds && duration < units[i].milliseconds) { + const amount = Math.floor(duration / units[i - 1].milliseconds); + const unit = short ? + units[i - 1].shortName : + ' ' + units[i - 1].longName + (amount > 1 ? 's' : ''); + return (amount > 1 || !skipOneUnitNumber ? amount : '') + unit; + } + } + + return 'now'; + } + +}