BizDay

How to Calculate Business Days in JavaScript

From simple weekend skipping to production-ready holiday handling.

Every JavaScript Developer Faces This

You are building a feature that needs to display delivery dates, SLA deadlines, or payment settlement windows. The requirement says “business days,” and your first instinct is to write a loop that skips Saturday and Sunday. That works right up until it does not.

The JavaScript Date object gives you getDay(), which returns 0 for Sunday and 6 for Saturday. That is enough to skip weekends. But business days also exclude public holidays, and that is where the real complexity begins.

The Weekend-Only Approach

Here is the most common starting point. This function adds a given number of business days to a start date, skipping weekends:

addBusinessDays.js
function addBusinessDays(startDate, days) {
  const result = new Date(startDate);
  let added = 0;

  while (added < days) {
    result.setDate(result.getDate() + 1);
    const dayOfWeek = result.getDay();
    if (dayOfWeek !== 0 && dayOfWeek !== 6) {
      added++;
    }
  }

  return result;
}

// 10 business days from March 9, 2026
const deadline = addBusinessDays(new Date('2026-03-09'), 10);
console.log(deadline.toISOString().slice(0, 10));
// "2026-03-23"

This is clean and works for the simplest case. But it assumes every Monday through Friday is a working day, which is incorrect in every country. Christmas Day, Independence Day, bank holidays — none of these are accounted for.

The Hardcoded Holiday List

The next step most developers take is adding an array of holiday dates:

withHolidays.js
const US_HOLIDAYS_2026 = [
  '2026-01-01', // New Year's Day
  '2026-01-19', // MLK Jr. Day
  '2026-02-16', // Presidents' Day
  '2026-05-25', // Memorial Day
  '2026-07-03', // Independence Day (observed)
  '2026-09-07', // Labor Day
  '2026-11-26', // Thanksgiving
  '2026-12-25', // Christmas
];

function addBusinessDays(startDate, days, holidays = []) {
  const holidaySet = new Set(holidays);
  const result = new Date(startDate);
  let added = 0;

  while (added < days) {
    result.setDate(result.getDate() + 1);
    const dayOfWeek = result.getDay();
    const dateStr = result.toISOString().slice(0, 10);

    if (dayOfWeek !== 0 && dayOfWeek !== 6 && !holidaySet.has(dateStr)) {
      added++;
    }
  }

  return result;
}

This works for a single country and a single year. But maintaining these lists introduces several problems:

Using the BizDay API Instead

Rather than maintaining holiday data yourself, you can delegate this to the BizDay API. It maintains up-to-date holiday calendars for 30+ countries and handles all the edge cases described above. Here is how to use it in JavaScript.

Check if a Date Is a Business Day

checkBusinessDay.js
const API_KEY = process.env.BIZDAY_API_KEY;
const BASE_URL = 'https://api.bizday.dev';

async function isBusinessDay(date, country = 'US') {
  const res = await fetch(
    `${BASE_URL}/v1/check?date=${date}&country=${country}`,
    { headers: { Authorization: `Bearer ${API_KEY}` } }
  );
  const json = await res.json();
  return json.data.is_workday;
}

// Check if Christmas 2026 is a business day in the UK
const result = await isBusinessDay('2026-12-25', 'GB');
console.log(result); // false

Add Business Days (Holiday-Aware)

addDaysApi.js
async function addBusinessDays(date, days, country = 'US') {
  const res = await fetch(
    `${BASE_URL}/v1/add?date=${date}&days=${days}&country=${country}`,
    { headers: { Authorization: `Bearer ${API_KEY}` } }
  );
  const json = await res.json();
  return json.data.result_date;
}

// 10 business days from today in Germany
const deadline = await addBusinessDays('2026-03-09', 10, 'DE');
console.log(deadline); // Correctly skips German public holidays

Count Business Days Between Two Dates

This is useful for billing cycles, SLA reporting, and project planning:

countBetween.js
async function businessDaysBetween(start, end, country = 'US') {
  const res = await fetch(
    `${BASE_URL}/v1/between?start=${start}&end=${end}&country=${country}`,
    { headers: { Authorization: `Bearer ${API_KEY}` } }
  );
  const json = await res.json();
  return json.data.workdays;
}

// Working days in Q1 2026 for the US
const count = await businessDaysBetween('2026-01-01', '2026-03-31', 'US');
console.log(`Q1 2026: ${count} working days`);

Batch Processing with a Single Request

If you need to check multiple dates at once, the batch endpoint lets you process up to 100 dates in a single API call:

batchCheck.js
async function batchCheck(dates, country = 'US') {
  const res = await fetch(`${BASE_URL}/v1/batch`, {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      operation: 'check',
      country,
      dates,
    }),
  });
  const json = await res.json();
  return json.data.results;
}

// Check an entire week at once
const results = await batchCheck([
  '2026-03-09', '2026-03-10', '2026-03-11',
  '2026-03-12', '2026-03-13',
], 'US');
console.log(results);

TypeScript Support

If you are using TypeScript, you can add type safety to your API calls with a simple wrapper:

bizday-client.ts
interface CheckResponse {
  success: true;
  data: {
    date: string;
    country: string;
    is_workday: boolean;
    reason?: string;
    holiday?: { name: string; local_name: string; type: string };
  };
}

interface AddResponse {
  success: true;
  data: {
    start_date: string;
    country: string;
    workdays_added: number;
    result_date: string;
    weekends_skipped: number;
    holidays_skipped: string[];
  };
}

async function checkDate(date: string, country: string): Promise<CheckResponse> {
  const res = await fetch(
    `${BASE_URL}/v1/check?date=${date}&country=${country}`,
    { headers: { Authorization: `Bearer ${API_KEY}` } }
  );
  return res.json();
}

Node.js, Deno, and Edge Runtimes

Because the BizDay API uses standard HTTP, it works in any JavaScript runtime that supports fetch. That includes Node.js 18+, Deno, Bun, Cloudflare Workers, and Vercel Edge Functions. There is no client library to install and no dependencies to manage.

When to Use a Library vs. an API

JavaScript libraries like date-fns and Luxon are excellent for date arithmetic, but they do not ship holiday data. You can combine them with a holiday dataset, but then you own the maintenance of that dataset. An API makes sense when:

Getting Started

The BizDay API has a free tier with 10,000 requests per month. No credit card required. You can get an API key in seconds and start making requests from any JavaScript environment. Check the full documentation for all available endpoints, parameters, and response formats.