我对MLK日假期做出了自己的定义,该定义不遵循假日首次出现时的定义,而是遵循纽约证券交易所首次出现假日时的定义。纽约证券交易所于1998年1月首次庆祝MLK日。
在向假日询问日期之间的假日的日期时,它在大多数情况下都可以正常工作;当MLK日期不在请求的范围内时,返回空集;在MLK日期不在时,返回适当的日期。对于假期start_date
之前的日期范围,它将适当地返回空集,直到我们在1995年左右达到,然后失败。我无法弄清楚为什么会失败,而在空集是正确答案的其他情况下却无法解决。
注意:仍然停留在Pandas 0.22.0上。 Python3
import pandas as pd
from datetime import datetime
from dateutil.relativedelta import MO
from pandas.tseries.holiday import Holiday
__author__ = 'eb'
mlk_rule = Holiday('MLK Day (NYSE Observed)',
start_date=datetime(1998, 1, 1), month=1, day=1,
offset=pd.DateOffset(weekday=MO(3)))
start = pd.to_datetime('1999-01-17')
end = pd.to_datetime('1999-05-01')
finish = pd.to_datetime('1980-01-01')
while start > finish:
print(f"{start} - {end}:")
try:
dates = mlk_rule.dates(start, end, return_name=True)
except Exception as e:
print("\t****** Fail *******")
print(f"\t{e}")
break
print(f"\t{dates}")
start = start - pd.DateOffset(years=1)
end = end - pd.DateOffset(years=1)
运行时,结果为:
1999-01-17 00:00:00 - 1999-05-01 00:00:00:
1999-01-18 MLK Day (NYSE Observed)
Freq: 52W-MON, dtype: object
1998-01-17 00:00:00 - 1998-05-01 00:00:00:
1998-01-19 MLK Day (NYSE Observed)
Freq: 52W-MON, dtype: object
1997-01-17 00:00:00 - 1997-05-01 00:00:00:
Series([], dtype: object)
1996-01-17 00:00:00 - 1996-05-01 00:00:00:
Series([], dtype: object)
1995-01-17 00:00:00 - 1995-05-01 00:00:00:
****** Fail *******
Must provide freq argument if no data is supplied
在1995年发生了什么导致其失败的事情,而在几年前的同一时期没有发生?
答案 0 :(得分:0)
答案:在Holiday
类的内部,dates()
方法用于
收集请求日期范围内的有效假期列表。在
为了确保这种情况正确发生,实现会收集
从要求的日期的前一年到后一年的所有假期
通过内部_reference_dates()
方法的范围。用这种方法
如果接收方的Holiday
实例具有内部开始或结束日期,
它使用该日期作为要检查范围的开始或结束
而不是传入的请求范围,即使请求中的日期
范围早于或超过规则的开始或结束日期。
现有实现错误地认为可以将必须准确识别存在哪些假日的有效范围限制为存在假日的范围是可以的。作为日历中一组规则的一部分,Holiday
识别假日不存在的地方和假日不重要。 NULL设置响应是Holiday
类的重要功能。
例如,在需要确定金融市场何时开放或关闭的交易日日历中,日历可能需要准确地识别100年历史中的哪一天关闭市场。在该历史记录的一小部分,市场仅以MLK日收市。要求包含MLK start_date
[1]之前时段的开放日或假期时,包含上述构造的MLK假期的日历会引发错误。
为解决此问题,我在一个新版本中重新实现了_reference_dates()
方法
假日的自定义子类,以确保在请求的日期
范围扩展到start_date
之前或之后的end_date
之后
假期规则,它使用实际要求的范围来构建
参考日期来自内部,而不是内部
开始和结束日期。
这是我正在使用的实现。
class MLKHoliday(Holiday):
def __init__(self):
super().__init__('MLK Day (NYSE Observed)',
start_date=datetime(1998, 1, 1), month=1, day=1,
offset=pd.DateOffset(weekday=MO(3)))
def _reference_dates(self, start_date, end_date):
"""
Get reference dates for the holiday.
Return reference dates for the holiday also returning the year
prior to the start_date and year following the end_date. This ensures
that any offsets to be applied will yield the holidays within
the passed in dates.
"""
if self.start_date and start_date and start_date >= self.start_date:
start_date = self.start_date.tz_localize(start_date.tz)
if self.end_date and end_date and end_date <= self.end_date:
end_date = self.end_date.tz_localize(end_date.tz)
year_offset = pd.DateOffset(years=1)
reference_start_date = pd.Timestamp(
datetime(start_date.year - 1, self.month, self.day))
reference_end_date = pd.Timestamp(
datetime(end_date.year + 1, self.month, self.day))
# Don't process unnecessary holidays
dates = pd.DatetimeIndex(start=reference_start_date,
end=reference_end_date,
freq=year_offset, tz=start_date.tz)
return dates
有人知道这个问题是否已在最新版本的熊猫中得到解决?
[1]注意:如原始问题中所述,mlk_rule
实际上不会在dates()
之前的范围内提供start_date
调用的NULL设置,但是实际上会在一年左右之前开始引发异常。这是因为通过将日期范围在每个方向上各增加一年_reference_dates()
,可以减轻关于不需要适当的NULL集响应的错误假设。