Как можно вычислить разницу между датами в рабочих днях?

Разницу между датами в рабочих днях можно вычислить, используя библиотеку datetime и модуль calendar (или специализированную библиотеку, например, pandas или workdays):


import datetime
import calendar

def working_days_difference(start_date, end_date):
  """Вычисляет количество рабочих дней между двумя датами."""
  total_days = (end_date - start_date).days + 1 # Включаем конечную дату
  working_days = 0
  for i in range(total_days):
    current_date = start_date + datetime.timedelta(days=i)
    if calendar.weekday(current_date.year, current_date.month, current_date.day) < 5: # 0-4: пн-пт
      working_days += 1
  return working_days

# Пример использования:
start = datetime.date(2023, 10, 26)
end = datetime.date(2023, 11, 10)
diff = working_days_difference(start, end)
print(f"Количество рабочих дней: {diff}")
  

Этот код перебирает все дни между датами и проверяет, является ли день рабочим (понедельник-пятница).

Альтернативный подход (с `pandas`):


import pandas as pd

def working_days_difference_pandas(start_date, end_date):
  """Вычисляет количество рабочих дней между двумя датами, используя pandas."""
  dates = pd.date_range(start_date, end_date, freq='B') # 'B' означает только бизнес-дни
  return len(dates)

# Пример использования:
start = pd.to_datetime('2023-10-26').date() # Преобразуем в datetime.date
end = pd.to_datetime('2023-11-10').date()  # Преобразуем в datetime.date

diff = working_days_difference_pandas(start, end)
print(f"Количество рабочих дней: {diff}")

    

Использование `pandas` обычно быстрее и позволяет более гибко учитывать праздничные дни (путем передачи списка праздников в `pd.date_range`).


Для вычисления разницы между датами в рабочих днях на Python можно использовать несколько подходов. Наиболее распространенные и эффективные решения включают использование модуля datetime и библиотеки holidays. Вот несколько вариантов с объяснениями и примерами кода:

1. Использование datetime и простого цикла:

Этот подход предполагает итерацию по дням между двумя датами и проверку, является ли каждый день рабочим (не выходным).


import datetime

def calculate_working_days(start_date, end_date):
  """
  Вычисляет количество рабочих дней между двумя датами (исключая выходные - суббота и воскресенье).
  """
  if start_date > end_date:
    start_date, end_date = end_date, start_date # Swap if start_date is after end_date

  total_days = (end_date - start_date).days + 1
  working_days = 0
  for i in range(total_days):
    current_date = start_date + datetime.timedelta(days=i)
    if current_date.weekday() < 5:  # 0-4: Monday-Friday
      working_days += 1
  return working_days

# Пример использования
start_date = datetime.date(2023, 10, 26)
end_date = datetime.date(2023, 11, 10)
working_days = calculate_working_days(start_date, end_date)
print(f"Количество рабочих дней между {start_date} и {end_date}: {working_days}")

Плюсы: Простота реализации.

Минусы: Не учитывает праздничные дни; неэффективно для больших интервалов дат.

2. Использование datetime и списочных включений (List Comprehension):

Более компактная версия предыдущего подхода.


import datetime

def calculate_working_days_comprehension(start_date, end_date):
    if start_date > end_date:
        start_date, end_date = end_date, start_date

    dates = [start_date + datetime.timedelta(days=i) for i in range((end_date - start_date).days + 1)]
    working_days = sum(1 for date in dates if date.weekday() < 5)
    return working_days

# Пример использования
start_date = datetime.date(2023, 10, 26)
end_date = datetime.date(2023, 11, 10)
working_days = calculate_working_days_comprehension(start_date, end_date)
print(f"Количество рабочих дней между {start_date} и {end_date}: {working_days}")

Плюсы: Более компактный код.

Минусы: Не учитывает праздничные дни; создает временный список, что может быть неэффективно для больших интервалов.

3. Использование библиотеки holidays для учета праздников:

Библиотека holidays позволяет получить список праздников для конкретной страны или региона. Это позволяет точно вычислить рабочие дни, исключая как выходные, так и праздники.


import datetime
import holidays

def calculate_business_days(start_date, end_date, country='RU'): # Default country is Russia
    """
    Вычисляет количество рабочих дней между двумя датами, исключая выходные и праздники.
    """
    if start_date > end_date:
        start_date, end_date = end_date, start_date

    country_holidays = holidays.CountryHoliday(country, years=start_date.year)

    total_days = (end_date - start_date).days + 1
    business_days = 0
    for i in range(total_days):
        current_date = start_date + datetime.timedelta(days=i)
        if current_date.weekday() < 5 and current_date not in country_holidays:
            business_days += 1
    return business_days

# Пример использования
start_date = datetime.date(2023, 10, 26)
end_date = datetime.date(2023, 11, 10)
business_days = calculate_business_days(start_date, end_date, country='RU')
print(f"Количество рабочих дней между {start_date} и {end_date}: {business_days}")

# Чтобы установить holidays: pip install holidays

Плюсы: Учитывает праздничные дни, что дает более точный результат.

Минусы: Требуется установка дополнительной библиотеки (holidays); может быть медленнее для очень больших диапазонов дат.

4. Использование `numpy` и `busdaycalendar`:

Для очень больших диапазонов дат, `numpy` с его `busdaycalendar` может быть более производительным.


import datetime
import numpy as np

def calculate_business_days_numpy(start_date, end_date, holidays=[]):
    """
    Вычисляет количество рабочих дней между двумя датами, исключая выходные и список праздников.
    Использует numpy.busday_count.
    """
    if start_date > end_date:
        start_date, end_date = end_date, start_date

    bus_days = np.busday_count(start_date, end_date, holidays=holidays) # end_date is exclusive

    return bus_days

# Пример использования
start_date = datetime.date(2023, 10, 26)
end_date = datetime.date(2023, 11, 10)

# Add some sample holidays for demonstration
holidays_list = [datetime.date(2023, 11, 3), datetime.date(2023, 11, 6)] # Replace with actual holiday dates

business_days = calculate_business_days_numpy(start_date, end_date, holidays=holidays_list)
print(f"Количество рабочих дней между {start_date} и {end_date}: {business_days}")

# Чтобы установить numpy: pip install numpy

Плюсы: Высокая производительность, особенно для больших диапазонов дат. Легко интегрировать список праздников.

Минусы: Требует установки дополнительной библиотеки (numpy); немного менее читаемый код.

Выбор подходящего метода:

  • Если вам не нужно учитывать праздничные дни и важна простота, используйте первый или второй метод.
  • Если важна точность и необходимо учитывать праздничные дни, используйте библиотеку holidays (третий метод). Убедитесь, что выбранная страна поддерживается библиотекой.
  • Если важна производительность и работаете с большими интервалами дат, рассмотрите использование numpy (четвертый метод).
0