diff --git a/doc/source/whatsnew/v0.23.2.txt b/doc/source/whatsnew/v0.23.2.txt index b8d865195cddd..d5f3cfa477eca 100644 --- a/doc/source/whatsnew/v0.23.2.txt +++ b/doc/source/whatsnew/v0.23.2.txt @@ -79,6 +79,11 @@ Bug Fixes **Timezones** - Bug in :class:`Timestamp` and :class:`DatetimeIndex` where passing a :class:`Timestamp` localized after a DST transition would return a datetime before the DST transition (:issue:`20854`) - Bug in comparing :class:`DataFrame`s with tz-aware :class:`DatetimeIndex` columns with a DST transition that raised a ``KeyError`` (:issue:`19970`) +- Bug in :meth:`DatetimeIndex.shift` where an ``AssertionError`` would raise when shifting across DST (:issue:`8616`) +- Bug in :class:`Timestamp` constructor where passing an invalid timezone offset designator (``Z``) would not raise a ``ValueError``(:issue:`8910`) +- Bug in :meth:`Timestamp.replace` where replacing at a DST boundary would retain an incorrect offset (:issue:`7825`) +- Bug in :meth:`DatetimeIndex.reindex` when reindexing a tz-naive and tz-aware :class:`DatetimeIndex` (:issue:`8306`) +- Bug in :meth:`DatetimeIndex.resample` when downsampling across a DST boundary (:issue:`8531`) **Other** diff --git a/pandas/tests/indexes/datetimes/test_arithmetic.py b/pandas/tests/indexes/datetimes/test_arithmetic.py index eff2872a1cff3..0649083a440df 100644 --- a/pandas/tests/indexes/datetimes/test_arithmetic.py +++ b/pandas/tests/indexes/datetimes/test_arithmetic.py @@ -4,7 +4,7 @@ import operator import pytest - +import pytz import numpy as np import pandas as pd @@ -476,6 +476,28 @@ def test_dti_shift_localized(self, tzstr): result = dr_tz.shift(1, '10T') assert result.tz == dr_tz.tz + def test_dti_shift_across_dst(self): + # GH 8616 + idx = date_range('2013-11-03', tz='America/Chicago', + periods=7, freq='H') + s = Series(index=idx[:-1]) + result = s.shift(freq='H') + expected = Series(index=idx[1:]) + tm.assert_series_equal(result, expected) + + @pytest.mark.parametrize('shift, result_time', [ + [0, '2014-11-14 00:00:00'], + [-1, '2014-11-13 23:00:00'], + [1, '2014-11-14 01:00:00']]) + def test_dti_shift_near_midnight(self, shift, result_time): + # GH 8616 + dt = datetime(2014, 11, 14, 0) + dt_est = pytz.timezone('EST').localize(dt) + s = Series(data=[1], index=[dt_est]) + result = s.shift(shift, freq='H') + expected = Series(1, index=DatetimeIndex([result_time], tz='EST')) + tm.assert_series_equal(result, expected) + # ------------------------------------------------------------- # Binary operations DatetimeIndex and timedelta-like diff --git a/pandas/tests/scalar/timestamp/test_timestamp.py b/pandas/tests/scalar/timestamp/test_timestamp.py index 4689c7bea626f..8dc9903b7356d 100644 --- a/pandas/tests/scalar/timestamp/test_timestamp.py +++ b/pandas/tests/scalar/timestamp/test_timestamp.py @@ -420,6 +420,12 @@ def test_constructor_nanosecond(self, result): expected = expected + Timedelta(nanoseconds=1) assert result == expected + @pytest.mark.parametrize('z', ['Z0', 'Z00']) + def test_constructor_invalid_Z0_isostring(self, z): + # GH 8910 + with pytest.raises(ValueError): + Timestamp('2014-11-02 01:00{}'.format(z)) + @pytest.mark.parametrize('arg', ['year', 'month', 'day', 'hour', 'minute', 'second', 'microsecond', 'nanosecond']) def test_invalid_date_kwarg_with_string_input(self, arg): diff --git a/pandas/tests/scalar/timestamp/test_unary_ops.py b/pandas/tests/scalar/timestamp/test_unary_ops.py index aecddab8477fc..6f3b5ae6a20a3 100644 --- a/pandas/tests/scalar/timestamp/test_unary_ops.py +++ b/pandas/tests/scalar/timestamp/test_unary_ops.py @@ -238,6 +238,13 @@ def test_replace_across_dst(self, tz, normalize): ts2b = normalize(ts2) assert ts2 == ts2b + def test_replace_dst_border(self): + # Gh 7825 + t = Timestamp('2013-11-3', tz='America/Chicago') + result = t.replace(hour=3) + expected = Timestamp('2013-11-3 03:00:00', tz='America/Chicago') + assert result == expected + # -------------------------------------------------------------- @td.skip_if_windows diff --git a/pandas/tests/series/indexing/test_alter_index.py b/pandas/tests/series/indexing/test_alter_index.py index 999ed5f26daee..bcd5a64402c33 100644 --- a/pandas/tests/series/indexing/test_alter_index.py +++ b/pandas/tests/series/indexing/test_alter_index.py @@ -453,6 +453,15 @@ def test_reindex_fill_value(): assert_series_equal(result, expected) +def test_reindex_datetimeindexes_tz_naive_and_aware(): + # GH 8306 + idx = date_range('20131101', tz='America/Chicago', periods=7) + newidx = date_range('20131103', periods=10, freq='H') + s = Series(range(7), index=idx) + with pytest.raises(TypeError): + s.reindex(newidx, method='ffill') + + def test_rename(): # GH 17407 s = Series(range(1, 6), index=pd.Index(range(2, 7), name='IntIndex')) diff --git a/pandas/tests/test_resample.py b/pandas/tests/test_resample.py index c1257cce9a9a4..6f0ad0535c6b4 100644 --- a/pandas/tests/test_resample.py +++ b/pandas/tests/test_resample.py @@ -2084,6 +2084,17 @@ def test_resample_dst_anchor(self): freq='D', tz='Europe/Paris')), 'D Frequency') + def test_downsample_across_dst(self): + # GH 8531 + tz = pytz.timezone('Europe/Berlin') + dt = datetime(2014, 10, 26) + dates = date_range(tz.localize(dt), periods=4, freq='2H') + result = Series(5, index=dates).resample('H').mean() + expected = Series([5., np.nan] * 3 + [5.], + index=date_range(tz.localize(dt), periods=7, + freq='H')) + tm.assert_series_equal(result, expected) + def test_resample_with_nat(self): # GH 13020 index = DatetimeIndex([pd.NaT,