import { DAY, HOUR, MINUTE, SECOND, WEEK } from "./constants.ts";
export type Unit = | "milliseconds" | "seconds" | "minutes" | "hours" | "days" | "weeks" | "months" | "quarters" | "years";
export type DifferenceFormat = Partial<Record<Unit, number>>;
export type DifferenceOptions = { units?: Unit[];};
function calculateMonthsDifference(from: Date, to: Date): number { let months = (from.getFullYear() - to.getFullYear()) * 12 + (from.getMonth() - to.getMonth()); if (from.getDate() < to.getDate()) { months--; } return months;}
export function difference( from: Date, to: Date, options?: DifferenceOptions,): DifferenceFormat { const uniqueUnits = options?.units ? [...new Set(options?.units)] : [ "milliseconds", "seconds", "minutes", "hours", "days", "weeks", "months", "quarters", "years", ];
const differenceInMs = Math.abs(from.getTime() - to.getTime());
const differences: DifferenceFormat = {};
for (const uniqueUnit of uniqueUnits) { switch (uniqueUnit) { case "milliseconds": differences.milliseconds = differenceInMs; break; case "seconds": differences.seconds = Math.floor(differenceInMs / SECOND); break; case "minutes": differences.minutes = Math.floor(differenceInMs / MINUTE); break; case "hours": differences.hours = Math.floor(differenceInMs / HOUR); break; case "days": differences.days = Math.floor(differenceInMs / DAY); break; case "weeks": differences.weeks = Math.floor(differenceInMs / WEEK); break; case "months": differences.months = calculateMonthsDifference(from, to); break; case "quarters": differences.quarters = Math.floor( (differences.months !== undefined && differences.months / 3) || calculateMonthsDifference(from, to) / 3, ); break; case "years": differences.years = Math.floor( (differences.months !== undefined && differences.months / 12) || calculateMonthsDifference(from, to) / 12, ); break; } }
return differences;}