我试图将n(整数)个工作日添加到给定日期,日期添加必须避免假期和周末(它不包含在工作日)将n个工作日添加到给定日期,而忽略python中的假期和周末
回答
跳绳周末会很容易做这样的事情:
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)
假期的问题在于,它们因国家或地区,宗教等因素而异。为您的用例预留一个列表/一组假期,然后以类似的方式跳过它们。一个出发点可能是苹果发布的的iCal(在ICS格式)日历的饲料,一对美国将是http://files.apple.com/calendars/US32Holidays.ics
您可以使用icalendar模块来解析这一点。基于OMZ代码
这将需要一些工作,因为在任何图书馆中没有任何定义的假期构造(据我所知至少)。您将需要创建自己的枚举。
通过在您的datetime对象上调用.weekday() < 6
可以轻松地检查周末日期。
没有真正的捷径来做到这一点。试试这个办法:
- 创建具有方法
skip(self, d)
这对于应该跳过日期返回True
类。 - 在包含所有假期的课程中创建一本词典为date objects。不要使用
datetime
或类似的因为一天中的一小部分会杀死你。任何日期 - 返回
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
你的回答是有用的,但我不能标记:(我没有足够的声望点!!谢谢! – cyberbrain
谢谢,我做了一些变化不大......这为其他用户也许有所帮助:
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)
如果你不介意使用第三方库,然后dateutil是得心应手
from dateutil.rrule import *
print "In 4 business days, it's", rrule(DAILY, byweekday=(MO,TU,WE,TH,FR))[4]
您还可以查看rruleset
并使用.exdate()
提供假期以跳过计算中的假期,并且可以选择cache
选项以避免重新计算,这可能值得您考虑。
看起来像可能会有提供这种支持的'dateutil'的扩展:https://pypi.python.org/pypi/bdateutil/0.1 – Blairg23
or pandas:https://stackoverflow.com/a/19036752/2097 – BlackShift
我想要一个不是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)
希望这会有所帮助。这不是O(N)
,而是O(holidays)
。此外,假期只适用于偏移量为正数的情况。
def add_working_days(start, working_days, holidays=()):
"""
Add working_days to start start date , skipping weekends and holidays.
:param start: the date to start from
:type start: datetime.datetime|datetime.date
:param working_days: offset in working days you want to add (can be negative)
:type working_days: int
:param holidays: iterator of datetime.datetime of datetime.date instances
:type holidays: iter(datetime.date|datetime.datetime)
:return: the new date wroking_days date from now
:rtype: datetime.datetime
:raise:
ValueError if working_days < 0 and holidays
"""
assert isinstance(start, (datetime.date, datetime.datetime)), 'start should be a datetime instance'
assert isinstance(working_days, int)
if working_days < 0 and holidays:
raise ValueError('Holidays and a negative offset is not implemented. ')
if working_days == 0:
return start
# first just add the days
new_date = start + datetime.timedelta(working_days)
# now compensate for the weekends.
# the days is 2 times plus the amount of weeks are included in the offset added to the day of the week
# from the start. This compensates for adding 1 to a friday because 4+1 // 5 = 1
new_date += datetime.timedelta(2 * ((working_days + start.weekday()) // 5))
# now compensate for the holidays
# process only the relevant dates so order the list and abort the handling when the holiday is no longer
# relevant. Check each holiday not being in a weekend, otherwise we don't mind because we skip them anyway
# next, if a holiday is found, just add 1 to the date, using the add_working_days function to compensate for
# weekends. Don't pass the holiday to avoid recursion more then 1 call deep.
for hday in sorted(holidays):
if hday < start:
# ignore holidays before start, we don't care
continue
if hday.weekday() > 4:
# skip holidays in weekends
continue
if hday <= new_date:
# only work with holidays up to and including the current new_date.
# increment using recursion to compensate for weekends
new_date = add_working_days(new_date, 1)
else:
break
return new_date
- 1. 如何在不包含周末和节假日的日期中添加日期
- 2. 如何在跳过周末和其他节假日的同时将日期添加到日期中,并且开始日期是周末或假日
- 3. 不要指望给定节假日或周末两个日期
- 4. 将两个工作日添加到排除假期日期的日期排列
- 5. 将日期添加到日期但不包括周末
- 6. 日期时间C#得到一个10天的周期工作有例外(周末和假日)
- 7. 在R中为数据框中的日期添加日期,无需周末和某些特定节假日
- 8. 得到工作日和周末的计数从给出两个日期在PHP
- 9. SQL更换日期值,如果日期是假期或周末
- 10. 确定日期是周日/周末java
- 11. 在Shopify中添加日期以排除周末日期
- 12. MYSQL将工作日添加到日期
- 13. 如何在日期中添加天数,只考虑工作日(即忽略周末)?
- 14. 添加天后选择日期不包括周末和节假日
- 15. 获取日期到周末
- 16. 按连续日期分组,忽略SQL中的周末
- 17. 将日期添加到特定日期
- 18. 计算日期给出两个日期不包括周末
- 19. 选择日期+ 3天,不包括周末和节假日
- 20. 如何在跳过周末和其他节假日的情况下向日期添加若干日期
- 21. 绕过周末和特定日期的日期函数
- 22. Java将毫秒添加到毫秒时间戳省略周末和节假日
- 23. 周末,假期计数两个日期之间没有迭代
- 24. 如何避免在日期中添加或减少日期的周末或节假日
- 25. 计算工作日,包括Python中两个日期列的自定义假期
- 26. 工作日添加到新的日期
- 27. R:周末或银行假期的填充日期
- 28. Sql计算两个日期之间的天数,不包括周末和假日表中的日期
- 29. JExcelAPI - 将日期写入Excel工作表忽略日期,月份和年份
- 30. 将工作日添加到开始日期以创建结束日期(包括银行假期)
你能告诉我们你到目前为止试过的东西 - 还有,你希望代码如何工作?一个函数?或者干脆怎么做? –
你必须硬编码的假期日期(我想无论如何) –