Python中最近的前一个工作日

Python中最近的前一个工作日,python,datetime,Python,Datetime,我需要从当前日期中减去工作日 我目前有一些代码,需要总是在最近的工作日运行。如果我们是周一到周五,那可能是今天,但是如果是周六或周日,那么我需要把它放回周末之前的周五。我目前有一些相当笨重的代码来执行此操作: lastBusDay = datetime.datetime.today() if datetime.date.weekday(lastBusDay) == 5: #if it's Saturday lastBusDay = lastBusDay - datetim

我需要从当前日期中减去工作日

我目前有一些代码,需要总是在最近的工作日运行。如果我们是周一到周五,那可能是今天,但是如果是周六或周日,那么我需要把它放回周末之前的周五。我目前有一些相当笨重的代码来执行此操作:

 lastBusDay = datetime.datetime.today()
 if datetime.date.weekday(lastBusDay) == 5:      #if it's Saturday
     lastBusDay = lastBusDay - datetime.timedelta(days = 1) #then make it Friday
 elif datetime.date.weekday(lastBusDay) == 6:      #if it's Sunday
     lastBusDay = lastBusDay - datetime.timedelta(days = 2); #then make it Friday
有更好的办法吗


例如,我可以告诉timedelta在工作日而不是日历日工作吗

如果您愿意安装额外的库,似乎有几种选择

这篇文章描述了一种定义工作日的方法

BusinessHours允许您自定义假期列表等,以定义您的工作时间(以及延长的工作日)是什么时候


也许这段代码可以帮助:

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


我真的不知道这是否会在性能方面更好。

为什么不试试以下方法:

lastBusDay = datetime.datetime.today()
if datetime.date.weekday(lastBusDay) not in range(0,5):
    lastBusDay = 5
使用熊猫

import datetime
# BDay is business day, not birthday...
from pandas.tseries.offsets import BDay

today = datetime.datetime.today()
print(today - BDay(4))
由于今天是9月26日,星期四,这将为您提供以下输出:

datetime.datetime(2013, 9, 20, 14, 8, 4, 89761)
def getNthBusinessDay(开始日期,开始日期之间):
当前日期=开始日期
daysToAdd=businessDaysInBetween
当daysToAdd>0时:
currentDate+=relativedelta(天数=1)
day=currentDate.weekday()
如果第5天<5天:
daysToAdd-=1
返回当前日期

DISCLAMER:我是作者

我写了一个软件包,就是这样的,业务日期计算。您可以使用自定义的周规格和假日

我在处理金融数据时遇到了这个问题,没有发现任何可用的解决方案特别容易,所以我写了一个

希望这对其他人有用


这将生成一个工作日生成器,当然没有节假日,stop是datetime.datetime对象。如果你需要假期,只需用假期列表进行额外的论证,并与“iFoology”核对即可;-)

软件包就是这样做的

假设您的日期是2017年9月4日。尽管是星期一,但在美国却是假日(劳动节)。因此,最近的一个工作日是9月1日星期五

>>> import timeboard.calendars.US as US
>>> clnd = US.Weekly8x5()
>>> clnd('04 Sep 2017').rollback().to_timestamp().date()
datetime.date(2017, 9, 1)
在英国,2017年9月4日是正常的工作日,因此最近的工作日就是它自己

>>> import timeboard.calendars.UK as UK
>>> clnd = UK.Weekly8x5()
>>> clnd('04 Sep 2017').rollback().to_timestamp().date()
datetime.date(2017, 9, 4)

免责声明:我是timeboard的作者。

如果您想跳过我们的假期和周末,这对我很有用(使用pandas 0.23.3):

要转换为python日期对象,我执行了以下操作:

result.to_pydatetime().date()

另一个简化版本

lastBusDay=datetime.datetime.today()
工作日=日期时间.日期.工作日(lastBusDay)
如果工作日>4:如果是周六或周日
lastBusDay=lastBusDay-datetime.timedelta(days=wk\u day-4)#然后定在周五

解决方案,无论不同的司法管辖区有不同的假期:

如果需要在表中找到正确的id,可以使用此代码段。表模型是一个sqlalchemy模型,要从中搜索的日期在字段day中

def last_relevant_date(数据库:会话,给定日期:日期)->int:
可用天数=(db.query(Table.id,Table.day)
.订购人(说明(表日))
.limit(100).all())
关闭日期=pd.DataFrame(可用天数)
结束日期['delta']=结束日期['day']-给定日期
过去日期=(结束日期)
.loc[结束日期['delta']

当您必须批量转换时,我不推荐使用此解决方案。由于您没有使用联接,因此它非常通用且昂贵。此外,它假定您有一个相关的日期,该日期是模型表中最近100天中的一天。因此,它可以处理可能具有不同日期的数据输入。

如果有人正在寻找有关假日的解决方案(没有像pandas这样的大型库),请尝试以下功能:

import holidays
import datetime


def previous_working_day(check_day_, holidays=holidays.US()):
    offset = max(1, (check_day_.weekday() + 6) % 7 - 3)
    most_recent = check_day_ - datetime.timedelta(offset)
    if most_recent not in holidays:
        return most_recent
    else:
        return previous_working_day(most_recent, holidays)

check_day = datetime.date(2020, 12, 28)
previous_working_day(check_day)
产生:

datetime.date(2020, 12, 24)

关于假期呢?这里有一个DZONE的片段可能会帮助你:是的,我已经在处理这些问题了:我的数据库总是反作用假期,只要它们在工作日。但我同意,一般来说,假期也是一个问题。我的意思是,我可以开始喜欢使用sckits.timeseries,但我真的想要更简单的东西。你好,我来晚了,对不起。OP可以做的一件简单的事情是检查datetime.date.weekday(lastBusDay)>=5,而不是分别检查周六和周日。但是是的。。无论如何,下面还有其他更好的答案。很好的答案,艾莉森。不幸的是,仍然不是很简单。不过我要走你的路。感谢您的帮助。定义所有文化背景下的工作日不太可能是一个简单到可以包含在标准库中的问题。这是一个正确的观点,因为我的应用程序适用于金融市场,埃及和以色列周日开放。有人甚至使用营业时间吗?在1分钟内,我发现第87行应该是
self.worktimeing[1]
(缺少self),第51行应该是
extradies
(缺少s)。源代码本身看起来很糟糕,分号散布在整个.Nice中。今天,这是正确的答案。当我问问题时,pandas仍然有点不完整。最近的pandas发行版(0.14.0)支持假日日历,安装pandas会为vps增加2.33亿。所以我重新发明了一个无骨的轮子。@EB非常感谢,你的图书馆对我来说非常有用。也许你应该在你的文档中添加,如果你想减去天数,你的库支持负天数,这取决于pipHey,我知道这可能不是联系你的最佳方式,但我只是想报告我在你的业务日历模块中遇到的一个问题。我和联邦政府制定了一个日程表
import pandas as pd
from pandas.tseries.holiday import USFederalHolidayCalendar
from pandas.tseries.offsets import CustomBusinessDay
US_BUSINESS_DAY = CustomBusinessDay(calendar=USFederalHolidayCalendar())
july_5 = pd.datetime(2018, 7, 5)
result = july_5 - 2 * US_BUSINESS_DAY # 2018-7-2
result.to_pydatetime().date()
import holidays
import datetime


def previous_working_day(check_day_, holidays=holidays.US()):
    offset = max(1, (check_day_.weekday() + 6) % 7 - 3)
    most_recent = check_day_ - datetime.timedelta(offset)
    if most_recent not in holidays:
        return most_recent
    else:
        return previous_working_day(most_recent, holidays)

check_day = datetime.date(2020, 12, 28)
previous_working_day(check_day)
datetime.date(2020, 12, 24)