Functional Weave
Code in Python

dates.add-business-days@1.0.0

impl/python.py

1,196 bytes · the Python 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.

from typing import Sequence

from .dates_add_days import epoch_day_from_iso, iso_from_epoch_day  ← from dates.add-days ^1.0.0 · built alongside by fune
from .dates_day_of_week import day_of_week  ← from dates.day-of-week ^1.0.0 · built alongside by fune


def add_business_days(iso: str, days: int, holidays: Sequence[str]) -> str:
    """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.
    """
    if isinstance(days, bool) or not isinstance(days, int):
        raise TypeError("days must be an integer, received %r" % (days,))
    day = epoch_day_from_iso(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.
    excluded = {epoch_day_from_iso(holiday) for holiday in holidays}

    step = -1 if days < 0 else 1
    weekday = day_of_week(iso)
    remaining = abs(days)
    while remaining > 0:
        day += step
        weekday = (weekday - 1 + step) % 7 + 1
        if weekday <= 5 and day not in excluded:
            remaining -= 1
    return iso_from_epoch_day(day)