Skip to main content

Python Pandas: How to Get Business Days Between Two Dates (Excluding Weekends/Holidays)

Calculating the number of business days between two dates is a common task in financial analysis, project management, and many other business applications. Pandas provides powerful tools for date and time manipulation, including functions to easily generate ranges of business days, optionally excluding weekends and specific holidays.

This guide demonstrates how to use pandas.bdate_range() and pandas.date_range() to find business days, and how to incorporate holiday calendars for more accurate calculations.

What Are Business Days in Pandas?

By default, Pandas considers "business days" to be Monday through Friday. Standard functions for business day ranges will automatically exclude Saturdays and Sundays. However, they do not inherently exclude national or regional holidays unless you explicitly provide a holiday calendar.

Example Date Strings: For our examples, we'll use string representations of dates, which Pandas can parse.

import pandas as pd

start_date_str = '2023-12-18' # A Monday
end_date_str = '2023-12-27' # A Wednesday (includes Christmas)

The pandas.bdate_range(start=None, end=None, periods=None, freq='B', tz=None, normalize=False, name=None, inclusive='both', **kwargs) function is specifically designed to return a fixed frequency DatetimeIndex with business day frequency by default.

Basic Usage (Excludes Weekends)

This will generate a DatetimeIndex containing all weekdays (Mon-Fri) between start_date_str and end_date_str, inclusive.

import pandas as pd

start_date_str = '2023-08-16' # Wednesday
end_date_str = '2023-08-21' # Monday

# Get business days between two dates (inclusive by default)
business_days_index = pd.bdate_range(start=start_date_str, end=end_date_str)

print("Business days using pd.bdate_range():")
print(business_days_index)

# Get the count of business days
num_business_days = len(business_days_index)
print(f"Number of business days: {num_business_days}") # Output: 4

Output:

Business days using pd.bdate_range():
DatetimeIndex(['2023-08-16', '2023-08-17', '2023-08-18', '2023-08-21'], dtype='datetime64[ns]', freq='B')
Number of business days: 4
  • freq='B' is the default frequency for bdate_range, signifying business day frequency.
  • Aug 19th (Sat) and Aug 20th (Sun) are excluded.

Controlling Inclusivity of Start/End Dates

The inclusive parameter determines whether the start and end dates are included in the range.

  • "both" (default): Includes both start and end dates if they are business days.
  • "neither": Excludes both start and end dates.
  • "left": Includes the start date, excludes the end date.
  • "right": Excludes the start date, includes the end date.
import pandas as pd

start_date_str = '2023-08-16' # Wednesday
end_date_str = '2023-08-21' # Monday

business_days_neither = pd.bdate_range(
start=start_date_str,
end=end_date_str,
inclusive='neither'
)
print("Business days (inclusive='neither'):")
print(business_days_neither)
print(f"Number of business days (neither): {len(business_days_neither)}") # Output: 2

Output:

Business days (inclusive='neither'):
DatetimeIndex(['2023-08-17', '2023-08-18'], dtype='datetime64[ns]', freq='B')
Number of business days (neither): 2

Method 2: Using pandas.date_range() with freq='B'

The more general pandas.date_range(start=None, end=None, periods=None, freq=None, ...) function can also generate business day ranges by setting its freq parameter to 'B'.

Basic Usage (Excludes Weekends)

This behaves similarly to bdate_range with default inclusivity.

import pandas as pd

start_date_str = '2023-09-27' # Wednesday
end_date_str = '2023-10-02' # Monday (Sept 30 is Sat, Oct 1 is Sun)

# Get business days using pd.date_range with freq='B'
business_days_dr = pd.date_range(start=start_date_str, end=end_date_str, freq='B')

print("Business days using pd.date_range(freq='B'):")
print(business_days_dr)
print(f"Number of business days: {len(business_days_dr)}") # Output: 4

Output:

Business days using pd.date_range(freq='B'):
DatetimeIndex(['2023-09-27', '2023-09-28', '2023-09-29', '2023-10-02'], dtype='datetime64[ns]', freq='B')
Number of business days: 4
  • freq='B' specifically requests business day frequency.
  • date_range also has an inclusive parameter (added in pandas 1.4.0, defaults to "both" if start and end are provided).

Excluding National Holidays

Standard business day calculations (freq='B') only exclude weekends (Sat, Sun). To exclude specific holidays, you need to use a CustomBusinessDay offset with a holiday calendar.

Using CustomBusinessDay with a Holiday Calendar

Pandas provides some built-in holiday calendars (e.g., for US federal holidays) and allows you to create custom ones.

Example: US Federal Holidays

Let's find business days in a week that includes Thanksgiving (a US federal holiday).

import pandas as pd
from pandas.tseries.holiday import USFederalHolidayCalendar # Import the calendar
from pandas.tseries.offsets import CustomBusinessDay # Import the custom offset

start_date_holiday_period = '2023-11-20' # Monday
end_date_holiday_period = '2023-11-24' # Friday
# Thanksgiving in the US is on Thursday, Nov 23, 2023.

# Create a custom business day frequency that observes US federal holidays
us_bus_day = CustomBusinessDay(calendar=USFederalHolidayCalendar())

# Use this custom frequency with bdate_range (or date_range)
business_days_excl_holidays = pd.bdate_range(
start=start_date_holiday_period,
end=end_date_holiday_period,
freq=us_bus_day # Use the custom frequency
)

print("Business days excluding US Federal Holidays:")
print(business_days_excl_holidays)
print(f"Number of business days (excl. Thanksgiving): {len(business_days_excl_holidays)}") # Output: 4

Output:

Business days excluding US Federal Holidays:
DatetimeIndex(['2023-11-20', '2023-11-21', '2023-11-22', '2023-11-24'], dtype='datetime64[ns]', freq='C')
Number of business days (excl. Thanksgiving): 4
  • USFederalHolidayCalendar(): Provides a list of US federal holiday dates.
  • CustomBusinessDay(calendar=...): Creates a frequency offset that respects both weekends and the specified holiday calendar.
  • Notice that 2023-11-23 (Thanksgiving) is correctly excluded from the result.
  • Pandas has other built-in calendars, and you can define your own AbstractHolidayCalendar for custom holidays.

Getting the Count of Business Days

Once you have the DatetimeIndex of business days, simply use the built-in len() function to get the number of business days in that range.

count_with_holidays = len(business_days_excl_holidays)
print(f"The count of business days (excluding holidays) is: {count_with_holidays}") # Output: 4

Conclusion

Pandas provides convenient and powerful tools for working with business days:

  • Use pd.bdate_range(start, end) or pd.date_range(start, end, freq='B') to generate a DatetimeIndex of business days (Mon-Fri) between two dates.
  • The len() of the resulting DatetimeIndex gives you the count of business days.
  • To exclude specific holidays, create a CustomBusinessDay offset using a holiday calendar (e.g., USFederalHolidayCalendar) and pass it as the freq argument to bdate_range or date_range.
  • The inclusive parameter in bdate_range (and more recently in date_range) allows fine-grained control over whether the start and end dates are included in the generated range.

By leveraging these Pandas features, you can accurately calculate business day ranges and counts for various analytical and scheduling tasks.