Functional Weave
Code in Rust

dates.add-business-days@1.0.0

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);
}