Skip to content

Commit 7f93018

Browse files
dontgotomroeschke
andauthored
BUG: #29049 make holiday support offsets of offsets (#57938)
* support offsets of offsets in holiday creation * update whatsnew * add type annotations * update type annotation * make types compatible * update docstring * don't accept, only raise with more informative exception * add attribute type hint * change array to list in docstring Co-authored-by: Matthew Roeschke <[email protected]> * broaden if check; specify error message * update test raises message --------- Co-authored-by: Matthew Roeschke <[email protected]>
1 parent 788695c commit 7f93018

File tree

2 files changed

+54
-12
lines changed

2 files changed

+54
-12
lines changed

pandas/tests/tseries/holiday/test_holiday.py

+19
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,25 @@ def test_both_offset_observance_raises():
271271
)
272272

273273

274+
def test_list_of_list_of_offsets_raises():
275+
# see gh-29049
276+
# Test that the offsets of offsets are forbidden
277+
holiday1 = Holiday(
278+
"Holiday1",
279+
month=USThanksgivingDay.month,
280+
day=USThanksgivingDay.day,
281+
offset=[USThanksgivingDay.offset, DateOffset(1)],
282+
)
283+
msg = "Only BaseOffsets and flat lists of them are supported for offset."
284+
with pytest.raises(ValueError, match=msg):
285+
Holiday(
286+
"Holiday2",
287+
month=holiday1.month,
288+
day=holiday1.day,
289+
offset=[holiday1.offset, DateOffset(3)],
290+
)
291+
292+
274293
def test_half_open_interval_with_observance():
275294
# Prompted by GH 49075
276295
# Check for holidays that have a half-open date interval where

pandas/tseries/holiday.py

+35-12
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
datetime,
55
timedelta,
66
)
7+
from typing import Callable
78
import warnings
89

910
from dateutil.relativedelta import (
@@ -17,6 +18,7 @@
1718
)
1819
import numpy as np
1920

21+
from pandas._libs.tslibs.offsets import BaseOffset
2022
from pandas.errors import PerformanceWarning
2123

2224
from pandas import (
@@ -159,24 +161,34 @@ def __init__(
159161
year=None,
160162
month=None,
161163
day=None,
162-
offset=None,
163-
observance=None,
164+
offset: BaseOffset | list[BaseOffset] | None = None,
165+
observance: Callable | None = None,
164166
start_date=None,
165167
end_date=None,
166-
days_of_week=None,
168+
days_of_week: tuple | None = None,
167169
) -> None:
168170
"""
169171
Parameters
170172
----------
171173
name : str
172174
Name of the holiday , defaults to class name
173-
offset : array of pandas.tseries.offsets or
174-
class from pandas.tseries.offsets
175-
computes offset from date
176-
observance: function
177-
computes when holiday is given a pandas Timestamp
178-
days_of_week:
179-
provide a tuple of days e.g (0,1,2,3,) for Monday Through Thursday
175+
year : int, default None
176+
Year of the holiday
177+
month : int, default None
178+
Month of the holiday
179+
day : int, default None
180+
Day of the holiday
181+
offset : list of pandas.tseries.offsets or
182+
class from pandas.tseries.offsets, default None
183+
Computes offset from date
184+
observance : function, default None
185+
Computes when holiday is given a pandas Timestamp
186+
start_date : datetime-like, default None
187+
First date the holiday is observed
188+
end_date : datetime-like, default None
189+
Last date the holiday is observed
190+
days_of_week : tuple of int or dateutil.relativedelta weekday strs, default None
191+
Provide a tuple of days e.g (0,1,2,3,) for Monday Through Thursday
180192
Monday=0,..,Sunday=6
181193
182194
Examples
@@ -216,8 +228,19 @@ class from pandas.tseries.offsets
216228
>>> July3rd
217229
Holiday: July 3rd (month=7, day=3, )
218230
"""
219-
if offset is not None and observance is not None:
220-
raise NotImplementedError("Cannot use both offset and observance.")
231+
if offset is not None:
232+
if observance is not None:
233+
raise NotImplementedError("Cannot use both offset and observance.")
234+
if not (
235+
isinstance(offset, BaseOffset)
236+
or (
237+
isinstance(offset, list)
238+
and all(isinstance(off, BaseOffset) for off in offset)
239+
)
240+
):
241+
raise ValueError(
242+
"Only BaseOffsets and flat lists of them are supported for offset."
243+
)
221244

222245
self.name = name
223246
self.year = year

0 commit comments

Comments
 (0)