Functional Weave
Code in Rust

dates.business-days-between@1.0.0

README.md

1,432 bytes · view raw

# dates.business-days-between

The interval is half-open: start inclusive, end exclusive. Two consequences a
caller has to know. Same date twice is 0, not 1. And intervals compose:
between(a,b) + between(b,c) = between(a,c), which is what lets a report be
summed by week or by month without double counting the boundary days. If you
want the end date included - "the job takes five working days and today counts" -
pass the day after it.

A start later than the end returns a negative count, exactly -between(end,
start). Clamping to zero would silently absorb an argument-order bug, and a
payment term calculated from swapped dates should look obviously wrong rather
than plausibly zero.

Holidays are an argument because no library knows which days your business is
closed, and a bank holiday calendar is jurisdiction-specific, year-specific and
sometimes employer-specific. Holidays on a weekend are not subtracted twice,
duplicates in the list are harmless, and holidays outside the interval are
ignored - but they are still validated, so a typo in a calendar fails on the
next run rather than in the year it finally falls inside a query.

The count is a day-by-day loop rather than a closed-form week count. It is
O(days) and that is a deliberate trade: the loop is the same six lines in all
three languages, which makes the parity gate meaningful, and the closed form is
where off-by-one errors around the start weekday live.