Skip to content

Commit 23cdb4b

Browse files
gfyoungPingviinituutti
authored andcommitted
REF: Add more pytest idiom to test_holiday.py (pandas-dev#25204)
1 parent b3a8d35 commit 23cdb4b

File tree

6 files changed

+399
-382
lines changed

6 files changed

+399
-382
lines changed

pandas/tests/tseries/holiday/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
from datetime import datetime
2+
3+
import pytest
4+
5+
from pandas import DatetimeIndex
6+
import pandas.util.testing as tm
7+
8+
from pandas.tseries.holiday import (
9+
AbstractHolidayCalendar, Holiday, Timestamp, USFederalHolidayCalendar,
10+
USThanksgivingDay, get_calendar)
11+
12+
13+
@pytest.mark.parametrize("transform", [
14+
lambda x: x,
15+
lambda x: x.strftime("%Y-%m-%d"),
16+
lambda x: Timestamp(x)
17+
])
18+
def test_calendar(transform):
19+
start_date = datetime(2012, 1, 1)
20+
end_date = datetime(2012, 12, 31)
21+
22+
calendar = USFederalHolidayCalendar()
23+
holidays = calendar.holidays(transform(start_date), transform(end_date))
24+
25+
expected = [
26+
datetime(2012, 1, 2),
27+
datetime(2012, 1, 16),
28+
datetime(2012, 2, 20),
29+
datetime(2012, 5, 28),
30+
datetime(2012, 7, 4),
31+
datetime(2012, 9, 3),
32+
datetime(2012, 10, 8),
33+
datetime(2012, 11, 12),
34+
datetime(2012, 11, 22),
35+
datetime(2012, 12, 25)
36+
]
37+
38+
assert list(holidays.to_pydatetime()) == expected
39+
40+
41+
def test_calendar_caching():
42+
# see gh-9552.
43+
44+
class TestCalendar(AbstractHolidayCalendar):
45+
def __init__(self, name=None, rules=None):
46+
super(TestCalendar, self).__init__(name=name, rules=rules)
47+
48+
jan1 = TestCalendar(rules=[Holiday("jan1", year=2015, month=1, day=1)])
49+
jan2 = TestCalendar(rules=[Holiday("jan2", year=2015, month=1, day=2)])
50+
51+
# Getting holidays for Jan 1 should not alter results for Jan 2.
52+
tm.assert_index_equal(jan1.holidays(), DatetimeIndex(["01-Jan-2015"]))
53+
tm.assert_index_equal(jan2.holidays(), DatetimeIndex(["02-Jan-2015"]))
54+
55+
56+
def test_calendar_observance_dates():
57+
# see gh-11477
58+
us_fed_cal = get_calendar("USFederalHolidayCalendar")
59+
holidays0 = us_fed_cal.holidays(datetime(2015, 7, 3), datetime(
60+
2015, 7, 3)) # <-- same start and end dates
61+
holidays1 = us_fed_cal.holidays(datetime(2015, 7, 3), datetime(
62+
2015, 7, 6)) # <-- different start and end dates
63+
holidays2 = us_fed_cal.holidays(datetime(2015, 7, 3), datetime(
64+
2015, 7, 3)) # <-- same start and end dates
65+
66+
# These should all produce the same result.
67+
#
68+
# In addition, calling with different start and end
69+
# dates should not alter the output if we call the
70+
# function again with the same start and end date.
71+
tm.assert_index_equal(holidays0, holidays1)
72+
tm.assert_index_equal(holidays0, holidays2)
73+
74+
75+
def test_rule_from_name():
76+
us_fed_cal = get_calendar("USFederalHolidayCalendar")
77+
assert us_fed_cal.rule_from_name("Thanksgiving") == USThanksgivingDay
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
from datetime import datetime
2+
3+
from pandas.tseries.holiday import (
4+
AbstractHolidayCalendar, USMartinLutherKingJr, USMemorialDay)
5+
6+
7+
def test_no_mlk_before_1986():
8+
# see gh-10278
9+
class MLKCalendar(AbstractHolidayCalendar):
10+
rules = [USMartinLutherKingJr]
11+
12+
holidays = MLKCalendar().holidays(start="1984",
13+
end="1988").to_pydatetime().tolist()
14+
15+
# Testing to make sure holiday is not incorrectly observed before 1986.
16+
assert holidays == [datetime(1986, 1, 20, 0, 0),
17+
datetime(1987, 1, 19, 0, 0)]
18+
19+
20+
def test_memorial_day():
21+
class MemorialDay(AbstractHolidayCalendar):
22+
rules = [USMemorialDay]
23+
24+
holidays = MemorialDay().holidays(start="1971",
25+
end="1980").to_pydatetime().tolist()
26+
27+
# Fixes 5/31 error and checked manually against Wikipedia.
28+
assert holidays == [datetime(1971, 5, 31, 0, 0),
29+
datetime(1972, 5, 29, 0, 0),
30+
datetime(1973, 5, 28, 0, 0),
31+
datetime(1974, 5, 27, 0, 0),
32+
datetime(1975, 5, 26, 0, 0),
33+
datetime(1976, 5, 31, 0, 0),
34+
datetime(1977, 5, 30, 0, 0),
35+
datetime(1978, 5, 29, 0, 0),
36+
datetime(1979, 5, 28, 0, 0)]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
from datetime import datetime
2+
3+
import pytest
4+
from pytz import utc
5+
6+
import pandas.util.testing as tm
7+
8+
from pandas.tseries.holiday import (
9+
MO, SA, AbstractHolidayCalendar, DateOffset, EasterMonday, GoodFriday,
10+
Holiday, HolidayCalendarFactory, Timestamp, USColumbusDay, USLaborDay,
11+
USMartinLutherKingJr, USMemorialDay, USPresidentsDay, USThanksgivingDay,
12+
get_calendar, next_monday)
13+
14+
15+
def _check_holiday_results(holiday, start, end, expected):
16+
"""
17+
Check that the dates for a given holiday match in date and timezone.
18+
19+
Parameters
20+
----------
21+
holiday : Holiday
22+
The holiday to check.
23+
start : datetime-like
24+
The start date of range in which to collect dates for a given holiday.
25+
end : datetime-like
26+
The end date of range in which to collect dates for a given holiday.
27+
expected : list
28+
The list of dates we expect to get.
29+
"""
30+
assert list(holiday.dates(start, end)) == expected
31+
32+
# Verify that timezone info is preserved.
33+
assert (list(holiday.dates(utc.localize(Timestamp(start)),
34+
utc.localize(Timestamp(end)))) ==
35+
[utc.localize(dt) for dt in expected])
36+
37+
38+
@pytest.mark.parametrize("holiday,start_date,end_date,expected", [
39+
(USMemorialDay, datetime(2011, 1, 1), datetime(2020, 12, 31),
40+
[datetime(2011, 5, 30), datetime(2012, 5, 28), datetime(2013, 5, 27),
41+
datetime(2014, 5, 26), datetime(2015, 5, 25), datetime(2016, 5, 30),
42+
datetime(2017, 5, 29), datetime(2018, 5, 28), datetime(2019, 5, 27),
43+
datetime(2020, 5, 25)]),
44+
45+
(Holiday("July 4th Eve", month=7, day=3), "2001-01-01", "2003-03-03",
46+
[Timestamp("2001-07-03 00:00:00"), Timestamp("2002-07-03 00:00:00")]),
47+
(Holiday("July 4th Eve", month=7, day=3, days_of_week=(0, 1, 2, 3)),
48+
"2001-01-01", "2008-03-03", [
49+
Timestamp("2001-07-03 00:00:00"), Timestamp("2002-07-03 00:00:00"),
50+
Timestamp("2003-07-03 00:00:00"), Timestamp("2006-07-03 00:00:00"),
51+
Timestamp("2007-07-03 00:00:00")]),
52+
53+
(EasterMonday, datetime(2011, 1, 1), datetime(2020, 12, 31),
54+
[Timestamp("2011-04-25 00:00:00"), Timestamp("2012-04-09 00:00:00"),
55+
Timestamp("2013-04-01 00:00:00"), Timestamp("2014-04-21 00:00:00"),
56+
Timestamp("2015-04-06 00:00:00"), Timestamp("2016-03-28 00:00:00"),
57+
Timestamp("2017-04-17 00:00:00"), Timestamp("2018-04-02 00:00:00"),
58+
Timestamp("2019-04-22 00:00:00"), Timestamp("2020-04-13 00:00:00")]),
59+
(GoodFriday, datetime(2011, 1, 1), datetime(2020, 12, 31),
60+
[Timestamp("2011-04-22 00:00:00"), Timestamp("2012-04-06 00:00:00"),
61+
Timestamp("2013-03-29 00:00:00"), Timestamp("2014-04-18 00:00:00"),
62+
Timestamp("2015-04-03 00:00:00"), Timestamp("2016-03-25 00:00:00"),
63+
Timestamp("2017-04-14 00:00:00"), Timestamp("2018-03-30 00:00:00"),
64+
Timestamp("2019-04-19 00:00:00"), Timestamp("2020-04-10 00:00:00")]),
65+
66+
(USThanksgivingDay, datetime(2011, 1, 1), datetime(2020, 12, 31),
67+
[datetime(2011, 11, 24), datetime(2012, 11, 22), datetime(2013, 11, 28),
68+
datetime(2014, 11, 27), datetime(2015, 11, 26), datetime(2016, 11, 24),
69+
datetime(2017, 11, 23), datetime(2018, 11, 22), datetime(2019, 11, 28),
70+
datetime(2020, 11, 26)])
71+
])
72+
def test_holiday_dates(holiday, start_date, end_date, expected):
73+
_check_holiday_results(holiday, start_date, end_date, expected)
74+
75+
76+
@pytest.mark.parametrize("holiday,start,expected", [
77+
(USMemorialDay, datetime(2015, 7, 1), []),
78+
(USMemorialDay, "2015-05-25", "2015-05-25"),
79+
80+
(USLaborDay, datetime(2015, 7, 1), []),
81+
(USLaborDay, "2015-09-07", "2015-09-07"),
82+
83+
(USColumbusDay, datetime(2015, 7, 1), []),
84+
(USColumbusDay, "2015-10-12", "2015-10-12"),
85+
86+
(USThanksgivingDay, datetime(2015, 7, 1), []),
87+
(USThanksgivingDay, "2015-11-26", "2015-11-26"),
88+
89+
(USMartinLutherKingJr, datetime(2015, 7, 1), []),
90+
(USMartinLutherKingJr, "2015-01-19", "2015-01-19"),
91+
92+
(USPresidentsDay, datetime(2015, 7, 1), []),
93+
(USPresidentsDay, "2015-02-16", "2015-02-16"),
94+
95+
(GoodFriday, datetime(2015, 7, 1), []),
96+
(GoodFriday, "2015-04-03", "2015-04-03"),
97+
98+
(EasterMonday, "2015-04-06", "2015-04-06"),
99+
(EasterMonday, datetime(2015, 7, 1), []),
100+
(EasterMonday, "2015-04-05", []),
101+
102+
("New Years Day", "2015-01-01", "2015-01-01"),
103+
("New Years Day", "2010-12-31", "2010-12-31"),
104+
("New Years Day", datetime(2015, 7, 1), []),
105+
("New Years Day", "2011-01-01", []),
106+
107+
("July 4th", "2015-07-03", "2015-07-03"),
108+
("July 4th", datetime(2015, 7, 1), []),
109+
("July 4th", "2015-07-04", []),
110+
111+
("Veterans Day", "2012-11-12", "2012-11-12"),
112+
("Veterans Day", datetime(2015, 7, 1), []),
113+
("Veterans Day", "2012-11-11", []),
114+
115+
("Christmas", "2011-12-26", "2011-12-26"),
116+
("Christmas", datetime(2015, 7, 1), []),
117+
("Christmas", "2011-12-25", []),
118+
])
119+
def test_holidays_within_dates(holiday, start, expected):
120+
# see gh-11477
121+
#
122+
# Fix holiday behavior where holiday.dates returned dates outside
123+
# start/end date, or observed rules could not be applied because the
124+
# holiday was not in the original date range (e.g., 7/4/2015 -> 7/3/2015).
125+
if isinstance(holiday, str):
126+
calendar = get_calendar("USFederalHolidayCalendar")
127+
holiday = calendar.rule_from_name(holiday)
128+
129+
if isinstance(expected, str):
130+
expected = [Timestamp(expected)]
131+
132+
_check_holiday_results(holiday, start, start, expected)
133+
134+
135+
@pytest.mark.parametrize("transform", [
136+
lambda x: x.strftime("%Y-%m-%d"),
137+
lambda x: Timestamp(x)
138+
])
139+
def test_argument_types(transform):
140+
start_date = datetime(2011, 1, 1)
141+
end_date = datetime(2020, 12, 31)
142+
143+
holidays = USThanksgivingDay.dates(start_date, end_date)
144+
holidays2 = USThanksgivingDay.dates(
145+
transform(start_date), transform(end_date))
146+
tm.assert_index_equal(holidays, holidays2)
147+
148+
149+
@pytest.mark.parametrize("name,kwargs", [
150+
("One-Time", dict(year=2012, month=5, day=28)),
151+
("Range", dict(month=5, day=28, start_date=datetime(2012, 1, 1),
152+
end_date=datetime(2012, 12, 31),
153+
offset=DateOffset(weekday=MO(1))))
154+
])
155+
def test_special_holidays(name, kwargs):
156+
base_date = [datetime(2012, 5, 28)]
157+
holiday = Holiday(name, **kwargs)
158+
159+
start_date = datetime(2011, 1, 1)
160+
end_date = datetime(2020, 12, 31)
161+
162+
assert base_date == holiday.dates(start_date, end_date)
163+
164+
165+
def test_get_calendar():
166+
class TestCalendar(AbstractHolidayCalendar):
167+
rules = []
168+
169+
calendar = get_calendar("TestCalendar")
170+
assert TestCalendar == calendar.__class__
171+
172+
173+
def test_factory():
174+
class_1 = HolidayCalendarFactory("MemorialDay",
175+
AbstractHolidayCalendar,
176+
USMemorialDay)
177+
class_2 = HolidayCalendarFactory("Thanksgiving",
178+
AbstractHolidayCalendar,
179+
USThanksgivingDay)
180+
class_3 = HolidayCalendarFactory("Combined", class_1, class_2)
181+
182+
assert len(class_1.rules) == 1
183+
assert len(class_2.rules) == 1
184+
assert len(class_3.rules) == 2
185+
186+
187+
def test_both_offset_observance_raises():
188+
# see gh-10217
189+
msg = "Cannot use both offset and observance"
190+
with pytest.raises(NotImplementedError, match=msg):
191+
Holiday("Cyber Monday", month=11, day=1,
192+
offset=[DateOffset(weekday=SA(4))],
193+
observance=next_monday)

0 commit comments

Comments
 (0)