关于datetime:Python中最近的前一个工作日

Most recent previous business day in Python

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

我现在有一些代码需要在最近的工作日运行。如果我们是星期一到星期五,那可能是今天,但是如果是星期六或星期天,我需要把它改回星期五。我现在有一些相当笨拙的代码来做这个:

1
2
3
4
5
 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在工作日而不是日历日工作吗?


使用熊猫!

1
2
3
4
5
6
7
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)

由于今天是9月26日,星期四,您将得到以下输出:

1
datetime.datetime(2013, 9, 20, 14, 8, 4, 89761)


如果您愿意安装额外的库,似乎有几个选项。

本文描述了使用dateutil定义工作日的方法。

http://coding.derkeiler.com/archive/python/comp.lang.python/2004-09/3758.html

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

http://pypi.python.org/pypi/businesshours/


披露者:我是作者…

我写了一个软件包,可以精确计算商业日期。您可以使用自定义周规格和假日。

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

希望这对其他人有用。

https://pypi.python.org/pypi/business_日历/


也许这个代码可以帮助:

1
2
3
lastBusDay = datetime.datetime.today()
shift = datetime.timedelta(max(1,(lastBusDay.weekday() + 6) % 7 - 3))
lastBusDay = lastBusDay - shift

这个想法是在周一你必须回去3天,周日2,和1在任何其他一天。

这份声明只是把星期一从0改为6。

真的不知道这在性能上是否会更好。


timeboard包可以做到这一点。

假设你的日期是2017年9月4日。尽管是星期一,但这是美国的一个假日(劳动节)。所以,最近的工作日是9月1日星期五。

1
2
3
4
>>> 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日是正常的工作日,所以最近的一个工作日就是它自己。

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

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


如果你想跳过美国的假期和周末,这对我很有效(使用熊猫0.23.3):

1
2
3
4
5
6
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

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

1
result.to_pydatetime().date()


这将提供一个工作日生成器,当然没有节假日,stop是datetime.datetime对象。如果您需要假期,只需与假期列表进行额外的讨论,并检查"iFalogy";-)

1
2
3
4
5
def workingdays(stop, start=datetime.date.today()):
    while start != stop:
        if start.weekday() < 5:
            yield start
        start += datetime.timedelta(1)

以后你可以像计算

1
2
workdays = workingdays(datetime.datetime(2015, 8, 8))
len(list(workdays))


1
2
3
4
5
6
7
8
9
10
 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

你为什么不试试像:

1
2
3
lastBusDay = datetime.datetime.today()
if datetime.date.weekday(lastBusDay) not in range(0,5):
    lastBusDay = 5