在给定日期添加n个工作日,忽略python中的假日和周末

cyb*_*ain 18 python datetime

我正在尝试将n(整数)工作日添加到给定日期,添加日期必须避免假期和周末(它不包括在工作日内)

omz*_*omz 17

跳过周末很容易做到这样的事情:

import datetime
def date_by_adding_business_days(from_date, add_days):
    business_days_to_add = add_days
    current_date = from_date
    while business_days_to_add > 0:
        current_date += datetime.timedelta(days=1)
        weekday = current_date.weekday()
        if weekday >= 5: # sunday = 6
            continue
        business_days_to_add -= 1
    return current_date

#demo:
print '10 business days from today:'
print date_by_adding_business_days(datetime.date.today(), 10)
Run Code Online (Sandbox Code Playgroud)

假期的问题在于它们因国家或地区,宗教等而有很大差异.您需要一个列表/一组假期用于您的用例,然后以类似的方式跳过它们.起点可能是Apple为iCal发布的日历源(采用ics格式),美国的日历源是http://files.apple.com/calendars/US32Holidays.ics

您可以使用icalendar模块来解析它.


Jon*_*nts 12

如果您不介意使用第三方库,则dateutil非常方便

from dateutil.rrule import *
print "In 4 business days, it's", rrule(DAILY, byweekday=(MO,TU,WE,TH,FR))[4]
Run Code Online (Sandbox Code Playgroud)

您还可以查看rruleset并使用.exdate()提供假期以跳过计算中的假期,并且可选择cache避免重新计算可能值得查看的选项.


Aar*_*lla 6

没有真正的捷径可以做到这一点.试试这种方法:

  1. 创建一个类,该类具有skip(self, d)返回True应跳过的日期的方法.
  2. 在类中创建一个包含所有假日作为日期对象的字典.不要使用datetime或类似,因为一天的分数会杀了你.
  3. 返回True字典中的任何日期或d.weekday() >= 5

要添加N天,请使用以下方法:

def advance(d, days):
    delta = datetime.timedelta(1)

    for x in range(days):
        d = d + delta
        while holidayHelper.skip(d):
            d = d + delta

    return d
Run Code Online (Sandbox Code Playgroud)


cyb*_*ain 5

感谢基于omz代码我做了一些小改动......它可能对其他用户有帮助:

import datetime
def date_by_adding_business_days(from_date, add_days,holidays):
    business_days_to_add = add_days
    current_date = from_date
    while business_days_to_add > 0:
        current_date += datetime.timedelta(days=1)
        weekday = current_date.weekday()
        if weekday >= 5: # sunday = 6
            continue
        if current_date in holidays:
            continue
        business_days_to_add -= 1
    return current_date

#demo:
Holidays =[datetime.datetime(2012,10,3),datetime.datetime(2012,10,4)]
print date_by_adding_business_days(datetime.datetime(2012,10,2), 10,Holidays)
Run Code Online (Sandbox Code Playgroud)


roy*_*yal 5

我想要一个不是O(N)的解决方案,它看起来像一个有趣的代码高尔夫.如果有人感兴趣的话,这就是我所说的.适用于正数和负数.如果我错过任何事情,请告诉我.

def add_business_days(d, business_days_to_add):
    num_whole_weeks  = business_days_to_add / 5
    extra_days       = num_whole_weeks * 2

    first_weekday    = d.weekday()
    remainder_days   = business_days_to_add % 5

    natural_day      = first_weekday + remainder_days
    if natural_day > 4:
        if first_weekday == 5:
            extra_days += 1
        elif first_weekday != 6:
            extra_days += 2

    return d + timedelta(business_days_to_add + extra_days)
Run Code Online (Sandbox Code Playgroud)