nhb-toolbox
Version:
A versatile collection of smart, efficient, and reusable utility functions and classes for everyday development needs.
90 lines (89 loc) • 3.17 kB
JavaScript
import { formatUnitWithPlural } from '../../string/convert.js';
import { INTERNALS } from '../constants.js';
/** * Plugin to inject `fromNow` method */
export const fromNowPlugin = (ChronosClass) => {
ChronosClass.prototype.fromNow = function (level = 'minute', withSuffixPrefix = true, time) {
const now = ChronosClass[INTERNALS].toNewDate(this, time);
const target = ChronosClass[INTERNALS].internalDate(this);
const isFuture = target > now;
const from = isFuture ? now : target;
const to = isFuture ? target : now;
let years = to.getFullYear() - from.getFullYear();
let months = to.getMonth() - from.getMonth();
let days = to.getDate() - from.getDate();
let weeks = 0;
let hours = to.getHours() - from.getHours();
let minutes = to.getMinutes() - from.getMinutes();
let seconds = to.getSeconds() - from.getSeconds();
// Adjust negative values
if (seconds < 0) {
seconds += 60;
minutes--;
}
if (minutes < 0) {
minutes += 60;
hours--;
}
if (hours < 0) {
hours += 24;
days--;
}
if (level === 'week' || level === 'day') {
weeks = Math.floor(days / 7);
days = days % 7;
}
if (days < 0) {
const prevMonth = new Date(to.getFullYear(), to.getMonth(), 0);
days += prevMonth.getDate();
months--;
}
if (months < 0) {
months += 12;
years--;
}
const unitOrder = [
'year',
'month',
'week',
'day',
'hour',
'minute',
'second',
];
const lvlIdx = unitOrder.indexOf(level);
const parts = [];
if (lvlIdx >= 0 && years > 0 && lvlIdx >= unitOrder.indexOf('year')) {
parts?.push(formatUnitWithPlural(years, 'year'));
}
if (lvlIdx >= unitOrder.indexOf('month') && months > 0) {
parts?.push(formatUnitWithPlural(months, 'month'));
}
if (lvlIdx >= unitOrder.indexOf('week') && weeks > 0) {
parts?.push(formatUnitWithPlural(weeks, 'week'));
}
if (lvlIdx >= unitOrder.indexOf('day') && days > 0) {
parts?.push(formatUnitWithPlural(days, 'day'));
}
if (lvlIdx >= unitOrder.indexOf('hour') && hours > 0) {
parts?.push(formatUnitWithPlural(hours, 'hour'));
}
if (lvlIdx >= unitOrder.indexOf('minute') && minutes > 0) {
parts?.push(formatUnitWithPlural(minutes, 'minute'));
}
if (lvlIdx >= unitOrder.indexOf('second') &&
(seconds > 0 || parts?.length === 0)) {
parts?.push(formatUnitWithPlural(seconds, 'second'));
}
let prefix = '';
let suffix = '';
if (withSuffixPrefix) {
if (isFuture) {
prefix = 'in ';
}
else {
suffix = ' ago';
}
}
return `${prefix}${parts?.join(' ')}${suffix}`;
};
};