Skip to content

Commit 66038e9

Browse files
jbrockmendelsimonjayhawkins
authored andcommitted
BUG+TST: non-optimized apply_index and empty DatetimeIndex (#30336)
1 parent b4343ef commit 66038e9

File tree

3 files changed

+49
-4
lines changed

3 files changed

+49
-4
lines changed

doc/source/whatsnew/v1.0.0.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -712,7 +712,7 @@ Datetimelike
712712
- Bug in :func:`pandas.to_datetime` when called with ``None`` raising ``TypeError`` instead of returning ``NaT`` (:issue:`30011`)
713713
- Bug in :func:`pandas.to_datetime` failing for `deques` when using ``cache=True`` (the default) (:issue:`29403`)
714714
- Bug in :meth:`Series.item` with ``datetime64`` or ``timedelta64`` dtype, :meth:`DatetimeIndex.item`, and :meth:`TimedeltaIndex.item` returning an integer instead of a :class:`Timestamp` or :class:`Timedelta` (:issue:`30175`)
715-
-
715+
- Bug in :class:`DatetimeIndex` addition when adding a non-optimized :class:`DateOffset` incorrectly dropping timezone information (:issue:`30336`)
716716

717717
Timedelta
718718
^^^^^^^^^

pandas/core/arrays/datetimes.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -794,16 +794,17 @@ def _add_offset(self, offset):
794794
values = self.tz_localize(None)
795795
else:
796796
values = self
797-
result = offset.apply_index(values)
798-
if self.tz is not None:
799-
result = result.tz_localize(self.tz)
797+
result = offset.apply_index(values).tz_localize(self.tz)
800798

801799
except NotImplementedError:
802800
warnings.warn(
803801
"Non-vectorized DateOffset being applied to Series or DatetimeIndex",
804802
PerformanceWarning,
805803
)
806804
result = self.astype("O") + offset
805+
if len(self) == 0:
806+
# _from_sequence won't be able to infer self.tz
807+
return type(self)._from_sequence(result).tz_localize(self.tz)
807808

808809
return type(self)._from_sequence(result, freq="infer")
809810

pandas/tests/tseries/offsets/test_offsets.py

+44
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from pandas._libs.tslibs.offsets import ApplyTypeError
2121
import pandas.compat as compat
2222
from pandas.compat.numpy import np_datetime64_compat
23+
from pandas.errors import PerformanceWarning
2324

2425
from pandas.core.indexes.datetimes import DatetimeIndex, _to_M8, date_range
2526
from pandas.core.series import Series
@@ -43,7 +44,10 @@
4344
CBMonthBegin,
4445
CBMonthEnd,
4546
CDay,
47+
CustomBusinessDay,
4648
CustomBusinessHour,
49+
CustomBusinessMonthBegin,
50+
CustomBusinessMonthEnd,
4751
DateOffset,
4852
Day,
4953
Easter,
@@ -607,6 +611,46 @@ def test_add(self, offset_types, tz_naive_fixture):
607611
assert isinstance(result, Timestamp)
608612
assert result == expected_localize
609613

614+
def test_add_empty_datetimeindex(self, offset_types, tz_naive_fixture):
615+
# GH#12724, GH#30336
616+
offset_s = self._get_offset(offset_types)
617+
618+
dti = DatetimeIndex([], tz=tz_naive_fixture)
619+
620+
warn = None
621+
if isinstance(
622+
offset_s,
623+
(
624+
Easter,
625+
WeekOfMonth,
626+
LastWeekOfMonth,
627+
CustomBusinessDay,
628+
BusinessHour,
629+
CustomBusinessHour,
630+
CustomBusinessMonthBegin,
631+
CustomBusinessMonthEnd,
632+
FY5253,
633+
FY5253Quarter,
634+
),
635+
):
636+
# We don't have an optimized apply_index
637+
warn = PerformanceWarning
638+
639+
with tm.assert_produces_warning(warn):
640+
result = dti + offset_s
641+
tm.assert_index_equal(result, dti)
642+
with tm.assert_produces_warning(warn):
643+
result = offset_s + dti
644+
tm.assert_index_equal(result, dti)
645+
646+
dta = dti._data
647+
with tm.assert_produces_warning(warn):
648+
result = dta + offset_s
649+
tm.assert_equal(result, dta)
650+
with tm.assert_produces_warning(warn):
651+
result = offset_s + dta
652+
tm.assert_equal(result, dta)
653+
610654
def test_pickle_v0_15_2(self, datapath):
611655
offsets = {
612656
"DateOffset": DateOffset(years=1),

0 commit comments

Comments
 (0)