Python/Pandas:查找考虑假期的日期时间的自定义业务季度结束

Python/Pandas: Find the Custom Business Quarter End of a datetime which takes holidays into account

我想在 python 中找到日期时间的商业季度结束,这也会处理假期。为简单起见,这些假期可以作为列表传递。我从 pandas.tseries.offsets 知道 BQuarterEnd()。据我所知,它不考虑假期。

例子:如果2020-11-20过去了,2020-12-31是一个工作日,也是一个假期;它应该 return 2020-12-30.

谢谢。

您可能需要自定义函数。可能是这样的:

def custom_quarter_end(date, holidays=[]):
    holidays = [pd.Timestamp(h) for h in holidays]
    end = pd.Timestamp(date)+pd.tseries.offsets.BQuarterEnd()
    while end in holidays:
        end = end - pd.tseries.offsets.BDay()
    return end

>>> custom_quarter_end("2020-11-20", ["2020-12-30", "2020-12-31"])
Timestamp('2020-12-29 00:00:00')

在 Pandas 中,有一组 Custom business days 函数,您可以在其中定义自己的假期列表,然后这些函数会为您计算正确的日期偏移量,同时考虑到自定义假期列表。

例如,我们有 CustomBusinessMonthEnd (better documentation here)。不幸的是,季末没有相应的CustomBusinessQuarterEnd(Custom Business QuarterEnd)函数。

但是,我们仍然可以得到一些变通解决方案,如下所示:

  1. 定义您的自定义假期列表,例如:
holiday_list = ['2020-12-31']
  1. 利用 QuarterEnd + CustomBusinessMonthEnd 的组合来获得 Custom Business QuarterEnd 跳过假期所需的日期:
import pandas as pd

base_date = pd.to_datetime('2020-11-20')   # Base date

custom_business_quarter_end = (base_date 
                                   + pd.offsets.QuarterEnd(n=0) 
                                   - pd.offsets.MonthBegin() 
                                   + pd.offsets.CustomBusinessMonthEnd(holidays=holiday_list))

首先,我们将您的基准日期添加到 QuarterEnd 以获得季度结束日期(不考虑节假日)。然后,为了让 Custom Business QuarterEnd 跳过节假日,我们使用 CustomBusinessMonthEnd 也传递节假日列表作为参数以针对节假日进行调整。

为了 QuarterEnd, we pass the parameter n=0 to handle the edge case where the base date is already on the Quarter End date. We avoid QuarterEnd to rollover this quarter end date to the next quarter end date. You can refer to the official doc here 了解更多关于 Pandas 如何处理落在锚定日期上的日期(请参阅以“对于 n=0 的情况,...”开头的小节)

在调用CustomBusinessMonthEnd之前,我们也先使用了MonthBegin。这是为了避免月末锚点的一天滚动到下个月。我们需要这个,因为 n=0 参数对 CustomBusinessMonthEnd 的工作方式与对 QuarterEnd 的工作方式不同,以避免翻转。因此,这个额外的减号 MonthBegin 是必需的。使用MonthBegin,我们先得到季末的月开始日期,即2020-12-01,然后得到自定义业务月末日期.这样,我们就可以避免 QuarterEnd 的结果,例如2020-12-31 结转到下个月底,例如2021-01-31 直接调用时 CustomBusinessMonthEnd.

结果:

print(custom_business_quarter_end)

2020-12-30 00:00:00