impl/typescript.ts
1,196 bytes · the TypeScript implementation · view raw
Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.
import { epochDayFromIso, isoFromEpochDay } from "./dates_add_days.ts"; ← from dates.add-days ^1.0.0 · built alongside by fune
import { dayOfWeek } from "./dates_day_of_week.ts"; ← from dates.day-of-week ^1.0.0 · built alongside by fune
/**
* The `days`-th working day after `iso` (before it when negative), skipping
* Saturdays, Sundays and the listed holidays. The start date is never counted,
* so Friday + 1 and Saturday + 1 are both Monday, as in spreadsheet WORKDAY.
* Zero returns `iso` unchanged.
*/
export function addBusinessDays(iso: string, days: number, holidays: readonly string[]): string {
if (!Number.isInteger(days)) {
throw new TypeError(`days must be an integer, received ${days}`);
}
let day = epochDayFromIso(iso);
// Every holiday is validated even when the move never reaches it, so a typo
// in a calendar fails on the next run rather than in the year it matters.
const excluded = new Set<number>();
for (const holiday of holidays) excluded.add(epochDayFromIso(holiday));
const step = days < 0 ? -1 : 1;
let weekday = dayOfWeek(iso);
let remaining = Math.abs(days);
while (remaining > 0) {
day += step;
weekday = ((weekday - 1 + step + 7) % 7) + 1;
if (weekday <= 5 && !excluded.has(day)) remaining--;
}
return isoFromEpochDay(day);
}