Подтвердить что ты не робот

Рабочие дни в 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 работать в будние дни, а не календарные дни, например?

4b9b3361

Ответ 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