Python/Pandas:查找将假期考虑在内的日期时间的自定义业务季度结束
Posted
技术标签:
【中文标题】Python/Pandas:查找将假期考虑在内的日期时间的自定义业务季度结束【英文标题】:Python/Pandas: Find the Custom Business Quarter End of a datetime which takes holidays into account 【发布时间】:2021-10-21 11:40:11 【问题描述】:我想在 python 中找到一个日期时间的商业季度结束,这也将照顾假期。为简单起见,这些假期可以作为列表传递。我从pandas.tseries.offsets
知道BQuarterEnd()
。据我所知,它没有考虑假期。
示例:如果 2020-11-20
已通过,而 2020-12-31
是工作日但也是假期;它应该返回2020-12-30
。
谢谢。
【问题讨论】:
【参考方案1】:在 Pandas 中,有一组 Custom business days
函数,您可以在其中定义自己的假期列表,然后这些函数会根据自定义假期列表为您计算正确的日期偏移量。
例如,我们有CustomBusinessMonthEnd
(更好的文档here)。很遗憾,季度末没有对应的CustomBusinessQuarterEnd
(Custom Business QuarterEnd
)函数。
但是,我们仍然可以获得一些变通解决方案,如下所示:
-
定义您的自定义假期列表,例如:
holiday_list = ['2020-12-31']
-
使用
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
,我们传递参数n=0
来处理基准日期已经在季度结束日期的极端情况。我们避免QuarterEnd
将本季度结束日期滚动到下一个季度结束日期。您可以参考官方文档here 了解更多关于 Pandas 如何处理落在锚定日期上的日期(参见以“对于 n=0 时的情况,...”开头的小节)
我们也先使用MonthBegin
,然后再调用CustomBusinessMonthEnd
。这是为了避免将月末锚点的一天滚动到下个月。我们需要这个,因为n=0
参数对CustomBusinessMonthEnd
的工作方式与QuarterEnd
的工作方式不同,以避免翻转。因此,这个额外的减号MonthBegin
是必需的。使用MonthBegin
,我们先得到季度末的月份开始日期,即2020-12-01
,然后得到自定义的业务月末日期。这样我们就可以避免QuarterEnd
的结果,例如2020-12-31
被滚动到下个月底,例如直接调用CustomBusinessMonthEnd
时2021-01-31
。
结果:
print(custom_business_quarter_end)
2020-12-30 00:00:00
【讨论】:
这很棒。谢谢。一些边缘情况对我来说失败了。一,当基准日期不是业务日期时,例如2022-12-31
,它给出2023-03-31
,但预期是2022-12-30
。在这种情况下,为简单起见,假期列表为空。也许 QuarterEnd() 而不是 BQuarterEnd 可以完成这项工作。另一种没有给出所需输出的情况:假设给定日期是 BQuarterEnd 并且也是假期。例如2020-12-31
是基准日期和假期。它给了2021-03-31
。
@ParasGupta 感谢您进行彻底的测试并建议边缘情况。对于边缘情况,我们可以在调用BQuarterEnd
之前进一步获取以MonthBegin
开头的月份。这将与我们在调用 CustomBusinessMonthEnd
之前最初使用 MonthBegin
的方式相同,以避免在月末锚定日期出现不必要的滚动。您可以查看并重试。让我知道结果。谢谢!
@ParasGupta 我已经用新添加的MonthBegin
进一步微调了代码以传递参数n=0
以确保基准日期是一个月的第一天,它不会回滚到上个月。请尝试使用最新的代码。
@ParasGupta 使用QuarterEnd
而不是BQuarterEnd
并将参数n=0
传递给QuarterEnd
,从而稍微简化了代码。希望这应该是最终版本。
谢谢。我还用你的线索搞乱了QuarterEnd
。这个完美无缺。太好了!!【参考方案2】:
您可能需要一个自定义函数。可能是这样的:
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')
【讨论】:
以上是关于Python/Pandas:查找将假期考虑在内的日期时间的自定义业务季度结束的主要内容,如果未能解决你的问题,请参考以下文章