Как рассчитать дату назад от другой даты с заданным количеством рабочих дней - PullRequest
2 голосов
/ 21 августа 2009

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

Пример: у меня есть дата 2009-08-21 и число 18 рабочих дней в качестве параметра, и правильный ответ должен быть 2009-07-27.

спасибо за любую помощь

Ответы [ 8 ]

2 голосов
/ 21 августа 2009

Вот один из способов сделать это. Примечание (1) вы не говорите, что ожидаете, если дата начала НЕ является рабочим днем. (2) Ваш пример неверен.

C:\junk\so>type workdays.py
import datetime

def add_workdays(adate, nworkdays):
    if nworkdays < 0:
        incr = -1
        nworkdays = - nworkdays
    else:
        incr = 1
    delta_weeks, delta_days = divmod(nworkdays, 5)
    one_day = datetime.timedelta(days=incr)
    if delta_weeks:
        wdate = adate + one_day * 7 * delta_weeks
    else:
        wdate = adate
    while delta_days:
        wdate += one_day
        if wdate.weekday() < 5: # Mon-Fri
            delta_days -= 1
    return wdate

if __name__ == "__main__":
    start = datetime.date(2009, 8, 21)
    for i in range(10, -19, -1):
        end = add_workdays(start, i)
        print "%3d %s" % (i, end.strftime("%a %Y-%m-%d"))

C:\junk\so>\python26\python workdays.py
 10 Fri 2009-09-04
  9 Thu 2009-09-03
  8 Wed 2009-09-02
  7 Tue 2009-09-01
  6 Mon 2009-08-31
  5 Fri 2009-08-28
  4 Thu 2009-08-27
  3 Wed 2009-08-26
  2 Tue 2009-08-25
  1 Mon 2009-08-24
  0 Fri 2009-08-21
 -1 Thu 2009-08-20
 -2 Wed 2009-08-19
 -3 Tue 2009-08-18
 -4 Mon 2009-08-17
 -5 Fri 2009-08-14
 -6 Thu 2009-08-13
 -7 Wed 2009-08-12
 -8 Tue 2009-08-11
 -9 Mon 2009-08-10
-10 Fri 2009-08-07
-11 Thu 2009-08-06
-12 Wed 2009-08-05
-13 Tue 2009-08-04
-14 Mon 2009-08-03
-15 Fri 2009-07-31
-16 Thu 2009-07-30
-17 Wed 2009-07-29
-18 Tue 2009-07-28

C:\junk\so>
2 голосов
/ 21 августа 2009

Предлагаю взглянуть на http://docs.python.org/library/calendar.html с его помощью вы можете легко определить, какой день недели является определенной датой, а затем рассчитать обратно - с учетом выходных

1 голос
/ 02 декабря 2012

Если вы используете панд , вы можете сделать это легко:

from pandas.tseries.offsets import BDay
import datetime

datetime.datetime(2009, 8, 21) - 18 * BDay()
1 голос
/ 21 августа 2009

Я рекомендую использовать серию scikits с частотой «бизнес». Вы можете скачать этот отличный пакет Python здесь:

http://pytseries.sourceforge.net/

Тогда вы можете написать что-то вроде

import datetime
import scikits.timeseries as TS
workDay1 = TS.Date(freq='B', datetime=datetime.datetime(2009,8,21))
workDay2 = workDay1 - 7
asDatetime = workDay2.datetime
0 голосов
/ 21 августа 2009

У моей жены Анны есть рецепт для этого во 2-м изд. поваренной книги Python - вы можете прочитать ее в Интернете с помощью этого Поиска книг Google url , он начинается с p. 122. Рецепт 3.5 - по будням против выходных; следующий рецепт, 3.6, добавляет рассмотрение праздников, но, к сожалению, его можно только частично прочитать в Интернете в Поиске книг Google (я видел много пиратских копий нашей книги, рекламируемых для бесплатных загрузок, но у них нет удобных URL-адресов).

Эти рецепты особенно близки и дороги для наших сердец, потому что они, в основном, связаны с тем, как мы воссоединились (в Интернете) после многих лет, когда мы теряли друг друга - Анна искала помощь в совершенствовании их, поскольку она нуждалась в их функциональность на ее рабочем месте мне предложили немного ... через 20 месяцев мы поженились; -).

0 голосов
/ 21 августа 2009

Если вам нужно в какой-то момент считать праздничные дни нерабочими днями, вам нужно определиться с Пасхой / Страстной пятницей, которую лучше оставить в библиотеке:

>>> from dateutil import easter<br/> >>> easter.easter(2009)<br/> datetime.date(2009, 4, 12)

Другие крупные праздники относительно просты: они либо встречаются в один и тот же день каждый год, либо выпадают на очередной день недели в месяце. Возможно, вы захотите проверить period.py (http://www.medsch.wisc.edu/~annis/creations/period.py.html), который предлагает метод is_holiday (), хотя он требует настройки.

Выходные на фондовом рынке NYSE предоставляют разумный график выходных по умолчанию для Соединенных Штатов.

0 голосов
/ 21 августа 2009

Я предполагаю, что вы используете datetime, но это должно работать (date - это datetime, days - целое число):

def goback(date, days):
    delta = datetime.timedelta( days=days + 2*(days//5) )
    if date.weekday() == 5:
        delta += datetime.timedelta(days=1)
    elif date.weekday() == 6:
        delta += datetime.timedelta(days=2)
    else:
        leftover = date.weekday() - days % 5
        if leftover < 0: 
            delta += datetime.timedelta(days=2)
    return date - delta

Обратите внимание, что пример в вашем описании неверен, я думаю. , , 18 рабочих дней до 21-го - 28-го.

0 голосов
/ 21 августа 2009

Я бы, вероятно, просто перебрал бы дни, проверяя, является ли день понедельник-пятница.
Не так эффективно, но легче получить право.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...