WFDASH-WEBAPP/src/lib/working-days.ts

58 lines
2.1 KiB
TypeScript
Raw Normal View History

/**
* Working-days date math for the Quotes dashboard.
*
* "Working days" = weekdays only. Saturdays and Sundays are skipped.
* Public holidays are intentionally NOT subtracted — the team can layer
* that on later if it becomes a problem; for the current "show me the
* aged quotes" indicator, weekday-only is the right baseline.
*
* All comparisons are done in the browser's local time. Quotes have
* `created` timestamps in ISO UTC; we convert to local-day boundaries
* before counting so "3 working days old" means "3 weekdays since the
* day this row was created, in the user's timezone".
*/
/** Strip a Date down to its local-day midnight. */
function startOfLocalDay(d: Date): Date {
return new Date(d.getFullYear(), d.getMonth(), d.getDate());
}
/**
* Number of working days (Mon–Fri) between `then` and `now`, exclusive
* of both endpoints' days. So a quote created today returns 0; a quote
* created yesterday on a weekday returns 1; a quote created Friday
* morning checked Monday morning returns 1 (Sat/Sun skipped).
*
* Returns 0 when `then` is in the future or on the same day as `now`.
*/
export function workingDaysBetween(then: Date | string, now: Date = new Date()): number {
const thenDate = typeof then === "string" ? new Date(then) : then;
if (Number.isNaN(thenDate.getTime())) return 0;
const startThen = startOfLocalDay(thenDate);
const startNow = startOfLocalDay(now);
if (startNow <= startThen) return 0;
let count = 0;
const cursor = new Date(startThen);
cursor.setDate(cursor.getDate() + 1); // start counting the day AFTER creation
while (cursor <= startNow) {
const dow = cursor.getDay(); // 0 = Sunday, 6 = Saturday
if (dow !== 0 && dow !== 6) count++;
cursor.setDate(cursor.getDate() + 1);
}
return count;
}
/**
* True iff `then` is older than `days` working days before `now`.
* Convenience wrapper around `workingDaysBetween` for the age warning.
*/
export function isOlderThanWorkingDays(
then: Date | string,
days: number,
now: Date = new Date()
): boolean {
return workingDaysBetween(then, now) >= days;
}