diff --git a/doc/source/whatsnew/v2.2.0.rst b/doc/source/whatsnew/v2.2.0.rst index b90563ba43d83..e122d06c75a71 100644 --- a/doc/source/whatsnew/v2.2.0.rst +++ b/doc/source/whatsnew/v2.2.0.rst @@ -113,6 +113,7 @@ Performance improvements Bug fixes ~~~~~~~~~ +- Bug in :class:`AbstractHolidayCalendar` where timezone data was not propagated when computing holiday observances (:issue:`54580`) Categorical ^^^^^^^^^^^ diff --git a/pandas/tests/tseries/holiday/test_holiday.py b/pandas/tests/tseries/holiday/test_holiday.py index ee83ca144d38a..e751339ca2cd0 100644 --- a/pandas/tests/tseries/holiday/test_holiday.py +++ b/pandas/tests/tseries/holiday/test_holiday.py @@ -3,7 +3,10 @@ import pytest from pytz import utc -from pandas import DatetimeIndex +from pandas import ( + DatetimeIndex, + Series, +) import pandas._testing as tm from pandas.tseries.holiday import ( @@ -17,6 +20,7 @@ HolidayCalendarFactory, Timestamp, USColumbusDay, + USFederalHolidayCalendar, USLaborDay, USMartinLutherKingJr, USMemorialDay, @@ -311,3 +315,17 @@ class TestHolidayCalendar(AbstractHolidayCalendar): tm.assert_index_equal(date_interval_low, expected_results) tm.assert_index_equal(date_window_edge, expected_results) tm.assert_index_equal(date_interval_high, expected_results) + + +def test_holidays_with_timezone_specified_but_no_occurences(): + # GH 54580 + # _apply_rule() in holiday.py was silently dropping timezones if you passed it + # an empty list of holiday dates that had timezone information + start_date = Timestamp("2018-01-01", tz="America/Chicago") + end_date = Timestamp("2018-01-11", tz="America/Chicago") + test_case = USFederalHolidayCalendar().holidays( + start_date, end_date, return_name=True + ) + expected_results = Series("New Year's Day", index=[start_date]) + + tm.assert_equal(test_case, expected_results) diff --git a/pandas/tseries/holiday.py b/pandas/tseries/holiday.py index 44c21bc284121..6b40907c009d5 100644 --- a/pandas/tseries/holiday.py +++ b/pandas/tseries/holiday.py @@ -354,7 +354,7 @@ def _apply_rule(self, dates: DatetimeIndex) -> DatetimeIndex: Dates with rules applied """ if dates.empty: - return DatetimeIndex([]) + return dates.copy() if self.observance is not None: return dates.map(lambda d: self.observance(d))