Рабочие дни в Python
Мне нужно вычесть рабочие дни с текущей даты.
В настоящее время у меня есть код, который нужно всегда запускать в последний рабочий день. Так может быть и сегодня, если мы с понедельника по пятницу, но если это суббота или воскресенье, то мне нужно вернуть его в пятницу до уик-энда. В настоящее время у меня есть довольно красивый неуклюжий код:
lastBusDay = datetime.datetime.today()
if datetime.date.weekday(lastBusDay) == 5: #if it Saturday
lastBusDay = lastBusDay - datetime.timedelta(days = 1) #then make it Friday
elif datetime.date.weekday(lastBusDay) == 6: #if it Sunday
lastBusDay = lastBusDay - datetime.timedelta(days = 2); #then make it Friday
Есть ли лучший способ?
Можно ли сказать timedelta работать в будние дни, а не календарные дни, например?
Ответы
Ответ 1
Используйте pandas!
import pandas as pd
# BDay is business day, not birthday...
from pandas.tseries.offsets import BDay
# pd.datetime is an alias for datetime.datetime
today = pd.datetime.today()
print today - BDay(4)
С сегодняшнего дня, четверг, 26 сентября, вы получите результат:
datetime.datetime(2013, 9, 20, 14, 8, 4, 89761)
Ответ 2
Кажется, есть несколько вариантов, если вы открыты для установки дополнительных библиотек.
В этом сообщении описывается способ определения рабочих дней с dateutil.
http://coding.derkeiler.com/Archive/Python/comp.lang.python/2004-09/3758.html
BusinessHours позволяет настраивать свой список праздников и т.д., чтобы определить, когда ваши рабочие часы (и по продолжительности рабочих дней).
http://pypi.python.org/pypi/BusinessHours/
Ответ 3
DISCLAMER: Я автор...
Я написал пакет, который делает именно это, расчеты бизнес-дат. Вы можете использовать пользовательские спецификации недели и праздники.
У меня была эта точная проблема при работе с финансовыми данными, и я не нашел ни одного из доступных решений, поэтому я написал один.
Надеюсь, это полезно для других людей.
https://pypi.python.org/pypi/business_calendar/
Ответ 4
Возможно, этот код может помочь:
lastBusDay = datetime.datetime.today()
shift = datetime.timedelta(max(1,(lastBusDay.weekday() + 6) % 7 - 3))
lastBusDay = lastBusDay - shift
Идея заключается в том, что по понедельникам вам нужно вернуться 3 дня, по воскресеньям 2 и 1 в любой другой день.
Заявление (lastBusDay.weekday() + 6) % 7
просто восстанавливает понедельник с 0 до 6.
На самом деле не знаю, будет ли это лучше с точки зрения производительности.
Ответ 5
Это даст генератор рабочих дней, конечно, без праздников, stop - это объект datetime.datetime. Если вам нужны праздники, просто добавьте дополнительный аргумент со списком праздников и проверьте с помощью "IFology"; -)
def workingdays(stop, start=datetime.date.today()):
while start != stop:
if start.weekday() < 5:
yield start
start += datetime.timedelta(1)
Позже вы можете считать их
workdays = workingdays(datetime.datetime(2015, 8, 8))
len(list(workdays))
Ответ 6
timeboard
пакет делает это.
Предположим, что ваша дата 04 сентября 2017. Несмотря на то, что в понедельник это был праздник в США (День труда). Итак, последний рабочий день был в пятницу, 1 сентября.
>>> import timeboard.calendars.US as US
>>> clnd = US.Weekly8x5()
>>> clnd('04 Sep 2017').rollback().to_timestamp().date()
datetime.date(2017, 9, 1)
В Великобритании, 04 сентября 2017 года был обычный рабочий день, поэтому самый последний рабочий день сам был.
>>> import timeboard.calendars.UK as UK
>>> clnd = UK.Weekly8x5()
>>> clnd('04 Sep 2017').rollback().to_timestamp().date()
datetime.date(2017, 9, 4)
ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: Я являюсь автором расписания.
Ответ 7
Почему бы вам не попробовать что-то вроде:
lastBusDay = datetime.datetime.today()
if datetime.date.weekday(lastBusDay) not in range(0,5):
lastBusDay = 5
Ответ 8
def getNthBusinessDay(startDate, businessDaysInBetween):
currentDate = startDate
daysToAdd = businessDaysInBetween
while daysToAdd > 0:
currentDate += relativedelta(days=1)
day = currentDate.weekday()
if day < 5:
daysToAdd -= 1
return currentDate