"Delivery in 10 business days." Sounds simple, right up until two people land on two different dates. Here are the traps I keep running into, plus a small JavaScript algorithm that doesn't drift by a day.
1. Does the start date count?
It's Monday and the deadline is "5 business days". Is that this Friday or next Monday? It depends on the convention:
- Exclusive (the start date doesn't count): Monday + 5 business days = next Monday.
- Inclusive (the start date is day 1): the 5th business day is Friday.
Excel uses both. WORKDAY returns the date a given number of working days after the start date, so the start date itself isn't counted. NETWORKDAYS counts whole working days including both ends. So NETWORKDAYS(start, WORKDAY(start, 5)) returns 6 when the start is a workday. Agree on the convention before you argue about the deadline.
2. Weekends aren't always Saturday and Sunday
A few examples:
- Saudi Arabia: Friday–Saturday
- Israel (Friday–Saturday for most offices; Sunday is a workday)
- Retail, healthcare and shift teams often have a single day off, or a rotating one
Excel handles this with WORKDAY.INTL and NETWORKDAYS.INTL. The weekend argument takes a number (1 = Saturday–Sunday, 7 = Friday–Saturday, 11 = Sunday only) or a 7-character string that starts on Monday, where 1 means day off: "0000011" is Saturday–Sunday, "0000001" is Sunday only.
If your code hard-codes [0, 6], it's wrong for a lot of people.
3. Holidays move
- Observed holidays. For US federal employees, a holiday that falls on a Saturday is observed on the Friday before, and one that falls on a Sunday is observed on the Monday after.
- Substitute holidays. The UK and South Korea, among others, add a substitute day off when certain holidays land on a weekend.
- Local holidays. National, state and city holidays stack. There is no single "holiday list" for a country that works for everyone.
The right holiday list is the one that applies to that team, in that place, this year.
4. Exceptions: a day off that becomes a workday
Make-up days, inventory Saturdays, on-call weekends... A usable model needs both extra days off and exceptional working days, and the exceptions have to override the weekly day off.
5. Time zones break dates
In JavaScript, new Date("2026-03-02") is parsed as midnight UTC. Anywhere west of UTC (the Americas, for example), getDay() and getDate() give you Sunday the 1st instead of Monday the 2nd. Parse date-only strings yourself and stay in UTC from start to finish.
An algorithm that handles all of the above
const parse = s => { const [y, m, d] = s.split("-").map(Number); return new Date(Date.UTC(y, m - 1, d)); };
const fmt = d => d.toISOString().slice(0, 10);
function isWorkday(date, { weekendDays = [0, 6], holidays = [], extraWorkdays = [] } = {}) {
const key = fmt(date);
if (extraWorkdays.includes(key)) return true; // an exception beats the weekly day off
if (holidays.includes(key)) return false;
return !weekendDays.includes(date.getUTCDay()); // 0 = Sunday
}
// n > 0 moves forward, n < 0 moves backward.
// inclusive: the start date counts as day 1 if it is a workday.
function addWorkdays(start, n, { inclusive = false, ...cal } = {}) {
const step = Math.sign(n) || 1;
let left = Math.abs(n);
const d = parse(start);
if (left === 0) return fmt(d);
if (inclusive && isWorkday(d, cal)) left--;
while (left > 0) {
d.setUTCDate(d.getUTCDate() + step);
if (isWorkday(d, cal)) left--;
}
return fmt(d);
}
const cal = { holidays: ["2026-11-20"] };
addWorkdays("2026-11-16", 5, cal); // "2026-11-24"
addWorkdays("2026-11-16", 5, { ...cal, inclusive: true }); // "2026-11-23"
addWorkdays("2026-03-02", 5); // "2026-03-09"
addWorkdays("2026-03-02", 5, { inclusive: true }); // "2026-03-06"
It walks one calendar day at a time instead of doing clever math with / 7. For deadlines measured in days or weeks, that's plenty fast, and it's much easier to explain why a given date was skipped.
In TypeScript, I'd type the calendar as { weekendDays: number[]; holidays: string[]; extraWorkdays: string[] } and use Sets if the lists get long.
Checklist
- Write down whether the start date counts.
- Make the weekend configurable.
- Let the user supply holidays; don't pretend one list fits a whole country.
- Support exceptional working days.
- Parse date-only strings in UTC.
- Show which days were counted and which were skipped.
How does your team count "business days"? I'd love to hear the edge cases I missed.
Disclosure: I build WorkdayMap, a free business-day calculator that applies these rules and shows every counted and skipped day.
Top comments (0)