From c079ee3a5cdf6d77e53d647c4122132faf942ee7 Mon Sep 17 00:00:00 2001 From: sinhrks Date: Sun, 7 Aug 2016 04:15:46 +0900 Subject: [PATCH] BUG: DatetimeTz shift raises AmbiguousTimeError near DST --- doc/source/whatsnew/v0.19.0.txt | 1 + pandas/core/internals.py | 5 ++--- pandas/tests/series/test_timeseries.py | 29 +++++++++++++++++++++++++- 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/doc/source/whatsnew/v0.19.0.txt b/doc/source/whatsnew/v0.19.0.txt index 581daab5cea58..644ad1e94fe66 100644 --- a/doc/source/whatsnew/v0.19.0.txt +++ b/doc/source/whatsnew/v0.19.0.txt @@ -875,6 +875,7 @@ Bug Fixes - Clean some compile time warnings in datetime parsing (:issue:`13607`) - Bug in ``factorize`` raises ``AmbiguousTimeError`` if data contains datetime near DST boundary (:issue:`13750`) - Bug in ``.set_index`` raises ``AmbiguousTimeError`` if new index contains DST boundary and multi levels (:issue:`12920`) +- Bug in ``.shift`` raises ``AmbiguousTimeError`` if data contains datetime near DST boundary (:issue:`13926`) - Bug in ``pd.read_hdf()`` returns incorrect result when a ``DataFrame`` with a ``categorical`` column and a query which doesn't match any values (:issue:`13792`) - Bug in ``pd.to_datetime()`` raise ``AttributeError`` with NaN and the other string is not valid when errors='ignore' (:issue:`12424`) diff --git a/pandas/core/internals.py b/pandas/core/internals.py index 83fba7a0ce8b5..18b67c41b4554 100644 --- a/pandas/core/internals.py +++ b/pandas/core/internals.py @@ -2438,15 +2438,14 @@ def shift(self, periods, axis=0, mgr=None): else: indexer[:periods] = np.arange(-periods, N) - # move to UTC & take - new_values = self.values.tz_localize(None).asi8.take(indexer) + new_values = self.values.asi8.take(indexer) if periods > 0: new_values[:periods] = tslib.iNaT else: new_values[periods:] = tslib.iNaT - new_values = DatetimeIndex(new_values, tz=self.values.tz) + new_values = self.values._shallow_copy(new_values) return [self.make_block_same_class(new_values, placement=self.mgr_locs)] diff --git a/pandas/tests/series/test_timeseries.py b/pandas/tests/series/test_timeseries.py index 19acf54c7a3cb..341d18f987abc 100644 --- a/pandas/tests/series/test_timeseries.py +++ b/pandas/tests/series/test_timeseries.py @@ -5,7 +5,7 @@ import numpy as np -from pandas import Index, Series, date_range +from pandas import Index, Series, date_range, NaT from pandas.tseries.index import DatetimeIndex from pandas.tseries.tdi import TimedeltaIndex @@ -93,6 +93,33 @@ def test_shift(self): tz='CET'), name='foo') self.assertRaises(ValueError, lambda: s - s2) + def test_shift_dst(self): + # GH 13926 + dates = date_range('2016-11-06', freq='H', periods=10, tz='US/Eastern') + s = Series(dates) + + res = s.shift(0) + tm.assert_series_equal(res, s) + self.assertEqual(res.dtype, 'datetime64[ns, US/Eastern]') + + res = s.shift(1) + exp_vals = [NaT] + dates.asobject.values.tolist()[:9] + exp = Series(exp_vals) + tm.assert_series_equal(res, exp) + self.assertEqual(res.dtype, 'datetime64[ns, US/Eastern]') + + res = s.shift(-2) + exp_vals = dates.asobject.values.tolist()[2:] + [NaT, NaT] + exp = Series(exp_vals) + tm.assert_series_equal(res, exp) + self.assertEqual(res.dtype, 'datetime64[ns, US/Eastern]') + + for ex in [10, -10, 20, -20]: + res = s.shift(ex) + exp = Series([NaT] * 10, dtype='datetime64[ns, US/Eastern]') + tm.assert_series_equal(res, exp) + self.assertEqual(res.dtype, 'datetime64[ns, US/Eastern]') + def test_tshift(self): # PeriodIndex ps = tm.makePeriodSeries()