
How to Calculate Business Days Excluding Public Holidays
To calculate business days between two dates, count every day in the range that is not a weekend and not a public holiday in the relevant country. Weekends are simple to detect from the calendar; public holidays differ by country and change every year, so they should come from a data source instead of being hard-coded.
This guide shows the method step by step, with code that gets holiday dates from the HolidaysMap API.
The method
- Decide which days are the weekend for the country you work with.
- Fetch the public holidays for the date range.
- Walk through every day from start to end and count the days that are neither weekend nor holiday.
A worked example: January 2024 has 23 weekdays. France’s only public holiday that month is New Year’s Day on Monday 1 January, so there are 22 business days.
Step 1: do not assume Saturday and Sunday
Saturday and Sunday are the weekend in most countries, but not all. Some countries, such as Saudi Arabia, use Friday and Saturday. Make the weekend a parameter of your function so it works for any country you support.
Step 2: fetch the holidays for the range
Request all public holidays between your start and end date in one call. Range queries with start and end are available on the Premium plan (see pricing); on the free plan you can look up one date at a time instead, as described in how to check if a date is a public holiday.
curl "https://holidaysmap.com/api/v1/holidays?key=YOUR_API_KEY&code=FR&start=2024-01-01&end=2024-01-31&format=YYYY-MM-DD"
Use format=YYYY-MM-DD so the returned dates match the ISO dates you compare against. Keep only entries where is_public is true.
Step 3: count the business days in JavaScript
async function fetchPublicHolidayDates(countryCode, startIso, endIso) {
const params = new URLSearchParams({
key: process.env.HOLIDAYS_API_KEY,
code: countryCode,
start: startIso,
end: endIso,
format: 'YYYY-MM-DD',
});
const response = await fetch(`https://holidaysmap.com/api/v1/holidays?${params}`);
if (!response.ok) {
throw new Error(`Holidays API request failed with status ${response.status}`);
}
const data = await response.json();
return new Set(
data.holidays.filter((holiday) => holiday.is_public).map((holiday) => holiday.date),
);
}
function countBusinessDays(startIso, endIso, holidayDates, weekendDays = [0, 6]) {
let count = 0;
const last = new Date(`${endIso}T00:00:00Z`);
for (
const day = new Date(`${startIso}T00:00:00Z`);
day <= last;
day.setUTCDate(day.getUTCDate() + 1)
) {
const isoDate = day.toISOString().slice(0, 10);
if (!weekendDays.includes(day.getUTCDay()) && !holidayDates.has(isoDate)) {
count += 1;
}
}
return count;
}
const holidays = await fetchPublicHolidayDates('FR', '2024-01-01', '2024-01-31');
console.log(countBusinessDays('2024-01-01', '2024-01-31', holidays));
Both the start and end date are counted. In JavaScript getUTCDay() returns 0 for Sunday and 6 for Saturday.
Step 4: count the business days in Python
import os
from datetime import date, timedelta
import requests
def fetch_public_holiday_dates(country_code: str, start: date, end: date) -> set[date]:
response = requests.get(
"https://holidaysmap.com/api/v1/holidays",
params={
"key": os.environ["HOLIDAYS_API_KEY"],
"code": country_code,
"start": start.isoformat(),
"end": end.isoformat(),
"format": "YYYY-MM-DD",
},
timeout=10,
)
response.raise_for_status()
return {
date.fromisoformat(holiday["date"])
for holiday in response.json()["holidays"]
if holiday["is_public"]
}
def count_business_days(
start: date, end: date, holidays: set[date], weekend_days: frozenset[int] = frozenset({5, 6})
) -> int:
count = 0
day = start
while day <= end:
if day.weekday() not in weekend_days and day not in holidays:
count += 1
day += timedelta(days=1)
return count
start, end = date(2024, 1, 1), date(2024, 1, 31)
print(count_business_days(start, end, fetch_public_holiday_dates("FR", start, end)))
In Python weekday() returns 0 for Monday, so Saturday and Sunday are 5 and 6.
Edge cases to handle
- Holidays that fall on a weekend. The set lookup handles this: a holiday on a Saturday is already excluded as a weekend and is not subtracted twice.
- Regional holidays. A country-level query returns country-level holidays. If your business rules depend on a region, check that the data covers it before relying on the result.
- Company-specific days off. Add your own closure days to the holiday set before counting.
- Time zones. Work with calendar dates, not timestamps, to avoid an off-by-one day near midnight.
- Caching. Holidays for a past year do not change. Cache the holiday set per country and year instead of calling the API for every calculation.
Next steps
Browse the supported countries and their codes, read the full API documentation, or look at the JSON response format in detail.