From 29eb7a4372b18ca91fc1e8ec1cdf79c2610f5ee7 Mon Sep 17 00:00:00 2001 From: David Hirschfeld Date: Mon, 3 Feb 2020 09:33:18 +1000 Subject: [PATCH 1/5] Fix bug in calculation of holidays Closes #31415 --- doc/source/whatsnew/v1.1.0.rst | 2 ++ pandas/tests/tseries/holiday/test_calendar.py | 11 +++++++++++ pandas/tseries/holiday.py | 15 ++++++--------- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/doc/source/whatsnew/v1.1.0.rst b/doc/source/whatsnew/v1.1.0.rst index dc7edd8db662e..dc17cddd32df9 100644 --- a/doc/source/whatsnew/v1.1.0.rst +++ b/doc/source/whatsnew/v1.1.0.rst @@ -223,6 +223,8 @@ Other - Appending a dictionary to a :class:`DataFrame` without passing ``ignore_index=True`` will raise ``TypeError: Can only append a dict if ignore_index=True`` instead of ``TypeError: Can only append a Series if ignore_index=True or if the Series has a name`` (:issue:`30871`) - Set operations on an object-dtype :class:`Index` now always return object-dtype results (:issue:`31401`) +- Bug in :meth:`AbstractHolidayCalendar.holidays` when no rules were defined (:issue:`31415`) +- .. --------------------------------------------------------------------------- diff --git a/pandas/tests/tseries/holiday/test_calendar.py b/pandas/tests/tseries/holiday/test_calendar.py index 5b4a7c74b1af1..9c53bfc70f3c5 100644 --- a/pandas/tests/tseries/holiday/test_calendar.py +++ b/pandas/tests/tseries/holiday/test_calendar.py @@ -98,3 +98,14 @@ class testCalendar(AbstractHolidayCalendar): Sat_before_Labor_Day_2031 = to_datetime("2031-08-30") next_working_day = Sat_before_Labor_Day_2031 + 0 * workDay assert next_working_day == to_datetime("2031-09-02") + + +def test_no_holidays_calendar(): + # Test for issue #31415 + + class NoHolidaysCalendar(AbstractHolidayCalendar): + pass + + cal = NoHolidaysCalendar() + holidays = cal.holidays(Timestamp("01-Jan-2020"), Timestamp("01-Jan-2021")) + assert holidays.empty diff --git a/pandas/tseries/holiday.py b/pandas/tseries/holiday.py index 62d7c26b590cc..fe30130e87c01 100644 --- a/pandas/tseries/holiday.py +++ b/pandas/tseries/holiday.py @@ -7,7 +7,7 @@ from pandas.errors import PerformanceWarning -from pandas import DateOffset, Series, Timestamp, date_range +from pandas import DateOffset, DatetimeIndex, Series, Timestamp, concat, date_range from pandas.tseries.offsets import Day, Easter @@ -406,17 +406,14 @@ def holidays(self, start=None, end=None, return_name=False): start = Timestamp(start) end = Timestamp(end) - holidays = None # If we don't have a cache or the dates are outside the prior cache, we # get them again if self._cache is None or start < self._cache[0] or end > self._cache[1]: - for rule in self.rules: - rule_holidays = rule.dates(start, end, return_name=True) - - if holidays is None: - holidays = rule_holidays - else: - holidays = holidays.append(rule_holidays) + holidays = [rule.dates(start, end, return_name=True) for rule in self.rules] + if holidays: + holidays = concat(holidays) + else: + holidays = Series(index=DatetimeIndex([]), dtype=object) self._cache = (start, end, holidays.sort_index()) From be850b7ab7c261e90d68599b33fc8a9f0b64aec9 Mon Sep 17 00:00:00 2001 From: David Hirschfeld Date: Wed, 5 Feb 2020 12:32:21 +1000 Subject: [PATCH 2/5] Address review comments --- pandas/tests/tseries/holiday/test_calendar.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pandas/tests/tseries/holiday/test_calendar.py b/pandas/tests/tseries/holiday/test_calendar.py index 9c53bfc70f3c5..5bc107d212e60 100644 --- a/pandas/tests/tseries/holiday/test_calendar.py +++ b/pandas/tests/tseries/holiday/test_calendar.py @@ -2,7 +2,7 @@ import pytest -from pandas import DatetimeIndex, offsets, to_datetime +from pandas import DatetimeIndex, Series, offsets, to_datetime import pandas._testing as tm from pandas.tseries.holiday import ( @@ -108,4 +108,5 @@ class NoHolidaysCalendar(AbstractHolidayCalendar): cal = NoHolidaysCalendar() holidays = cal.holidays(Timestamp("01-Jan-2020"), Timestamp("01-Jan-2021")) - assert holidays.empty + empty_series = Series(index=DatetimeIndex([]), dtype=object) + tm.assert_series_equal(holidays, empty_series) From f0f0f516f076471a4b9ef9ef52e6812e2fc9fae9 Mon Sep 17 00:00:00 2001 From: David Hirschfeld Date: Fri, 7 Feb 2020 13:25:30 +1000 Subject: [PATCH 3/5] Fix type check in test --- pandas/tests/tseries/holiday/test_calendar.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pandas/tests/tseries/holiday/test_calendar.py b/pandas/tests/tseries/holiday/test_calendar.py index 5bc107d212e60..3686c4e790b5f 100644 --- a/pandas/tests/tseries/holiday/test_calendar.py +++ b/pandas/tests/tseries/holiday/test_calendar.py @@ -108,5 +108,5 @@ class NoHolidaysCalendar(AbstractHolidayCalendar): cal = NoHolidaysCalendar() holidays = cal.holidays(Timestamp("01-Jan-2020"), Timestamp("01-Jan-2021")) - empty_series = Series(index=DatetimeIndex([]), dtype=object) - tm.assert_series_equal(holidays, empty_series) + empty_index = DatetimeIndex([]) # Type is DatetimeIndex since return_name=False + tm.assert_series_equal(holidays, empty_index) From b50995b35f9583ac03412d7f57640b13e0f1fca4 Mon Sep 17 00:00:00 2001 From: Dave Hirschfeld Date: Fri, 7 Feb 2020 13:55:04 +1000 Subject: [PATCH 4/5] Fix lint --- pandas/tests/tseries/holiday/test_calendar.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/tests/tseries/holiday/test_calendar.py b/pandas/tests/tseries/holiday/test_calendar.py index 3686c4e790b5f..be082c8099788 100644 --- a/pandas/tests/tseries/holiday/test_calendar.py +++ b/pandas/tests/tseries/holiday/test_calendar.py @@ -2,7 +2,7 @@ import pytest -from pandas import DatetimeIndex, Series, offsets, to_datetime +from pandas import DatetimeIndex, offsets, to_datetime import pandas._testing as tm from pandas.tseries.holiday import ( From b02918ab172531901fc29da4d197070dbd147d1a Mon Sep 17 00:00:00 2001 From: Dave Hirschfeld Date: Fri, 7 Feb 2020 14:22:14 +1000 Subject: [PATCH 5/5] Use appropriate assert function --- pandas/tests/tseries/holiday/test_calendar.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/tests/tseries/holiday/test_calendar.py b/pandas/tests/tseries/holiday/test_calendar.py index be082c8099788..cd3b1aab33a2a 100644 --- a/pandas/tests/tseries/holiday/test_calendar.py +++ b/pandas/tests/tseries/holiday/test_calendar.py @@ -109,4 +109,4 @@ class NoHolidaysCalendar(AbstractHolidayCalendar): cal = NoHolidaysCalendar() holidays = cal.holidays(Timestamp("01-Jan-2020"), Timestamp("01-Jan-2021")) empty_index = DatetimeIndex([]) # Type is DatetimeIndex since return_name=False - tm.assert_series_equal(holidays, empty_index) + tm.assert_index_equal(holidays, empty_index)