Skip to content

Commit b17da31

Browse files
BUG: Right result for DatetimeIndex + TimeDelta when timezone is set(pandas-dev#13905)
1 parent 7e15923 commit b17da31

File tree

5 files changed

+25
-6
lines changed

5 files changed

+25
-6
lines changed

doc/source/whatsnew/v0.19.0.txt

+1
Original file line numberDiff line numberDiff line change
@@ -938,6 +938,7 @@ Bug Fixes
938938
- Bug in invalid ``Timedelta`` arithmetic and comparison may raise ``ValueError`` rather than ``TypeError`` (:issue:`13624`)
939939
- Bug in invalid datetime parsing in ``to_datetime`` and ``DatetimeIndex`` may raise ``TypeError`` rather than ``ValueError`` (:issue:`11169`, :issue:`11287`)
940940
- Bug in ``Index`` created with tz-aware ``Timestamp`` and mismatched ``tz`` option incorrectly coerces timezone (:issue:`13692`)
941+
- Bug in ``DatetimeIndex + TimeDelta`` gives wrong results when timezone is set (:issue:`13905`)
941942
- Bug in ``DatetimeIndex`` with nanosecond frequency does not include timestamp specified with ``end`` (:issue:`13672`)
942943

943944
- Bug in ``Index`` raises ``OutOfBoundsDatetime`` if ``datetime`` exceeds ``datetime64[ns]`` bounds, rather than coercing to ``object`` dtype (:issue:`13663`)

pandas/core/ops.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -461,7 +461,7 @@ def _convert_to_array(self, values, name=None, other=None):
461461

462462
# a datelike
463463
elif isinstance(values, pd.DatetimeIndex):
464-
values = values.to_series()
464+
values = values.to_series(True)
465465
# datetime with tz
466466
elif (isinstance(ovalues, datetime.datetime) and
467467
hasattr(ovalues, 'tz')):
@@ -543,9 +543,9 @@ def _offset(lvalues, rvalues):
543543

544544
# with tz, convert to UTC
545545
if self.is_datetime64tz_lhs:
546-
lvalues = lvalues.tz_localize(None)
546+
lvalues = lvalues.tz_convert('UTC')
547547
if self.is_datetime64tz_rhs:
548-
rvalues = rvalues.tz_localize(None)
548+
rvalues = rvalues.tz_convert('UTC')
549549

550550
lvalues = lvalues.view(np.int64)
551551
rvalues = rvalues.view(np.int64)

pandas/indexes/base.py

+8-1
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,14 @@ def __new__(cls, data=None, dtype=None, copy=False, name=None,
165165
if (issubclass(data.dtype.type, np.datetime64) or
166166
is_datetimetz(data)):
167167
from pandas.tseries.index import DatetimeIndex
168-
result = DatetimeIndex(data, copy=copy, name=name, **kwargs)
168+
if 'tz' in kwargs:
169+
tz = kwargs['tz']
170+
del kwargs['tz']
171+
result = DatetimeIndex(data, copy=copy, tz='UTC',
172+
name=name, **kwargs).tz_convert(tz)
173+
else:
174+
result = DatetimeIndex(data, copy=copy,
175+
name=name, **kwargs)
169176
if dtype is not None and _o_dtype == dtype:
170177
return Index(result.to_pydatetime(), dtype=_o_dtype)
171178
else:

pandas/tests/series/test_operators.py

+11
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,17 @@ def test_timedelta64_operations_with_DateOffset(self):
373373
td - op(5)
374374
op(5) - td
375375

376+
def test_timedelta64_operations_with_DatetimeIndex_tz(self):
377+
# GH 13905
378+
dti = pd.DatetimeIndex(['2016-06-28 05:30', '2016-06-28 05:31'],
379+
dtype='datetime64[ns, America/Chicago]')
380+
td = Series(['00:00:05', '00:00:05'], dtype='timedelta64[ns]')
381+
382+
exp = Series(['2016-06-28 05:30:05-05:00',
383+
'2016-06-28 05:31:05-05:00'],
384+
dtype='datetime64[ns, America/Chicago]')
385+
assert_series_equal(dti + td, exp)
386+
376387
def test_timedelta64_operations_with_timedeltas(self):
377388

378389
# td operate with td

pandas/types/cast.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -820,8 +820,8 @@ def _possibly_cast_to_datetime(value, dtype, errors='raise'):
820820
# input has to be UTC at this point, so just
821821
# localize
822822
value = to_datetime(
823-
value,
824-
errors=errors).tz_localize(dtype.tz)
823+
value, utc=True,
824+
errors=errors).tz_convert(dtype.tz)
825825
elif is_timedelta64:
826826
value = to_timedelta(value, errors=errors)._values
827827
except (AttributeError, ValueError, TypeError):

0 commit comments

Comments
 (0)