done
This commit is contained in:
		| @ -0,0 +1,30 @@ | ||||
| from datetime import timedelta | ||||
|  | ||||
| from pandas import ( | ||||
|     Index, | ||||
|     Timestamp, | ||||
|     date_range, | ||||
|     isna, | ||||
| ) | ||||
|  | ||||
|  | ||||
| class TestAsOf: | ||||
|     def test_asof_partial(self): | ||||
|         index = date_range("2010-01-01", periods=2, freq="ME") | ||||
|         expected = Timestamp("2010-02-28") | ||||
|         result = index.asof("2010-02") | ||||
|         assert result == expected | ||||
|         assert not isinstance(result, Index) | ||||
|  | ||||
|     def test_asof(self): | ||||
|         index = date_range("2020-01-01", periods=10) | ||||
|  | ||||
|         dt = index[0] | ||||
|         assert index.asof(dt) == dt | ||||
|         assert isna(index.asof(dt - timedelta(1))) | ||||
|  | ||||
|         dt = index[-1] | ||||
|         assert index.asof(dt + timedelta(1)) == dt | ||||
|  | ||||
|         dt = index[0].to_pydatetime() | ||||
|         assert isinstance(index.asof(dt), Timestamp) | ||||
| @ -0,0 +1,338 @@ | ||||
| from datetime import datetime | ||||
|  | ||||
| import dateutil | ||||
| import numpy as np | ||||
| import pytest | ||||
| import pytz | ||||
|  | ||||
| import pandas as pd | ||||
| from pandas import ( | ||||
|     DatetimeIndex, | ||||
|     Index, | ||||
|     NaT, | ||||
|     PeriodIndex, | ||||
|     Timestamp, | ||||
|     date_range, | ||||
| ) | ||||
| import pandas._testing as tm | ||||
|  | ||||
|  | ||||
| class TestDatetimeIndex: | ||||
|     @pytest.mark.parametrize("tzstr", ["US/Eastern", "dateutil/US/Eastern"]) | ||||
|     def test_dti_astype_asobject_around_dst_transition(self, tzstr): | ||||
|         # GH#1345 | ||||
|  | ||||
|         # dates around a dst transition | ||||
|         rng = date_range("2/13/2010", "5/6/2010", tz=tzstr) | ||||
|  | ||||
|         objs = rng.astype(object) | ||||
|         for i, x in enumerate(objs): | ||||
|             exval = rng[i] | ||||
|             assert x == exval | ||||
|             assert x.tzinfo == exval.tzinfo | ||||
|  | ||||
|         objs = rng.astype(object) | ||||
|         for i, x in enumerate(objs): | ||||
|             exval = rng[i] | ||||
|             assert x == exval | ||||
|             assert x.tzinfo == exval.tzinfo | ||||
|  | ||||
|     def test_astype(self): | ||||
|         # GH 13149, GH 13209 | ||||
|         idx = DatetimeIndex( | ||||
|             ["2016-05-16", "NaT", NaT, np.nan], dtype="M8[ns]", name="idx" | ||||
|         ) | ||||
|  | ||||
|         result = idx.astype(object) | ||||
|         expected = Index( | ||||
|             [Timestamp("2016-05-16")] + [NaT] * 3, dtype=object, name="idx" | ||||
|         ) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         result = idx.astype(np.int64) | ||||
|         expected = Index( | ||||
|             [1463356800000000000] + [-9223372036854775808] * 3, | ||||
|             dtype=np.int64, | ||||
|             name="idx", | ||||
|         ) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|     def test_astype2(self): | ||||
|         rng = date_range("1/1/2000", periods=10, name="idx") | ||||
|         result = rng.astype("i8") | ||||
|         tm.assert_index_equal(result, Index(rng.asi8, name="idx")) | ||||
|         tm.assert_numpy_array_equal(result.values, rng.asi8) | ||||
|  | ||||
|     def test_astype_uint(self): | ||||
|         arr = date_range("2000", periods=2, name="idx") | ||||
|  | ||||
|         with pytest.raises(TypeError, match=r"Do obj.astype\('int64'\)"): | ||||
|             arr.astype("uint64") | ||||
|         with pytest.raises(TypeError, match=r"Do obj.astype\('int64'\)"): | ||||
|             arr.astype("uint32") | ||||
|  | ||||
|     def test_astype_with_tz(self): | ||||
|         # with tz | ||||
|         rng = date_range("1/1/2000", periods=10, tz="US/Eastern") | ||||
|         msg = "Cannot use .astype to convert from timezone-aware" | ||||
|         with pytest.raises(TypeError, match=msg): | ||||
|             # deprecated | ||||
|             rng.astype("datetime64[ns]") | ||||
|         with pytest.raises(TypeError, match=msg): | ||||
|             # check DatetimeArray while we're here deprecated | ||||
|             rng._data.astype("datetime64[ns]") | ||||
|  | ||||
|     def test_astype_tzaware_to_tzaware(self): | ||||
|         # GH 18951: tz-aware to tz-aware | ||||
|         idx = date_range("20170101", periods=4, tz="US/Pacific") | ||||
|         result = idx.astype("datetime64[ns, US/Eastern]") | ||||
|         expected = date_range("20170101 03:00:00", periods=4, tz="US/Eastern") | ||||
|         tm.assert_index_equal(result, expected) | ||||
|         assert result.freq == expected.freq | ||||
|  | ||||
|     def test_astype_tznaive_to_tzaware(self): | ||||
|         # GH 18951: tz-naive to tz-aware | ||||
|         idx = date_range("20170101", periods=4) | ||||
|         idx = idx._with_freq(None)  # tz_localize does not preserve freq | ||||
|         msg = "Cannot use .astype to convert from timezone-naive" | ||||
|         with pytest.raises(TypeError, match=msg): | ||||
|             # dt64->dt64tz deprecated | ||||
|             idx.astype("datetime64[ns, US/Eastern]") | ||||
|         with pytest.raises(TypeError, match=msg): | ||||
|             # dt64->dt64tz deprecated | ||||
|             idx._data.astype("datetime64[ns, US/Eastern]") | ||||
|  | ||||
|     def test_astype_str_nat(self, using_infer_string): | ||||
|         # GH 13149, GH 13209 | ||||
|         # verify that we are returning NaT as a string (and not unicode) | ||||
|  | ||||
|         idx = DatetimeIndex(["2016-05-16", "NaT", NaT, np.nan]) | ||||
|         result = idx.astype(str) | ||||
|         if using_infer_string: | ||||
|             expected = Index(["2016-05-16", None, None, None], dtype="str") | ||||
|         else: | ||||
|             expected = Index(["2016-05-16", "NaT", "NaT", "NaT"], dtype=object) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|     def test_astype_str(self): | ||||
|         # test astype string - #10442 | ||||
|         dti = date_range("2012-01-01", periods=4, name="test_name") | ||||
|         result = dti.astype(str) | ||||
|         expected = Index( | ||||
|             ["2012-01-01", "2012-01-02", "2012-01-03", "2012-01-04"], | ||||
|             name="test_name", | ||||
|             dtype="str", | ||||
|         ) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|     def test_astype_str_tz_and_name(self): | ||||
|         # test astype string with tz and name | ||||
|         dti = date_range("2012-01-01", periods=3, name="test_name", tz="US/Eastern") | ||||
|         result = dti.astype(str) | ||||
|         expected = Index( | ||||
|             [ | ||||
|                 "2012-01-01 00:00:00-05:00", | ||||
|                 "2012-01-02 00:00:00-05:00", | ||||
|                 "2012-01-03 00:00:00-05:00", | ||||
|             ], | ||||
|             name="test_name", | ||||
|             dtype="str", | ||||
|         ) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|     def test_astype_str_freq_and_name(self): | ||||
|         # test astype string with freqH and name | ||||
|         dti = date_range("1/1/2011", periods=3, freq="h", name="test_name") | ||||
|         result = dti.astype(str) | ||||
|         expected = Index( | ||||
|             ["2011-01-01 00:00:00", "2011-01-01 01:00:00", "2011-01-01 02:00:00"], | ||||
|             name="test_name", | ||||
|             dtype="str", | ||||
|         ) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|     def test_astype_str_freq_and_tz(self): | ||||
|         # test astype string with freqH and timezone | ||||
|         dti = date_range( | ||||
|             "3/6/2012 00:00", periods=2, freq="h", tz="Europe/London", name="test_name" | ||||
|         ) | ||||
|         result = dti.astype(str) | ||||
|         expected = Index( | ||||
|             ["2012-03-06 00:00:00+00:00", "2012-03-06 01:00:00+00:00"], | ||||
|             dtype="str", | ||||
|             name="test_name", | ||||
|         ) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|     def test_astype_datetime64(self): | ||||
|         # GH 13149, GH 13209 | ||||
|         idx = DatetimeIndex( | ||||
|             ["2016-05-16", "NaT", NaT, np.nan], dtype="M8[ns]", name="idx" | ||||
|         ) | ||||
|  | ||||
|         result = idx.astype("datetime64[ns]") | ||||
|         tm.assert_index_equal(result, idx) | ||||
|         assert result is not idx | ||||
|  | ||||
|         result = idx.astype("datetime64[ns]", copy=False) | ||||
|         tm.assert_index_equal(result, idx) | ||||
|         assert result is idx | ||||
|  | ||||
|         idx_tz = DatetimeIndex(["2016-05-16", "NaT", NaT, np.nan], tz="EST", name="idx") | ||||
|         msg = "Cannot use .astype to convert from timezone-aware" | ||||
|         with pytest.raises(TypeError, match=msg): | ||||
|             # dt64tz->dt64 deprecated | ||||
|             result = idx_tz.astype("datetime64[ns]") | ||||
|  | ||||
|     def test_astype_object(self): | ||||
|         rng = date_range("1/1/2000", periods=20) | ||||
|  | ||||
|         casted = rng.astype("O") | ||||
|         exp_values = list(rng) | ||||
|  | ||||
|         tm.assert_index_equal(casted, Index(exp_values, dtype=np.object_)) | ||||
|         assert casted.tolist() == exp_values | ||||
|  | ||||
|     @pytest.mark.parametrize("tz", [None, "Asia/Tokyo"]) | ||||
|     def test_astype_object_tz(self, tz): | ||||
|         idx = date_range(start="2013-01-01", periods=4, freq="ME", name="idx", tz=tz) | ||||
|         expected_list = [ | ||||
|             Timestamp("2013-01-31", tz=tz), | ||||
|             Timestamp("2013-02-28", tz=tz), | ||||
|             Timestamp("2013-03-31", tz=tz), | ||||
|             Timestamp("2013-04-30", tz=tz), | ||||
|         ] | ||||
|         expected = Index(expected_list, dtype=object, name="idx") | ||||
|         result = idx.astype(object) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|         assert idx.tolist() == expected_list | ||||
|  | ||||
|     def test_astype_object_with_nat(self): | ||||
|         idx = DatetimeIndex( | ||||
|             [datetime(2013, 1, 1), datetime(2013, 1, 2), NaT, datetime(2013, 1, 4)], | ||||
|             name="idx", | ||||
|         ) | ||||
|         expected_list = [ | ||||
|             Timestamp("2013-01-01"), | ||||
|             Timestamp("2013-01-02"), | ||||
|             NaT, | ||||
|             Timestamp("2013-01-04"), | ||||
|         ] | ||||
|         expected = Index(expected_list, dtype=object, name="idx") | ||||
|         result = idx.astype(object) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|         assert idx.tolist() == expected_list | ||||
|  | ||||
|     @pytest.mark.parametrize( | ||||
|         "dtype", | ||||
|         [float, "timedelta64", "timedelta64[ns]", "datetime64", "datetime64[D]"], | ||||
|     ) | ||||
|     def test_astype_raises(self, dtype): | ||||
|         # GH 13149, GH 13209 | ||||
|         idx = DatetimeIndex(["2016-05-16", "NaT", NaT, np.nan]) | ||||
|         msg = "Cannot cast DatetimeIndex to dtype" | ||||
|         if dtype == "datetime64": | ||||
|             msg = "Casting to unit-less dtype 'datetime64' is not supported" | ||||
|         with pytest.raises(TypeError, match=msg): | ||||
|             idx.astype(dtype) | ||||
|  | ||||
|     def test_index_convert_to_datetime_array(self): | ||||
|         def _check_rng(rng): | ||||
|             converted = rng.to_pydatetime() | ||||
|             assert isinstance(converted, np.ndarray) | ||||
|             for x, stamp in zip(converted, rng): | ||||
|                 assert isinstance(x, datetime) | ||||
|                 assert x == stamp.to_pydatetime() | ||||
|                 assert x.tzinfo == stamp.tzinfo | ||||
|  | ||||
|         rng = date_range("20090415", "20090519") | ||||
|         rng_eastern = date_range("20090415", "20090519", tz="US/Eastern") | ||||
|         rng_utc = date_range("20090415", "20090519", tz="utc") | ||||
|  | ||||
|         _check_rng(rng) | ||||
|         _check_rng(rng_eastern) | ||||
|         _check_rng(rng_utc) | ||||
|  | ||||
|     def test_index_convert_to_datetime_array_explicit_pytz(self): | ||||
|         def _check_rng(rng): | ||||
|             converted = rng.to_pydatetime() | ||||
|             assert isinstance(converted, np.ndarray) | ||||
|             for x, stamp in zip(converted, rng): | ||||
|                 assert isinstance(x, datetime) | ||||
|                 assert x == stamp.to_pydatetime() | ||||
|                 assert x.tzinfo == stamp.tzinfo | ||||
|  | ||||
|         rng = date_range("20090415", "20090519") | ||||
|         rng_eastern = date_range("20090415", "20090519", tz=pytz.timezone("US/Eastern")) | ||||
|         rng_utc = date_range("20090415", "20090519", tz=pytz.utc) | ||||
|  | ||||
|         _check_rng(rng) | ||||
|         _check_rng(rng_eastern) | ||||
|         _check_rng(rng_utc) | ||||
|  | ||||
|     def test_index_convert_to_datetime_array_dateutil(self): | ||||
|         def _check_rng(rng): | ||||
|             converted = rng.to_pydatetime() | ||||
|             assert isinstance(converted, np.ndarray) | ||||
|             for x, stamp in zip(converted, rng): | ||||
|                 assert isinstance(x, datetime) | ||||
|                 assert x == stamp.to_pydatetime() | ||||
|                 assert x.tzinfo == stamp.tzinfo | ||||
|  | ||||
|         rng = date_range("20090415", "20090519") | ||||
|         rng_eastern = date_range("20090415", "20090519", tz="dateutil/US/Eastern") | ||||
|         rng_utc = date_range("20090415", "20090519", tz=dateutil.tz.tzutc()) | ||||
|  | ||||
|         _check_rng(rng) | ||||
|         _check_rng(rng_eastern) | ||||
|         _check_rng(rng_utc) | ||||
|  | ||||
|     @pytest.mark.parametrize( | ||||
|         "tz, dtype", | ||||
|         [["US/Pacific", "datetime64[ns, US/Pacific]"], [None, "datetime64[ns]"]], | ||||
|     ) | ||||
|     def test_integer_index_astype_datetime(self, tz, dtype): | ||||
|         # GH 20997, 20964, 24559 | ||||
|         val = [Timestamp("2018-01-01", tz=tz).as_unit("ns")._value] | ||||
|         result = Index(val, name="idx").astype(dtype) | ||||
|         expected = DatetimeIndex(["2018-01-01"], tz=tz, name="idx").as_unit("ns") | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|     def test_dti_astype_period(self): | ||||
|         idx = DatetimeIndex([NaT, "2011-01-01", "2011-02-01"], name="idx") | ||||
|  | ||||
|         res = idx.astype("period[M]") | ||||
|         exp = PeriodIndex(["NaT", "2011-01", "2011-02"], freq="M", name="idx") | ||||
|         tm.assert_index_equal(res, exp) | ||||
|  | ||||
|         res = idx.astype("period[3M]") | ||||
|         exp = PeriodIndex(["NaT", "2011-01", "2011-02"], freq="3M", name="idx") | ||||
|         tm.assert_index_equal(res, exp) | ||||
|  | ||||
|  | ||||
| class TestAstype: | ||||
|     @pytest.mark.parametrize("tz", [None, "US/Central"]) | ||||
|     def test_astype_category(self, tz): | ||||
|         obj = date_range("2000", periods=2, tz=tz, name="idx") | ||||
|         result = obj.astype("category") | ||||
|         dti = DatetimeIndex(["2000-01-01", "2000-01-02"], tz=tz).as_unit("ns") | ||||
|         expected = pd.CategoricalIndex( | ||||
|             dti, | ||||
|             name="idx", | ||||
|         ) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         result = obj._data.astype("category") | ||||
|         expected = expected.values | ||||
|         tm.assert_categorical_equal(result, expected) | ||||
|  | ||||
|     @pytest.mark.parametrize("tz", [None, "US/Central"]) | ||||
|     def test_astype_array_fallback(self, tz): | ||||
|         obj = date_range("2000", periods=2, tz=tz, name="idx") | ||||
|         result = obj.astype(bool) | ||||
|         expected = Index(np.array([True, True]), name="idx") | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         result = obj._data.astype(bool) | ||||
|         expected = np.array([True, True]) | ||||
|         tm.assert_numpy_array_equal(result, expected) | ||||
| @ -0,0 +1,141 @@ | ||||
| import pytest | ||||
|  | ||||
| from pandas import ( | ||||
|     DatetimeIndex, | ||||
|     Series, | ||||
|     date_range, | ||||
| ) | ||||
| import pandas._testing as tm | ||||
|  | ||||
|  | ||||
| class TestDelete: | ||||
|     def test_delete(self, unit): | ||||
|         idx = date_range( | ||||
|             start="2000-01-01", periods=5, freq="ME", name="idx", unit=unit | ||||
|         ) | ||||
|  | ||||
|         # preserve freq | ||||
|         expected_0 = date_range( | ||||
|             start="2000-02-01", periods=4, freq="ME", name="idx", unit=unit | ||||
|         ) | ||||
|         expected_4 = date_range( | ||||
|             start="2000-01-01", periods=4, freq="ME", name="idx", unit=unit | ||||
|         ) | ||||
|  | ||||
|         # reset freq to None | ||||
|         expected_1 = DatetimeIndex( | ||||
|             ["2000-01-31", "2000-03-31", "2000-04-30", "2000-05-31"], | ||||
|             freq=None, | ||||
|             name="idx", | ||||
|         ).as_unit(unit) | ||||
|  | ||||
|         cases = { | ||||
|             0: expected_0, | ||||
|             -5: expected_0, | ||||
|             -1: expected_4, | ||||
|             4: expected_4, | ||||
|             1: expected_1, | ||||
|         } | ||||
|         for n, expected in cases.items(): | ||||
|             result = idx.delete(n) | ||||
|             tm.assert_index_equal(result, expected) | ||||
|             assert result.name == expected.name | ||||
|             assert result.freq == expected.freq | ||||
|  | ||||
|         with pytest.raises((IndexError, ValueError), match="out of bounds"): | ||||
|             # either depending on numpy version | ||||
|             idx.delete(5) | ||||
|  | ||||
|     @pytest.mark.parametrize("tz", [None, "Asia/Tokyo", "US/Pacific"]) | ||||
|     def test_delete2(self, tz): | ||||
|         idx = date_range( | ||||
|             start="2000-01-01 09:00", periods=10, freq="h", name="idx", tz=tz | ||||
|         ) | ||||
|  | ||||
|         expected = date_range( | ||||
|             start="2000-01-01 10:00", periods=9, freq="h", name="idx", tz=tz | ||||
|         ) | ||||
|         result = idx.delete(0) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|         assert result.name == expected.name | ||||
|         assert result.freqstr == "h" | ||||
|         assert result.tz == expected.tz | ||||
|  | ||||
|         expected = date_range( | ||||
|             start="2000-01-01 09:00", periods=9, freq="h", name="idx", tz=tz | ||||
|         ) | ||||
|         result = idx.delete(-1) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|         assert result.name == expected.name | ||||
|         assert result.freqstr == "h" | ||||
|         assert result.tz == expected.tz | ||||
|  | ||||
|     def test_delete_slice(self, unit): | ||||
|         idx = date_range( | ||||
|             start="2000-01-01", periods=10, freq="D", name="idx", unit=unit | ||||
|         ) | ||||
|  | ||||
|         # preserve freq | ||||
|         expected_0_2 = date_range( | ||||
|             start="2000-01-04", periods=7, freq="D", name="idx", unit=unit | ||||
|         ) | ||||
|         expected_7_9 = date_range( | ||||
|             start="2000-01-01", periods=7, freq="D", name="idx", unit=unit | ||||
|         ) | ||||
|  | ||||
|         # reset freq to None | ||||
|         expected_3_5 = DatetimeIndex( | ||||
|             [ | ||||
|                 "2000-01-01", | ||||
|                 "2000-01-02", | ||||
|                 "2000-01-03", | ||||
|                 "2000-01-07", | ||||
|                 "2000-01-08", | ||||
|                 "2000-01-09", | ||||
|                 "2000-01-10", | ||||
|             ], | ||||
|             freq=None, | ||||
|             name="idx", | ||||
|         ).as_unit(unit) | ||||
|  | ||||
|         cases = { | ||||
|             (0, 1, 2): expected_0_2, | ||||
|             (7, 8, 9): expected_7_9, | ||||
|             (3, 4, 5): expected_3_5, | ||||
|         } | ||||
|         for n, expected in cases.items(): | ||||
|             result = idx.delete(n) | ||||
|             tm.assert_index_equal(result, expected) | ||||
|             assert result.name == expected.name | ||||
|             assert result.freq == expected.freq | ||||
|  | ||||
|             result = idx.delete(slice(n[0], n[-1] + 1)) | ||||
|             tm.assert_index_equal(result, expected) | ||||
|             assert result.name == expected.name | ||||
|             assert result.freq == expected.freq | ||||
|  | ||||
|     # TODO: belongs in Series.drop tests? | ||||
|     @pytest.mark.parametrize("tz", [None, "Asia/Tokyo", "US/Pacific"]) | ||||
|     def test_delete_slice2(self, tz, unit): | ||||
|         dti = date_range( | ||||
|             "2000-01-01 09:00", periods=10, freq="h", name="idx", tz=tz, unit=unit | ||||
|         ) | ||||
|         ts = Series( | ||||
|             1, | ||||
|             index=dti, | ||||
|         ) | ||||
|         # preserve freq | ||||
|         result = ts.drop(ts.index[:5]).index | ||||
|         expected = dti[5:] | ||||
|         tm.assert_index_equal(result, expected) | ||||
|         assert result.name == expected.name | ||||
|         assert result.freq == expected.freq | ||||
|         assert result.tz == expected.tz | ||||
|  | ||||
|         # reset freq to None | ||||
|         result = ts.drop(ts.index[[1, 3, 5, 7, 9]]).index | ||||
|         expected = dti[::2]._with_freq(None) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|         assert result.name == expected.name | ||||
|         assert result.freq == expected.freq | ||||
|         assert result.tz == expected.tz | ||||
| @ -0,0 +1,125 @@ | ||||
| import numpy as np | ||||
| import pytest | ||||
|  | ||||
| from pandas import ( | ||||
|     DatetimeIndex, | ||||
|     Index, | ||||
|     date_range, | ||||
|     factorize, | ||||
| ) | ||||
| import pandas._testing as tm | ||||
|  | ||||
|  | ||||
| class TestDatetimeIndexFactorize: | ||||
|     def test_factorize(self): | ||||
|         idx1 = DatetimeIndex( | ||||
|             ["2014-01", "2014-01", "2014-02", "2014-02", "2014-03", "2014-03"] | ||||
|         ) | ||||
|  | ||||
|         exp_arr = np.array([0, 0, 1, 1, 2, 2], dtype=np.intp) | ||||
|         exp_idx = DatetimeIndex(["2014-01", "2014-02", "2014-03"]) | ||||
|  | ||||
|         arr, idx = idx1.factorize() | ||||
|         tm.assert_numpy_array_equal(arr, exp_arr) | ||||
|         tm.assert_index_equal(idx, exp_idx) | ||||
|         assert idx.freq == exp_idx.freq | ||||
|  | ||||
|         arr, idx = idx1.factorize(sort=True) | ||||
|         tm.assert_numpy_array_equal(arr, exp_arr) | ||||
|         tm.assert_index_equal(idx, exp_idx) | ||||
|         assert idx.freq == exp_idx.freq | ||||
|  | ||||
|         # tz must be preserved | ||||
|         idx1 = idx1.tz_localize("Asia/Tokyo") | ||||
|         exp_idx = exp_idx.tz_localize("Asia/Tokyo") | ||||
|  | ||||
|         arr, idx = idx1.factorize() | ||||
|         tm.assert_numpy_array_equal(arr, exp_arr) | ||||
|         tm.assert_index_equal(idx, exp_idx) | ||||
|         assert idx.freq == exp_idx.freq | ||||
|  | ||||
|         idx2 = DatetimeIndex( | ||||
|             ["2014-03", "2014-03", "2014-02", "2014-01", "2014-03", "2014-01"] | ||||
|         ) | ||||
|  | ||||
|         exp_arr = np.array([2, 2, 1, 0, 2, 0], dtype=np.intp) | ||||
|         exp_idx = DatetimeIndex(["2014-01", "2014-02", "2014-03"]) | ||||
|         arr, idx = idx2.factorize(sort=True) | ||||
|         tm.assert_numpy_array_equal(arr, exp_arr) | ||||
|         tm.assert_index_equal(idx, exp_idx) | ||||
|         assert idx.freq == exp_idx.freq | ||||
|  | ||||
|         exp_arr = np.array([0, 0, 1, 2, 0, 2], dtype=np.intp) | ||||
|         exp_idx = DatetimeIndex(["2014-03", "2014-02", "2014-01"]) | ||||
|         arr, idx = idx2.factorize() | ||||
|         tm.assert_numpy_array_equal(arr, exp_arr) | ||||
|         tm.assert_index_equal(idx, exp_idx) | ||||
|         assert idx.freq == exp_idx.freq | ||||
|  | ||||
|     def test_factorize_preserves_freq(self): | ||||
|         # GH#38120 freq should be preserved | ||||
|         idx3 = date_range("2000-01", periods=4, freq="ME", tz="Asia/Tokyo") | ||||
|         exp_arr = np.array([0, 1, 2, 3], dtype=np.intp) | ||||
|  | ||||
|         arr, idx = idx3.factorize() | ||||
|         tm.assert_numpy_array_equal(arr, exp_arr) | ||||
|         tm.assert_index_equal(idx, idx3) | ||||
|         assert idx.freq == idx3.freq | ||||
|  | ||||
|         arr, idx = factorize(idx3) | ||||
|         tm.assert_numpy_array_equal(arr, exp_arr) | ||||
|         tm.assert_index_equal(idx, idx3) | ||||
|         assert idx.freq == idx3.freq | ||||
|  | ||||
|     def test_factorize_tz(self, tz_naive_fixture, index_or_series): | ||||
|         tz = tz_naive_fixture | ||||
|         # GH#13750 | ||||
|         base = date_range("2016-11-05", freq="h", periods=100, tz=tz) | ||||
|         idx = base.repeat(5) | ||||
|  | ||||
|         exp_arr = np.arange(100, dtype=np.intp).repeat(5) | ||||
|  | ||||
|         obj = index_or_series(idx) | ||||
|  | ||||
|         arr, res = obj.factorize() | ||||
|         tm.assert_numpy_array_equal(arr, exp_arr) | ||||
|         expected = base._with_freq(None) | ||||
|         tm.assert_index_equal(res, expected) | ||||
|         assert res.freq == expected.freq | ||||
|  | ||||
|     def test_factorize_dst(self, index_or_series): | ||||
|         # GH#13750 | ||||
|         idx = date_range("2016-11-06", freq="h", periods=12, tz="US/Eastern") | ||||
|         obj = index_or_series(idx) | ||||
|  | ||||
|         arr, res = obj.factorize() | ||||
|         tm.assert_numpy_array_equal(arr, np.arange(12, dtype=np.intp)) | ||||
|         tm.assert_index_equal(res, idx) | ||||
|         if index_or_series is Index: | ||||
|             assert res.freq == idx.freq | ||||
|  | ||||
|         idx = date_range("2016-06-13", freq="h", periods=12, tz="US/Eastern") | ||||
|         obj = index_or_series(idx) | ||||
|  | ||||
|         arr, res = obj.factorize() | ||||
|         tm.assert_numpy_array_equal(arr, np.arange(12, dtype=np.intp)) | ||||
|         tm.assert_index_equal(res, idx) | ||||
|         if index_or_series is Index: | ||||
|             assert res.freq == idx.freq | ||||
|  | ||||
|     @pytest.mark.parametrize("sort", [True, False]) | ||||
|     def test_factorize_no_freq_non_nano(self, tz_naive_fixture, sort): | ||||
|         # GH#51978 case that does not go through the fastpath based on | ||||
|         #  non-None freq | ||||
|         tz = tz_naive_fixture | ||||
|         idx = date_range("2016-11-06", freq="h", periods=5, tz=tz)[[0, 4, 1, 3, 2]] | ||||
|         exp_codes, exp_uniques = idx.factorize(sort=sort) | ||||
|  | ||||
|         res_codes, res_uniques = idx.as_unit("s").factorize(sort=sort) | ||||
|  | ||||
|         tm.assert_numpy_array_equal(res_codes, exp_codes) | ||||
|         tm.assert_index_equal(res_uniques, exp_uniques.as_unit("s")) | ||||
|  | ||||
|         res_codes, res_uniques = idx.as_unit("s").to_series().factorize(sort=sort) | ||||
|         tm.assert_numpy_array_equal(res_codes, exp_codes) | ||||
|         tm.assert_index_equal(res_uniques, exp_uniques.as_unit("s")) | ||||
| @ -0,0 +1,62 @@ | ||||
| import pytest | ||||
|  | ||||
| import pandas as pd | ||||
| import pandas._testing as tm | ||||
|  | ||||
|  | ||||
| class TestDatetimeIndexFillNA: | ||||
|     @pytest.mark.parametrize("tz", ["US/Eastern", "Asia/Tokyo"]) | ||||
|     def test_fillna_datetime64(self, tz): | ||||
|         # GH 11343 | ||||
|         idx = pd.DatetimeIndex(["2011-01-01 09:00", pd.NaT, "2011-01-01 11:00"]) | ||||
|  | ||||
|         exp = pd.DatetimeIndex( | ||||
|             ["2011-01-01 09:00", "2011-01-01 10:00", "2011-01-01 11:00"] | ||||
|         ) | ||||
|         tm.assert_index_equal(idx.fillna(pd.Timestamp("2011-01-01 10:00")), exp) | ||||
|  | ||||
|         # tz mismatch | ||||
|         exp = pd.Index( | ||||
|             [ | ||||
|                 pd.Timestamp("2011-01-01 09:00"), | ||||
|                 pd.Timestamp("2011-01-01 10:00", tz=tz), | ||||
|                 pd.Timestamp("2011-01-01 11:00"), | ||||
|             ], | ||||
|             dtype=object, | ||||
|         ) | ||||
|         tm.assert_index_equal(idx.fillna(pd.Timestamp("2011-01-01 10:00", tz=tz)), exp) | ||||
|  | ||||
|         # object | ||||
|         exp = pd.Index( | ||||
|             [pd.Timestamp("2011-01-01 09:00"), "x", pd.Timestamp("2011-01-01 11:00")], | ||||
|             dtype=object, | ||||
|         ) | ||||
|         tm.assert_index_equal(idx.fillna("x"), exp) | ||||
|  | ||||
|         idx = pd.DatetimeIndex(["2011-01-01 09:00", pd.NaT, "2011-01-01 11:00"], tz=tz) | ||||
|  | ||||
|         exp = pd.DatetimeIndex( | ||||
|             ["2011-01-01 09:00", "2011-01-01 10:00", "2011-01-01 11:00"], tz=tz | ||||
|         ) | ||||
|         tm.assert_index_equal(idx.fillna(pd.Timestamp("2011-01-01 10:00", tz=tz)), exp) | ||||
|  | ||||
|         exp = pd.Index( | ||||
|             [ | ||||
|                 pd.Timestamp("2011-01-01 09:00", tz=tz), | ||||
|                 pd.Timestamp("2011-01-01 10:00"), | ||||
|                 pd.Timestamp("2011-01-01 11:00", tz=tz), | ||||
|             ], | ||||
|             dtype=object, | ||||
|         ) | ||||
|         tm.assert_index_equal(idx.fillna(pd.Timestamp("2011-01-01 10:00")), exp) | ||||
|  | ||||
|         # object | ||||
|         exp = pd.Index( | ||||
|             [ | ||||
|                 pd.Timestamp("2011-01-01 09:00", tz=tz), | ||||
|                 "x", | ||||
|                 pd.Timestamp("2011-01-01 11:00", tz=tz), | ||||
|             ], | ||||
|             dtype=object, | ||||
|         ) | ||||
|         tm.assert_index_equal(idx.fillna("x"), exp) | ||||
| @ -0,0 +1,265 @@ | ||||
| from datetime import datetime | ||||
|  | ||||
| import numpy as np | ||||
| import pytest | ||||
| import pytz | ||||
|  | ||||
| from pandas import ( | ||||
|     NA, | ||||
|     DatetimeIndex, | ||||
|     Index, | ||||
|     NaT, | ||||
|     Timestamp, | ||||
|     date_range, | ||||
| ) | ||||
| import pandas._testing as tm | ||||
|  | ||||
|  | ||||
| class TestInsert: | ||||
|     @pytest.mark.parametrize("null", [None, np.nan, np.datetime64("NaT"), NaT, NA]) | ||||
|     @pytest.mark.parametrize("tz", [None, "UTC", "US/Eastern"]) | ||||
|     def test_insert_nat(self, tz, null): | ||||
|         # GH#16537, GH#18295 (test missing) | ||||
|  | ||||
|         idx = DatetimeIndex(["2017-01-01"], tz=tz) | ||||
|         expected = DatetimeIndex(["NaT", "2017-01-01"], tz=tz) | ||||
|         if tz is not None and isinstance(null, np.datetime64): | ||||
|             expected = Index([null, idx[0]], dtype=object) | ||||
|  | ||||
|         res = idx.insert(0, null) | ||||
|         tm.assert_index_equal(res, expected) | ||||
|  | ||||
|     @pytest.mark.parametrize("tz", [None, "UTC", "US/Eastern"]) | ||||
|     def test_insert_invalid_na(self, tz): | ||||
|         idx = DatetimeIndex(["2017-01-01"], tz=tz) | ||||
|  | ||||
|         item = np.timedelta64("NaT") | ||||
|         result = idx.insert(0, item) | ||||
|         expected = Index([item] + list(idx), dtype=object) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|     def test_insert_empty_preserves_freq(self, tz_naive_fixture): | ||||
|         # GH#33573 | ||||
|         tz = tz_naive_fixture | ||||
|         dti = DatetimeIndex([], tz=tz, freq="D") | ||||
|         item = Timestamp("2017-04-05").tz_localize(tz) | ||||
|  | ||||
|         result = dti.insert(0, item) | ||||
|         assert result.freq == dti.freq | ||||
|  | ||||
|         # But not when we insert an item that doesn't conform to freq | ||||
|         dti = DatetimeIndex([], tz=tz, freq="W-THU") | ||||
|         result = dti.insert(0, item) | ||||
|         assert result.freq is None | ||||
|  | ||||
|     def test_insert(self, unit): | ||||
|         idx = DatetimeIndex( | ||||
|             ["2000-01-04", "2000-01-01", "2000-01-02"], name="idx" | ||||
|         ).as_unit(unit) | ||||
|  | ||||
|         result = idx.insert(2, datetime(2000, 1, 5)) | ||||
|         exp = DatetimeIndex( | ||||
|             ["2000-01-04", "2000-01-01", "2000-01-05", "2000-01-02"], name="idx" | ||||
|         ).as_unit(unit) | ||||
|         tm.assert_index_equal(result, exp) | ||||
|  | ||||
|         # insertion of non-datetime should coerce to object index | ||||
|         result = idx.insert(1, "inserted") | ||||
|         expected = Index( | ||||
|             [ | ||||
|                 datetime(2000, 1, 4), | ||||
|                 "inserted", | ||||
|                 datetime(2000, 1, 1), | ||||
|                 datetime(2000, 1, 2), | ||||
|             ], | ||||
|             name="idx", | ||||
|         ) | ||||
|         assert not isinstance(result, DatetimeIndex) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|         assert result.name == expected.name | ||||
|  | ||||
|     def test_insert2(self, unit): | ||||
|         idx = date_range("1/1/2000", periods=3, freq="ME", name="idx", unit=unit) | ||||
|  | ||||
|         # preserve freq | ||||
|         expected_0 = DatetimeIndex( | ||||
|             ["1999-12-31", "2000-01-31", "2000-02-29", "2000-03-31"], | ||||
|             name="idx", | ||||
|             freq="ME", | ||||
|         ).as_unit(unit) | ||||
|         expected_3 = DatetimeIndex( | ||||
|             ["2000-01-31", "2000-02-29", "2000-03-31", "2000-04-30"], | ||||
|             name="idx", | ||||
|             freq="ME", | ||||
|         ).as_unit(unit) | ||||
|  | ||||
|         # reset freq to None | ||||
|         expected_1_nofreq = DatetimeIndex( | ||||
|             ["2000-01-31", "2000-01-31", "2000-02-29", "2000-03-31"], | ||||
|             name="idx", | ||||
|             freq=None, | ||||
|         ).as_unit(unit) | ||||
|         expected_3_nofreq = DatetimeIndex( | ||||
|             ["2000-01-31", "2000-02-29", "2000-03-31", "2000-01-02"], | ||||
|             name="idx", | ||||
|             freq=None, | ||||
|         ).as_unit(unit) | ||||
|  | ||||
|         cases = [ | ||||
|             (0, datetime(1999, 12, 31), expected_0), | ||||
|             (-3, datetime(1999, 12, 31), expected_0), | ||||
|             (3, datetime(2000, 4, 30), expected_3), | ||||
|             (1, datetime(2000, 1, 31), expected_1_nofreq), | ||||
|             (3, datetime(2000, 1, 2), expected_3_nofreq), | ||||
|         ] | ||||
|  | ||||
|         for n, d, expected in cases: | ||||
|             result = idx.insert(n, d) | ||||
|             tm.assert_index_equal(result, expected) | ||||
|             assert result.name == expected.name | ||||
|             assert result.freq == expected.freq | ||||
|  | ||||
|     def test_insert3(self, unit): | ||||
|         idx = date_range("1/1/2000", periods=3, freq="ME", name="idx", unit=unit) | ||||
|  | ||||
|         # reset freq to None | ||||
|         result = idx.insert(3, datetime(2000, 1, 2)) | ||||
|         expected = DatetimeIndex( | ||||
|             ["2000-01-31", "2000-02-29", "2000-03-31", "2000-01-02"], | ||||
|             name="idx", | ||||
|             freq=None, | ||||
|         ).as_unit(unit) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|         assert result.name == expected.name | ||||
|         assert result.freq is None | ||||
|  | ||||
|     def test_insert4(self, unit): | ||||
|         for tz in ["US/Pacific", "Asia/Singapore"]: | ||||
|             idx = date_range( | ||||
|                 "1/1/2000 09:00", periods=6, freq="h", tz=tz, name="idx", unit=unit | ||||
|             ) | ||||
|             # preserve freq | ||||
|             expected = date_range( | ||||
|                 "1/1/2000 09:00", periods=7, freq="h", tz=tz, name="idx", unit=unit | ||||
|             ) | ||||
|             for d in [ | ||||
|                 Timestamp("2000-01-01 15:00", tz=tz), | ||||
|                 pytz.timezone(tz).localize(datetime(2000, 1, 1, 15)), | ||||
|             ]: | ||||
|                 result = idx.insert(6, d) | ||||
|                 tm.assert_index_equal(result, expected) | ||||
|                 assert result.name == expected.name | ||||
|                 assert result.freq == expected.freq | ||||
|                 assert result.tz == expected.tz | ||||
|  | ||||
|             expected = DatetimeIndex( | ||||
|                 [ | ||||
|                     "2000-01-01 09:00", | ||||
|                     "2000-01-01 10:00", | ||||
|                     "2000-01-01 11:00", | ||||
|                     "2000-01-01 12:00", | ||||
|                     "2000-01-01 13:00", | ||||
|                     "2000-01-01 14:00", | ||||
|                     "2000-01-01 10:00", | ||||
|                 ], | ||||
|                 name="idx", | ||||
|                 tz=tz, | ||||
|                 freq=None, | ||||
|             ).as_unit(unit) | ||||
|             # reset freq to None | ||||
|             for d in [ | ||||
|                 Timestamp("2000-01-01 10:00", tz=tz), | ||||
|                 pytz.timezone(tz).localize(datetime(2000, 1, 1, 10)), | ||||
|             ]: | ||||
|                 result = idx.insert(6, d) | ||||
|                 tm.assert_index_equal(result, expected) | ||||
|                 assert result.name == expected.name | ||||
|                 assert result.tz == expected.tz | ||||
|                 assert result.freq is None | ||||
|  | ||||
|     # TODO: also changes DataFrame.__setitem__ with expansion | ||||
|     def test_insert_mismatched_tzawareness(self): | ||||
|         # see GH#7299 | ||||
|         idx = date_range("1/1/2000", periods=3, freq="D", tz="Asia/Tokyo", name="idx") | ||||
|  | ||||
|         # mismatched tz-awareness | ||||
|         item = Timestamp("2000-01-04") | ||||
|         result = idx.insert(3, item) | ||||
|         expected = Index( | ||||
|             list(idx[:3]) + [item] + list(idx[3:]), dtype=object, name="idx" | ||||
|         ) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         # mismatched tz-awareness | ||||
|         item = datetime(2000, 1, 4) | ||||
|         result = idx.insert(3, item) | ||||
|         expected = Index( | ||||
|             list(idx[:3]) + [item] + list(idx[3:]), dtype=object, name="idx" | ||||
|         ) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|     # TODO: also changes DataFrame.__setitem__ with expansion | ||||
|     def test_insert_mismatched_tz(self): | ||||
|         # see GH#7299 | ||||
|         # pre-2.0 with mismatched tzs we would cast to object | ||||
|         idx = date_range("1/1/2000", periods=3, freq="D", tz="Asia/Tokyo", name="idx") | ||||
|  | ||||
|         # mismatched tz -> cast to object (could reasonably cast to same tz or UTC) | ||||
|         item = Timestamp("2000-01-04", tz="US/Eastern") | ||||
|         result = idx.insert(3, item) | ||||
|         expected = Index( | ||||
|             list(idx[:3]) + [item.tz_convert(idx.tz)] + list(idx[3:]), | ||||
|             name="idx", | ||||
|         ) | ||||
|         assert expected.dtype == idx.dtype | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         item = datetime(2000, 1, 4, tzinfo=pytz.timezone("US/Eastern")) | ||||
|         result = idx.insert(3, item) | ||||
|         expected = Index( | ||||
|             list(idx[:3]) + [item.astimezone(idx.tzinfo)] + list(idx[3:]), | ||||
|             name="idx", | ||||
|         ) | ||||
|         assert expected.dtype == idx.dtype | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|     @pytest.mark.parametrize( | ||||
|         "item", [0, np.int64(0), np.float64(0), np.array(0), np.timedelta64(456)] | ||||
|     ) | ||||
|     def test_insert_mismatched_types_raises(self, tz_aware_fixture, item): | ||||
|         # GH#33703 dont cast these to dt64 | ||||
|         tz = tz_aware_fixture | ||||
|         dti = date_range("2019-11-04", periods=9, freq="-1D", name=9, tz=tz) | ||||
|  | ||||
|         result = dti.insert(1, item) | ||||
|  | ||||
|         if isinstance(item, np.ndarray): | ||||
|             assert item.item() == 0 | ||||
|             expected = Index([dti[0], 0] + list(dti[1:]), dtype=object, name=9) | ||||
|         else: | ||||
|             expected = Index([dti[0], item] + list(dti[1:]), dtype=object, name=9) | ||||
|  | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|     def test_insert_castable_str(self, tz_aware_fixture): | ||||
|         # GH#33703 | ||||
|         tz = tz_aware_fixture | ||||
|         dti = date_range("2019-11-04", periods=3, freq="-1D", name=9, tz=tz) | ||||
|  | ||||
|         value = "2019-11-05" | ||||
|         result = dti.insert(0, value) | ||||
|  | ||||
|         ts = Timestamp(value).tz_localize(tz) | ||||
|         expected = DatetimeIndex([ts] + list(dti), dtype=dti.dtype, name=9) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|     def test_insert_non_castable_str(self, tz_aware_fixture): | ||||
|         # GH#33703 | ||||
|         tz = tz_aware_fixture | ||||
|         dti = date_range("2019-11-04", periods=3, freq="-1D", name=9, tz=tz) | ||||
|  | ||||
|         value = "foo" | ||||
|         result = dti.insert(0, value) | ||||
|  | ||||
|         expected = Index(["foo"] + list(dti), dtype=object, name=9) | ||||
|         tm.assert_index_equal(result, expected) | ||||
| @ -0,0 +1,28 @@ | ||||
| from pandas import ( | ||||
|     DataFrame, | ||||
|     DatetimeIndex, | ||||
|     date_range, | ||||
| ) | ||||
| import pandas._testing as tm | ||||
|  | ||||
|  | ||||
| def test_isocalendar_returns_correct_values_close_to_new_year_with_tz(): | ||||
|     # GH#6538: Check that DatetimeIndex and its TimeStamp elements | ||||
|     # return the same weekofyear accessor close to new year w/ tz | ||||
|     dates = ["2013/12/29", "2013/12/30", "2013/12/31"] | ||||
|     dates = DatetimeIndex(dates, tz="Europe/Brussels") | ||||
|     result = dates.isocalendar() | ||||
|     expected_data_frame = DataFrame( | ||||
|         [[2013, 52, 7], [2014, 1, 1], [2014, 1, 2]], | ||||
|         columns=["year", "week", "day"], | ||||
|         index=dates, | ||||
|         dtype="UInt32", | ||||
|     ) | ||||
|     tm.assert_frame_equal(result, expected_data_frame) | ||||
|  | ||||
|  | ||||
| def test_dti_timestamp_isocalendar_fields(): | ||||
|     idx = date_range("2020-01-01", periods=10) | ||||
|     expected = tuple(idx.isocalendar().iloc[-1].to_list()) | ||||
|     result = idx[-1].isocalendar() | ||||
|     assert result == expected | ||||
| @ -0,0 +1,47 @@ | ||||
| import pytest | ||||
|  | ||||
| from pandas import ( | ||||
|     DatetimeIndex, | ||||
|     Index, | ||||
|     MultiIndex, | ||||
|     Period, | ||||
|     date_range, | ||||
| ) | ||||
| import pandas._testing as tm | ||||
|  | ||||
|  | ||||
| class TestMap: | ||||
|     def test_map(self): | ||||
|         rng = date_range("1/1/2000", periods=10) | ||||
|  | ||||
|         f = lambda x: x.strftime("%Y%m%d") | ||||
|         result = rng.map(f) | ||||
|         exp = Index([f(x) for x in rng]) | ||||
|         tm.assert_index_equal(result, exp) | ||||
|  | ||||
|     def test_map_fallthrough(self, capsys): | ||||
|         # GH#22067, check we don't get warnings about silently ignored errors | ||||
|         dti = date_range("2017-01-01", "2018-01-01", freq="B") | ||||
|  | ||||
|         dti.map(lambda x: Period(year=x.year, month=x.month, freq="M")) | ||||
|  | ||||
|         captured = capsys.readouterr() | ||||
|         assert captured.err == "" | ||||
|  | ||||
|     def test_map_bug_1677(self): | ||||
|         index = DatetimeIndex(["2012-04-25 09:30:00.393000"]) | ||||
|         f = index.asof | ||||
|  | ||||
|         result = index.map(f) | ||||
|         expected = Index([f(index[0])]) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|     @pytest.mark.parametrize("name", [None, "name"]) | ||||
|     def test_index_map(self, name): | ||||
|         # see GH#20990 | ||||
|         count = 6 | ||||
|         index = date_range("2018-01-01", periods=count, freq="ME", name=name).map( | ||||
|             lambda x: (x.year, x.month) | ||||
|         ) | ||||
|         exp_index = MultiIndex.from_product(((2018,), range(1, 7)), names=[name, name]) | ||||
|         tm.assert_index_equal(index, exp_index) | ||||
| @ -0,0 +1,95 @@ | ||||
| from dateutil.tz import tzlocal | ||||
| import numpy as np | ||||
| import pytest | ||||
|  | ||||
| import pandas.util._test_decorators as td | ||||
|  | ||||
| from pandas import ( | ||||
|     DatetimeIndex, | ||||
|     NaT, | ||||
|     Timestamp, | ||||
|     date_range, | ||||
| ) | ||||
| import pandas._testing as tm | ||||
|  | ||||
|  | ||||
| class TestNormalize: | ||||
|     def test_normalize(self): | ||||
|         rng = date_range("1/1/2000 9:30", periods=10, freq="D") | ||||
|  | ||||
|         result = rng.normalize() | ||||
|         expected = date_range("1/1/2000", periods=10, freq="D") | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         arr_ns = np.array([1380585623454345752, 1380585612343234312]).astype( | ||||
|             "datetime64[ns]" | ||||
|         ) | ||||
|         rng_ns = DatetimeIndex(arr_ns) | ||||
|         rng_ns_normalized = rng_ns.normalize() | ||||
|  | ||||
|         arr_ns = np.array([1380585600000000000, 1380585600000000000]).astype( | ||||
|             "datetime64[ns]" | ||||
|         ) | ||||
|         expected = DatetimeIndex(arr_ns) | ||||
|         tm.assert_index_equal(rng_ns_normalized, expected) | ||||
|  | ||||
|         assert result.is_normalized | ||||
|         assert not rng.is_normalized | ||||
|  | ||||
|     def test_normalize_nat(self): | ||||
|         dti = DatetimeIndex([NaT, Timestamp("2018-01-01 01:00:00")]) | ||||
|         result = dti.normalize() | ||||
|         expected = DatetimeIndex([NaT, Timestamp("2018-01-01")]) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|     def test_normalize_tz(self): | ||||
|         rng = date_range("1/1/2000 9:30", periods=10, freq="D", tz="US/Eastern") | ||||
|  | ||||
|         result = rng.normalize()  # does not preserve freq | ||||
|         expected = date_range("1/1/2000", periods=10, freq="D", tz="US/Eastern") | ||||
|         tm.assert_index_equal(result, expected._with_freq(None)) | ||||
|  | ||||
|         assert result.is_normalized | ||||
|         assert not rng.is_normalized | ||||
|  | ||||
|         rng = date_range("1/1/2000 9:30", periods=10, freq="D", tz="UTC") | ||||
|  | ||||
|         result = rng.normalize() | ||||
|         expected = date_range("1/1/2000", periods=10, freq="D", tz="UTC") | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         assert result.is_normalized | ||||
|         assert not rng.is_normalized | ||||
|  | ||||
|         rng = date_range("1/1/2000 9:30", periods=10, freq="D", tz=tzlocal()) | ||||
|         result = rng.normalize()  # does not preserve freq | ||||
|         expected = date_range("1/1/2000", periods=10, freq="D", tz=tzlocal()) | ||||
|         tm.assert_index_equal(result, expected._with_freq(None)) | ||||
|  | ||||
|         assert result.is_normalized | ||||
|         assert not rng.is_normalized | ||||
|  | ||||
|     @td.skip_if_windows | ||||
|     @pytest.mark.parametrize( | ||||
|         "timezone", | ||||
|         [ | ||||
|             "US/Pacific", | ||||
|             "US/Eastern", | ||||
|             "UTC", | ||||
|             "Asia/Kolkata", | ||||
|             "Asia/Shanghai", | ||||
|             "Australia/Canberra", | ||||
|         ], | ||||
|     ) | ||||
|     def test_normalize_tz_local(self, timezone): | ||||
|         # GH#13459 | ||||
|         with tm.set_timezone(timezone): | ||||
|             rng = date_range("1/1/2000 9:30", periods=10, freq="D", tz=tzlocal()) | ||||
|  | ||||
|             result = rng.normalize() | ||||
|             expected = date_range("1/1/2000", periods=10, freq="D", tz=tzlocal()) | ||||
|             expected = expected._with_freq(None) | ||||
|             tm.assert_index_equal(result, expected) | ||||
|  | ||||
|             assert result.is_normalized | ||||
|             assert not rng.is_normalized | ||||
| @ -0,0 +1,83 @@ | ||||
| import numpy as np | ||||
| import pytest | ||||
|  | ||||
| from pandas import ( | ||||
|     DatetimeIndex, | ||||
|     Timestamp, | ||||
|     date_range, | ||||
| ) | ||||
| import pandas._testing as tm | ||||
|  | ||||
|  | ||||
| class TestRepeat: | ||||
|     def test_repeat_range(self, tz_naive_fixture): | ||||
|         rng = date_range("1/1/2000", "1/1/2001") | ||||
|  | ||||
|         result = rng.repeat(5) | ||||
|         assert result.freq is None | ||||
|         assert len(result) == 5 * len(rng) | ||||
|  | ||||
|     def test_repeat_range2(self, tz_naive_fixture, unit): | ||||
|         tz = tz_naive_fixture | ||||
|         index = date_range("2001-01-01", periods=2, freq="D", tz=tz, unit=unit) | ||||
|         exp = DatetimeIndex( | ||||
|             ["2001-01-01", "2001-01-01", "2001-01-02", "2001-01-02"], tz=tz | ||||
|         ).as_unit(unit) | ||||
|         for res in [index.repeat(2), np.repeat(index, 2)]: | ||||
|             tm.assert_index_equal(res, exp) | ||||
|             assert res.freq is None | ||||
|  | ||||
|     def test_repeat_range3(self, tz_naive_fixture, unit): | ||||
|         tz = tz_naive_fixture | ||||
|         index = date_range("2001-01-01", periods=2, freq="2D", tz=tz, unit=unit) | ||||
|         exp = DatetimeIndex( | ||||
|             ["2001-01-01", "2001-01-01", "2001-01-03", "2001-01-03"], tz=tz | ||||
|         ).as_unit(unit) | ||||
|         for res in [index.repeat(2), np.repeat(index, 2)]: | ||||
|             tm.assert_index_equal(res, exp) | ||||
|             assert res.freq is None | ||||
|  | ||||
|     def test_repeat_range4(self, tz_naive_fixture, unit): | ||||
|         tz = tz_naive_fixture | ||||
|         index = DatetimeIndex(["2001-01-01", "NaT", "2003-01-01"], tz=tz).as_unit(unit) | ||||
|         exp = DatetimeIndex( | ||||
|             [ | ||||
|                 "2001-01-01", | ||||
|                 "2001-01-01", | ||||
|                 "2001-01-01", | ||||
|                 "NaT", | ||||
|                 "NaT", | ||||
|                 "NaT", | ||||
|                 "2003-01-01", | ||||
|                 "2003-01-01", | ||||
|                 "2003-01-01", | ||||
|             ], | ||||
|             tz=tz, | ||||
|         ).as_unit(unit) | ||||
|         for res in [index.repeat(3), np.repeat(index, 3)]: | ||||
|             tm.assert_index_equal(res, exp) | ||||
|             assert res.freq is None | ||||
|  | ||||
|     def test_repeat(self, tz_naive_fixture, unit): | ||||
|         tz = tz_naive_fixture | ||||
|         reps = 2 | ||||
|         msg = "the 'axis' parameter is not supported" | ||||
|  | ||||
|         rng = date_range(start="2016-01-01", periods=2, freq="30Min", tz=tz, unit=unit) | ||||
|  | ||||
|         expected_rng = DatetimeIndex( | ||||
|             [ | ||||
|                 Timestamp("2016-01-01 00:00:00", tz=tz), | ||||
|                 Timestamp("2016-01-01 00:00:00", tz=tz), | ||||
|                 Timestamp("2016-01-01 00:30:00", tz=tz), | ||||
|                 Timestamp("2016-01-01 00:30:00", tz=tz), | ||||
|             ] | ||||
|         ).as_unit(unit) | ||||
|  | ||||
|         res = rng.repeat(reps) | ||||
|         tm.assert_index_equal(res, expected_rng) | ||||
|         assert res.freq is None | ||||
|  | ||||
|         tm.assert_index_equal(np.repeat(rng, reps), expected_rng) | ||||
|         with pytest.raises(ValueError, match=msg): | ||||
|             np.repeat(rng, reps, axis=1) | ||||
| @ -0,0 +1,31 @@ | ||||
| from dateutil.tz import tzlocal | ||||
| import pytest | ||||
|  | ||||
| from pandas.compat import IS64 | ||||
|  | ||||
| from pandas import date_range | ||||
|  | ||||
|  | ||||
| @pytest.mark.parametrize( | ||||
|     "freq,expected", | ||||
|     [ | ||||
|         ("YE", "day"), | ||||
|         ("QE", "day"), | ||||
|         ("ME", "day"), | ||||
|         ("D", "day"), | ||||
|         ("h", "hour"), | ||||
|         ("min", "minute"), | ||||
|         ("s", "second"), | ||||
|         ("ms", "millisecond"), | ||||
|         ("us", "microsecond"), | ||||
|     ], | ||||
| ) | ||||
| def test_dti_resolution(request, tz_naive_fixture, freq, expected): | ||||
|     tz = tz_naive_fixture | ||||
|     if freq == "YE" and not IS64 and isinstance(tz, tzlocal): | ||||
|         request.applymarker( | ||||
|             pytest.mark.xfail(reason="OverflowError inside tzlocal past 2038") | ||||
|         ) | ||||
|  | ||||
|     idx = date_range(start="2013-04-01", periods=30, freq=freq, tz=tz) | ||||
|     assert idx.resolution == expected | ||||
| @ -0,0 +1,221 @@ | ||||
| import pytest | ||||
|  | ||||
| from pandas._libs.tslibs import to_offset | ||||
| from pandas._libs.tslibs.offsets import INVALID_FREQ_ERR_MSG | ||||
|  | ||||
| from pandas import ( | ||||
|     DatetimeIndex, | ||||
|     Timestamp, | ||||
|     date_range, | ||||
| ) | ||||
| import pandas._testing as tm | ||||
|  | ||||
|  | ||||
| class TestDatetimeIndexRound: | ||||
|     def test_round_daily(self): | ||||
|         dti = date_range("20130101 09:10:11", periods=5) | ||||
|         result = dti.round("D") | ||||
|         expected = date_range("20130101", periods=5) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         dti = dti.tz_localize("UTC").tz_convert("US/Eastern") | ||||
|         result = dti.round("D") | ||||
|         expected = date_range("20130101", periods=5).tz_localize("US/Eastern") | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         result = dti.round("s") | ||||
|         tm.assert_index_equal(result, dti) | ||||
|  | ||||
|     @pytest.mark.parametrize( | ||||
|         "freq, error_msg", | ||||
|         [ | ||||
|             ("YE", "<YearEnd: month=12> is a non-fixed frequency"), | ||||
|             ("ME", "<MonthEnd> is a non-fixed frequency"), | ||||
|             ("foobar", "Invalid frequency: foobar"), | ||||
|         ], | ||||
|     ) | ||||
|     def test_round_invalid(self, freq, error_msg): | ||||
|         dti = date_range("20130101 09:10:11", periods=5) | ||||
|         dti = dti.tz_localize("UTC").tz_convert("US/Eastern") | ||||
|         with pytest.raises(ValueError, match=error_msg): | ||||
|             dti.round(freq) | ||||
|  | ||||
|     def test_round(self, tz_naive_fixture, unit): | ||||
|         tz = tz_naive_fixture | ||||
|         rng = date_range(start="2016-01-01", periods=5, freq="30Min", tz=tz, unit=unit) | ||||
|         elt = rng[1] | ||||
|  | ||||
|         expected_rng = DatetimeIndex( | ||||
|             [ | ||||
|                 Timestamp("2016-01-01 00:00:00", tz=tz), | ||||
|                 Timestamp("2016-01-01 00:00:00", tz=tz), | ||||
|                 Timestamp("2016-01-01 01:00:00", tz=tz), | ||||
|                 Timestamp("2016-01-01 02:00:00", tz=tz), | ||||
|                 Timestamp("2016-01-01 02:00:00", tz=tz), | ||||
|             ] | ||||
|         ).as_unit(unit) | ||||
|         expected_elt = expected_rng[1] | ||||
|  | ||||
|         result = rng.round(freq="h") | ||||
|         tm.assert_index_equal(result, expected_rng) | ||||
|         assert elt.round(freq="h") == expected_elt | ||||
|  | ||||
|         msg = INVALID_FREQ_ERR_MSG | ||||
|         with pytest.raises(ValueError, match=msg): | ||||
|             rng.round(freq="foo") | ||||
|         with pytest.raises(ValueError, match=msg): | ||||
|             elt.round(freq="foo") | ||||
|  | ||||
|         msg = "<MonthEnd> is a non-fixed frequency" | ||||
|         with pytest.raises(ValueError, match=msg): | ||||
|             rng.round(freq="ME") | ||||
|         with pytest.raises(ValueError, match=msg): | ||||
|             elt.round(freq="ME") | ||||
|  | ||||
|     def test_round2(self, tz_naive_fixture): | ||||
|         tz = tz_naive_fixture | ||||
|         # GH#14440 & GH#15578 | ||||
|         index = DatetimeIndex(["2016-10-17 12:00:00.0015"], tz=tz).as_unit("ns") | ||||
|         result = index.round("ms") | ||||
|         expected = DatetimeIndex(["2016-10-17 12:00:00.002000"], tz=tz).as_unit("ns") | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         for freq in ["us", "ns"]: | ||||
|             tm.assert_index_equal(index, index.round(freq)) | ||||
|  | ||||
|     def test_round3(self, tz_naive_fixture): | ||||
|         tz = tz_naive_fixture | ||||
|         index = DatetimeIndex(["2016-10-17 12:00:00.00149"], tz=tz).as_unit("ns") | ||||
|         result = index.round("ms") | ||||
|         expected = DatetimeIndex(["2016-10-17 12:00:00.001000"], tz=tz).as_unit("ns") | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|     def test_round4(self, tz_naive_fixture): | ||||
|         index = DatetimeIndex(["2016-10-17 12:00:00.001501031"], dtype="M8[ns]") | ||||
|         result = index.round("10ns") | ||||
|         expected = DatetimeIndex(["2016-10-17 12:00:00.001501030"], dtype="M8[ns]") | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         ts = "2016-10-17 12:00:00.001501031" | ||||
|         dti = DatetimeIndex([ts], dtype="M8[ns]") | ||||
|         with tm.assert_produces_warning(False): | ||||
|             dti.round("1010ns") | ||||
|  | ||||
|     def test_no_rounding_occurs(self, tz_naive_fixture): | ||||
|         # GH 21262 | ||||
|         tz = tz_naive_fixture | ||||
|         rng = date_range(start="2016-01-01", periods=5, freq="2Min", tz=tz) | ||||
|  | ||||
|         expected_rng = DatetimeIndex( | ||||
|             [ | ||||
|                 Timestamp("2016-01-01 00:00:00", tz=tz), | ||||
|                 Timestamp("2016-01-01 00:02:00", tz=tz), | ||||
|                 Timestamp("2016-01-01 00:04:00", tz=tz), | ||||
|                 Timestamp("2016-01-01 00:06:00", tz=tz), | ||||
|                 Timestamp("2016-01-01 00:08:00", tz=tz), | ||||
|             ] | ||||
|         ).as_unit("ns") | ||||
|  | ||||
|         result = rng.round(freq="2min") | ||||
|         tm.assert_index_equal(result, expected_rng) | ||||
|  | ||||
|     @pytest.mark.parametrize( | ||||
|         "test_input, rounder, freq, expected", | ||||
|         [ | ||||
|             (["2117-01-01 00:00:45"], "floor", "15s", ["2117-01-01 00:00:45"]), | ||||
|             (["2117-01-01 00:00:45"], "ceil", "15s", ["2117-01-01 00:00:45"]), | ||||
|             ( | ||||
|                 ["2117-01-01 00:00:45.000000012"], | ||||
|                 "floor", | ||||
|                 "10ns", | ||||
|                 ["2117-01-01 00:00:45.000000010"], | ||||
|             ), | ||||
|             ( | ||||
|                 ["1823-01-01 00:00:01.000000012"], | ||||
|                 "ceil", | ||||
|                 "10ns", | ||||
|                 ["1823-01-01 00:00:01.000000020"], | ||||
|             ), | ||||
|             (["1823-01-01 00:00:01"], "floor", "1s", ["1823-01-01 00:00:01"]), | ||||
|             (["1823-01-01 00:00:01"], "ceil", "1s", ["1823-01-01 00:00:01"]), | ||||
|             (["2018-01-01 00:15:00"], "ceil", "15min", ["2018-01-01 00:15:00"]), | ||||
|             (["2018-01-01 00:15:00"], "floor", "15min", ["2018-01-01 00:15:00"]), | ||||
|             (["1823-01-01 03:00:00"], "ceil", "3h", ["1823-01-01 03:00:00"]), | ||||
|             (["1823-01-01 03:00:00"], "floor", "3h", ["1823-01-01 03:00:00"]), | ||||
|             ( | ||||
|                 ("NaT", "1823-01-01 00:00:01"), | ||||
|                 "floor", | ||||
|                 "1s", | ||||
|                 ("NaT", "1823-01-01 00:00:01"), | ||||
|             ), | ||||
|             ( | ||||
|                 ("NaT", "1823-01-01 00:00:01"), | ||||
|                 "ceil", | ||||
|                 "1s", | ||||
|                 ("NaT", "1823-01-01 00:00:01"), | ||||
|             ), | ||||
|         ], | ||||
|     ) | ||||
|     def test_ceil_floor_edge(self, test_input, rounder, freq, expected): | ||||
|         dt = DatetimeIndex(list(test_input)) | ||||
|         func = getattr(dt, rounder) | ||||
|         result = func(freq) | ||||
|         expected = DatetimeIndex(list(expected)) | ||||
|         assert expected.equals(result) | ||||
|  | ||||
|     @pytest.mark.parametrize( | ||||
|         "start, index_freq, periods", | ||||
|         [("2018-01-01", "12h", 25), ("2018-01-01 0:0:0.124999", "1ns", 1000)], | ||||
|     ) | ||||
|     @pytest.mark.parametrize( | ||||
|         "round_freq", | ||||
|         [ | ||||
|             "2ns", | ||||
|             "3ns", | ||||
|             "4ns", | ||||
|             "5ns", | ||||
|             "6ns", | ||||
|             "7ns", | ||||
|             "250ns", | ||||
|             "500ns", | ||||
|             "750ns", | ||||
|             "1us", | ||||
|             "19us", | ||||
|             "250us", | ||||
|             "500us", | ||||
|             "750us", | ||||
|             "1s", | ||||
|             "2s", | ||||
|             "3s", | ||||
|             "12h", | ||||
|             "1D", | ||||
|         ], | ||||
|     ) | ||||
|     def test_round_int64(self, start, index_freq, periods, round_freq): | ||||
|         dt = date_range(start=start, freq=index_freq, periods=periods) | ||||
|         unit = to_offset(round_freq).nanos | ||||
|  | ||||
|         # test floor | ||||
|         result = dt.floor(round_freq) | ||||
|         diff = dt.asi8 - result.asi8 | ||||
|         mod = result.asi8 % unit | ||||
|         assert (mod == 0).all(), f"floor not a {round_freq} multiple" | ||||
|         assert (0 <= diff).all() and (diff < unit).all(), "floor error" | ||||
|  | ||||
|         # test ceil | ||||
|         result = dt.ceil(round_freq) | ||||
|         diff = result.asi8 - dt.asi8 | ||||
|         mod = result.asi8 % unit | ||||
|         assert (mod == 0).all(), f"ceil not a {round_freq} multiple" | ||||
|         assert (0 <= diff).all() and (diff < unit).all(), "ceil error" | ||||
|  | ||||
|         # test round | ||||
|         result = dt.round(round_freq) | ||||
|         diff = abs(result.asi8 - dt.asi8) | ||||
|         mod = result.asi8 % unit | ||||
|         assert (mod == 0).all(), f"round not a {round_freq} multiple" | ||||
|         assert (diff <= unit // 2).all(), "round error" | ||||
|         if unit % 2 == 0: | ||||
|             assert ( | ||||
|                 result.asi8[diff == unit // 2] % 2 == 0 | ||||
|             ).all(), "round half to even error" | ||||
| @ -0,0 +1,169 @@ | ||||
| from datetime import datetime | ||||
|  | ||||
| import pytest | ||||
| import pytz | ||||
|  | ||||
| from pandas.errors import NullFrequencyError | ||||
|  | ||||
| import pandas as pd | ||||
| from pandas import ( | ||||
|     DatetimeIndex, | ||||
|     Series, | ||||
|     date_range, | ||||
| ) | ||||
| import pandas._testing as tm | ||||
|  | ||||
| START, END = datetime(2009, 1, 1), datetime(2010, 1, 1) | ||||
|  | ||||
|  | ||||
| class TestDatetimeIndexShift: | ||||
|     # ------------------------------------------------------------- | ||||
|     # DatetimeIndex.shift is used in integer addition | ||||
|  | ||||
|     def test_dti_shift_tzaware(self, tz_naive_fixture, unit): | ||||
|         # GH#9903 | ||||
|         tz = tz_naive_fixture | ||||
|         idx = DatetimeIndex([], name="xxx", tz=tz).as_unit(unit) | ||||
|         tm.assert_index_equal(idx.shift(0, freq="h"), idx) | ||||
|         tm.assert_index_equal(idx.shift(3, freq="h"), idx) | ||||
|  | ||||
|         idx = DatetimeIndex( | ||||
|             ["2011-01-01 10:00", "2011-01-01 11:00", "2011-01-01 12:00"], | ||||
|             name="xxx", | ||||
|             tz=tz, | ||||
|             freq="h", | ||||
|         ).as_unit(unit) | ||||
|         tm.assert_index_equal(idx.shift(0, freq="h"), idx) | ||||
|         exp = DatetimeIndex( | ||||
|             ["2011-01-01 13:00", "2011-01-01 14:00", "2011-01-01 15:00"], | ||||
|             name="xxx", | ||||
|             tz=tz, | ||||
|             freq="h", | ||||
|         ).as_unit(unit) | ||||
|         tm.assert_index_equal(idx.shift(3, freq="h"), exp) | ||||
|         exp = DatetimeIndex( | ||||
|             ["2011-01-01 07:00", "2011-01-01 08:00", "2011-01-01 09:00"], | ||||
|             name="xxx", | ||||
|             tz=tz, | ||||
|             freq="h", | ||||
|         ).as_unit(unit) | ||||
|         tm.assert_index_equal(idx.shift(-3, freq="h"), exp) | ||||
|  | ||||
|     def test_dti_shift_freqs(self, unit): | ||||
|         # test shift for DatetimeIndex and non DatetimeIndex | ||||
|         # GH#8083 | ||||
|         drange = date_range("20130101", periods=5, unit=unit) | ||||
|         result = drange.shift(1) | ||||
|         expected = DatetimeIndex( | ||||
|             ["2013-01-02", "2013-01-03", "2013-01-04", "2013-01-05", "2013-01-06"], | ||||
|             dtype=f"M8[{unit}]", | ||||
|             freq="D", | ||||
|         ) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         result = drange.shift(-1) | ||||
|         expected = DatetimeIndex( | ||||
|             ["2012-12-31", "2013-01-01", "2013-01-02", "2013-01-03", "2013-01-04"], | ||||
|             dtype=f"M8[{unit}]", | ||||
|             freq="D", | ||||
|         ) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         result = drange.shift(3, freq="2D") | ||||
|         expected = DatetimeIndex( | ||||
|             ["2013-01-07", "2013-01-08", "2013-01-09", "2013-01-10", "2013-01-11"], | ||||
|             dtype=f"M8[{unit}]", | ||||
|             freq="D", | ||||
|         ) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|     def test_dti_shift_int(self, unit): | ||||
|         rng = date_range("1/1/2000", periods=20, unit=unit) | ||||
|  | ||||
|         result = rng + 5 * rng.freq | ||||
|         expected = rng.shift(5) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         result = rng - 5 * rng.freq | ||||
|         expected = rng.shift(-5) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|     def test_dti_shift_no_freq(self, unit): | ||||
|         # GH#19147 | ||||
|         dti = DatetimeIndex(["2011-01-01 10:00", "2011-01-01"], freq=None).as_unit(unit) | ||||
|         with pytest.raises(NullFrequencyError, match="Cannot shift with no freq"): | ||||
|             dti.shift(2) | ||||
|  | ||||
|     @pytest.mark.parametrize("tzstr", ["US/Eastern", "dateutil/US/Eastern"]) | ||||
|     def test_dti_shift_localized(self, tzstr, unit): | ||||
|         dr = date_range("2011/1/1", "2012/1/1", freq="W-FRI", unit=unit) | ||||
|         dr_tz = dr.tz_localize(tzstr) | ||||
|  | ||||
|         result = dr_tz.shift(1, "10min") | ||||
|         assert result.tz == dr_tz.tz | ||||
|  | ||||
|     def test_dti_shift_across_dst(self, unit): | ||||
|         # GH 8616 | ||||
|         idx = date_range( | ||||
|             "2013-11-03", tz="America/Chicago", periods=7, freq="h", unit=unit | ||||
|         ) | ||||
|         ser = Series(index=idx[:-1], dtype=object) | ||||
|         result = ser.shift(freq="h") | ||||
|         expected = Series(index=idx[1:], dtype=object) | ||||
|         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, unit): | ||||
|         # GH 8616 | ||||
|         dt = datetime(2014, 11, 14, 0) | ||||
|         dt_est = pytz.timezone("EST").localize(dt) | ||||
|         idx = DatetimeIndex([dt_est]).as_unit(unit) | ||||
|         ser = Series(data=[1], index=idx) | ||||
|         result = ser.shift(shift, freq="h") | ||||
|         exp_index = DatetimeIndex([result_time], tz="EST").as_unit(unit) | ||||
|         expected = Series(1, index=exp_index) | ||||
|         tm.assert_series_equal(result, expected) | ||||
|  | ||||
|     def test_shift_periods(self, unit): | ||||
|         # GH#22458 : argument 'n' was deprecated in favor of 'periods' | ||||
|         idx = date_range(start=START, end=END, periods=3, unit=unit) | ||||
|         tm.assert_index_equal(idx.shift(periods=0), idx) | ||||
|         tm.assert_index_equal(idx.shift(0), idx) | ||||
|  | ||||
|     @pytest.mark.parametrize("freq", ["B", "C"]) | ||||
|     def test_shift_bday(self, freq, unit): | ||||
|         rng = date_range(START, END, freq=freq, unit=unit) | ||||
|         shifted = rng.shift(5) | ||||
|         assert shifted[0] == rng[5] | ||||
|         assert shifted.freq == rng.freq | ||||
|  | ||||
|         shifted = rng.shift(-5) | ||||
|         assert shifted[5] == rng[0] | ||||
|         assert shifted.freq == rng.freq | ||||
|  | ||||
|         shifted = rng.shift(0) | ||||
|         assert shifted[0] == rng[0] | ||||
|         assert shifted.freq == rng.freq | ||||
|  | ||||
|     def test_shift_bmonth(self, unit): | ||||
|         rng = date_range(START, END, freq=pd.offsets.BMonthEnd(), unit=unit) | ||||
|         shifted = rng.shift(1, freq=pd.offsets.BDay()) | ||||
|         assert shifted[0] == rng[0] + pd.offsets.BDay() | ||||
|  | ||||
|         rng = date_range(START, END, freq=pd.offsets.BMonthEnd(), unit=unit) | ||||
|         with tm.assert_produces_warning(pd.errors.PerformanceWarning): | ||||
|             shifted = rng.shift(1, freq=pd.offsets.CDay()) | ||||
|             assert shifted[0] == rng[0] + pd.offsets.CDay() | ||||
|  | ||||
|     def test_shift_empty(self, unit): | ||||
|         # GH#14811 | ||||
|         dti = date_range(start="2016-10-21", end="2016-10-21", freq="BME", unit=unit) | ||||
|         result = dti.shift(1) | ||||
|         tm.assert_index_equal(result, dti) | ||||
| @ -0,0 +1,47 @@ | ||||
| import pytest | ||||
|  | ||||
| from pandas import ( | ||||
|     DatetimeIndex, | ||||
|     date_range, | ||||
| ) | ||||
| import pandas._testing as tm | ||||
|  | ||||
|  | ||||
| @pytest.mark.parametrize("tz", [None, "Asia/Shanghai", "Europe/Berlin"]) | ||||
| @pytest.mark.parametrize("name", [None, "my_dti"]) | ||||
| @pytest.mark.parametrize("unit", ["ns", "us", "ms", "s"]) | ||||
| def test_dti_snap(name, tz, unit): | ||||
|     dti = DatetimeIndex( | ||||
|         [ | ||||
|             "1/1/2002", | ||||
|             "1/2/2002", | ||||
|             "1/3/2002", | ||||
|             "1/4/2002", | ||||
|             "1/5/2002", | ||||
|             "1/6/2002", | ||||
|             "1/7/2002", | ||||
|         ], | ||||
|         name=name, | ||||
|         tz=tz, | ||||
|         freq="D", | ||||
|     ) | ||||
|     dti = dti.as_unit(unit) | ||||
|  | ||||
|     result = dti.snap(freq="W-MON") | ||||
|     expected = date_range("12/31/2001", "1/7/2002", name=name, tz=tz, freq="w-mon") | ||||
|     expected = expected.repeat([3, 4]) | ||||
|     expected = expected.as_unit(unit) | ||||
|     tm.assert_index_equal(result, expected) | ||||
|     assert result.tz == expected.tz | ||||
|     assert result.freq is None | ||||
|     assert expected.freq is None | ||||
|  | ||||
|     result = dti.snap(freq="B") | ||||
|  | ||||
|     expected = date_range("1/1/2002", "1/7/2002", name=name, tz=tz, freq="b") | ||||
|     expected = expected.repeat([1, 1, 1, 2, 2]) | ||||
|     expected = expected.as_unit(unit) | ||||
|     tm.assert_index_equal(result, expected) | ||||
|     assert result.tz == expected.tz | ||||
|     assert result.freq is None | ||||
|     assert expected.freq is None | ||||
| @ -0,0 +1,28 @@ | ||||
| from pandas import ( | ||||
|     DataFrame, | ||||
|     Index, | ||||
|     date_range, | ||||
| ) | ||||
| import pandas._testing as tm | ||||
|  | ||||
|  | ||||
| class TestToFrame: | ||||
|     def test_to_frame_datetime_tz(self): | ||||
|         # GH#25809 | ||||
|         idx = date_range(start="2019-01-01", end="2019-01-30", freq="D", tz="UTC") | ||||
|         result = idx.to_frame() | ||||
|         expected = DataFrame(idx, index=idx) | ||||
|         tm.assert_frame_equal(result, expected) | ||||
|  | ||||
|     def test_to_frame_respects_none_name(self): | ||||
|         # GH#44212 if we explicitly pass name=None, then that should be respected, | ||||
|         #  not changed to 0 | ||||
|         # GH-45448 this is first deprecated to only change in the future | ||||
|         idx = date_range(start="2019-01-01", end="2019-01-30", freq="D", tz="UTC") | ||||
|         result = idx.to_frame(name=None) | ||||
|         exp_idx = Index([None], dtype=object) | ||||
|         tm.assert_index_equal(exp_idx, result.columns) | ||||
|  | ||||
|         result = idx.rename("foo").to_frame(name=None) | ||||
|         exp_idx = Index([None], dtype=object) | ||||
|         tm.assert_index_equal(exp_idx, result.columns) | ||||
| @ -0,0 +1,45 @@ | ||||
| import numpy as np | ||||
|  | ||||
| from pandas import ( | ||||
|     Index, | ||||
|     Timestamp, | ||||
|     date_range, | ||||
| ) | ||||
| import pandas._testing as tm | ||||
|  | ||||
|  | ||||
| class TestDateTimeIndexToJulianDate: | ||||
|     def test_1700(self): | ||||
|         dr = date_range(start=Timestamp("1710-10-01"), periods=5, freq="D") | ||||
|         r1 = Index([x.to_julian_date() for x in dr]) | ||||
|         r2 = dr.to_julian_date() | ||||
|         assert isinstance(r2, Index) and r2.dtype == np.float64 | ||||
|         tm.assert_index_equal(r1, r2) | ||||
|  | ||||
|     def test_2000(self): | ||||
|         dr = date_range(start=Timestamp("2000-02-27"), periods=5, freq="D") | ||||
|         r1 = Index([x.to_julian_date() for x in dr]) | ||||
|         r2 = dr.to_julian_date() | ||||
|         assert isinstance(r2, Index) and r2.dtype == np.float64 | ||||
|         tm.assert_index_equal(r1, r2) | ||||
|  | ||||
|     def test_hour(self): | ||||
|         dr = date_range(start=Timestamp("2000-02-27"), periods=5, freq="h") | ||||
|         r1 = Index([x.to_julian_date() for x in dr]) | ||||
|         r2 = dr.to_julian_date() | ||||
|         assert isinstance(r2, Index) and r2.dtype == np.float64 | ||||
|         tm.assert_index_equal(r1, r2) | ||||
|  | ||||
|     def test_minute(self): | ||||
|         dr = date_range(start=Timestamp("2000-02-27"), periods=5, freq="min") | ||||
|         r1 = Index([x.to_julian_date() for x in dr]) | ||||
|         r2 = dr.to_julian_date() | ||||
|         assert isinstance(r2, Index) and r2.dtype == np.float64 | ||||
|         tm.assert_index_equal(r1, r2) | ||||
|  | ||||
|     def test_second(self): | ||||
|         dr = date_range(start=Timestamp("2000-02-27"), periods=5, freq="s") | ||||
|         r1 = Index([x.to_julian_date() for x in dr]) | ||||
|         r2 = dr.to_julian_date() | ||||
|         assert isinstance(r2, Index) and r2.dtype == np.float64 | ||||
|         tm.assert_index_equal(r1, r2) | ||||
| @ -0,0 +1,225 @@ | ||||
| import dateutil.tz | ||||
| from dateutil.tz import tzlocal | ||||
| import pytest | ||||
| import pytz | ||||
|  | ||||
| from pandas._libs.tslibs.ccalendar import MONTHS | ||||
| from pandas._libs.tslibs.offsets import MonthEnd | ||||
| from pandas._libs.tslibs.period import INVALID_FREQ_ERR_MSG | ||||
|  | ||||
| from pandas import ( | ||||
|     DatetimeIndex, | ||||
|     Period, | ||||
|     PeriodIndex, | ||||
|     Timestamp, | ||||
|     date_range, | ||||
|     period_range, | ||||
| ) | ||||
| import pandas._testing as tm | ||||
|  | ||||
|  | ||||
| class TestToPeriod: | ||||
|     def test_dti_to_period(self): | ||||
|         dti = date_range(start="1/1/2005", end="12/1/2005", freq="ME") | ||||
|         pi1 = dti.to_period() | ||||
|         pi2 = dti.to_period(freq="D") | ||||
|         pi3 = dti.to_period(freq="3D") | ||||
|  | ||||
|         assert pi1[0] == Period("Jan 2005", freq="M") | ||||
|         assert pi2[0] == Period("1/31/2005", freq="D") | ||||
|         assert pi3[0] == Period("1/31/2005", freq="3D") | ||||
|  | ||||
|         assert pi1[-1] == Period("Nov 2005", freq="M") | ||||
|         assert pi2[-1] == Period("11/30/2005", freq="D") | ||||
|         assert pi3[-1], Period("11/30/2005", freq="3D") | ||||
|  | ||||
|         tm.assert_index_equal(pi1, period_range("1/1/2005", "11/1/2005", freq="M")) | ||||
|         tm.assert_index_equal( | ||||
|             pi2, period_range("1/1/2005", "11/1/2005", freq="M").asfreq("D") | ||||
|         ) | ||||
|         tm.assert_index_equal( | ||||
|             pi3, period_range("1/1/2005", "11/1/2005", freq="M").asfreq("3D") | ||||
|         ) | ||||
|  | ||||
|     @pytest.mark.parametrize("month", MONTHS) | ||||
|     def test_to_period_quarterly(self, month): | ||||
|         # make sure we can make the round trip | ||||
|         freq = f"Q-{month}" | ||||
|         rng = period_range("1989Q3", "1991Q3", freq=freq) | ||||
|         stamps = rng.to_timestamp() | ||||
|         result = stamps.to_period(freq) | ||||
|         tm.assert_index_equal(rng, result) | ||||
|  | ||||
|     @pytest.mark.parametrize("off", ["BQE", "QS", "BQS"]) | ||||
|     def test_to_period_quarterlyish(self, off): | ||||
|         rng = date_range("01-Jan-2012", periods=8, freq=off) | ||||
|         prng = rng.to_period() | ||||
|         assert prng.freq == "QE-DEC" | ||||
|  | ||||
|     @pytest.mark.parametrize("off", ["BYE", "YS", "BYS"]) | ||||
|     def test_to_period_annualish(self, off): | ||||
|         rng = date_range("01-Jan-2012", periods=8, freq=off) | ||||
|         prng = rng.to_period() | ||||
|         assert prng.freq == "YE-DEC" | ||||
|  | ||||
|     def test_to_period_monthish(self): | ||||
|         offsets = ["MS", "BME"] | ||||
|         for off in offsets: | ||||
|             rng = date_range("01-Jan-2012", periods=8, freq=off) | ||||
|             prng = rng.to_period() | ||||
|             assert prng.freqstr == "M" | ||||
|  | ||||
|         rng = date_range("01-Jan-2012", periods=8, freq="ME") | ||||
|         prng = rng.to_period() | ||||
|         assert prng.freqstr == "M" | ||||
|  | ||||
|         with pytest.raises(ValueError, match=INVALID_FREQ_ERR_MSG): | ||||
|             date_range("01-Jan-2012", periods=8, freq="EOM") | ||||
|  | ||||
|     @pytest.mark.parametrize( | ||||
|         "freq_offset, freq_period", | ||||
|         [ | ||||
|             ("2ME", "2M"), | ||||
|             (MonthEnd(2), MonthEnd(2)), | ||||
|         ], | ||||
|     ) | ||||
|     def test_dti_to_period_2monthish(self, freq_offset, freq_period): | ||||
|         dti = date_range("2020-01-01", periods=3, freq=freq_offset) | ||||
|         pi = dti.to_period() | ||||
|  | ||||
|         tm.assert_index_equal(pi, period_range("2020-01", "2020-05", freq=freq_period)) | ||||
|  | ||||
|     @pytest.mark.parametrize( | ||||
|         "freq, freq_depr", | ||||
|         [ | ||||
|             ("2ME", "2M"), | ||||
|             ("2QE", "2Q"), | ||||
|             ("2QE-SEP", "2Q-SEP"), | ||||
|             ("1YE", "1Y"), | ||||
|             ("2YE-MAR", "2Y-MAR"), | ||||
|             ("1YE", "1A"), | ||||
|             ("2YE-MAR", "2A-MAR"), | ||||
|         ], | ||||
|     ) | ||||
|     def test_to_period_frequency_M_Q_Y_A_deprecated(self, freq, freq_depr): | ||||
|         # GH#9586 | ||||
|         msg = f"'{freq_depr[1:]}' is deprecated and will be removed " | ||||
|         f"in a future version, please use '{freq[1:]}' instead." | ||||
|  | ||||
|         rng = date_range("01-Jan-2012", periods=8, freq=freq) | ||||
|         prng = rng.to_period() | ||||
|         with tm.assert_produces_warning(FutureWarning, match=msg): | ||||
|             assert prng.freq == freq_depr | ||||
|  | ||||
|     def test_to_period_infer(self): | ||||
|         # https://github.com/pandas-dev/pandas/issues/33358 | ||||
|         rng = date_range( | ||||
|             start="2019-12-22 06:40:00+00:00", | ||||
|             end="2019-12-22 08:45:00+00:00", | ||||
|             freq="5min", | ||||
|         ) | ||||
|  | ||||
|         with tm.assert_produces_warning(UserWarning): | ||||
|             pi1 = rng.to_period("5min") | ||||
|  | ||||
|         with tm.assert_produces_warning(UserWarning): | ||||
|             pi2 = rng.to_period() | ||||
|  | ||||
|         tm.assert_index_equal(pi1, pi2) | ||||
|  | ||||
|     @pytest.mark.filterwarnings(r"ignore:PeriodDtype\[B\] is deprecated:FutureWarning") | ||||
|     def test_period_dt64_round_trip(self): | ||||
|         dti = date_range("1/1/2000", "1/7/2002", freq="B") | ||||
|         pi = dti.to_period() | ||||
|         tm.assert_index_equal(pi.to_timestamp(), dti) | ||||
|  | ||||
|         dti = date_range("1/1/2000", "1/7/2002", freq="B") | ||||
|         pi = dti.to_period(freq="h") | ||||
|         tm.assert_index_equal(pi.to_timestamp(), dti) | ||||
|  | ||||
|     def test_to_period_millisecond(self): | ||||
|         index = DatetimeIndex( | ||||
|             [ | ||||
|                 Timestamp("2007-01-01 10:11:12.123456Z"), | ||||
|                 Timestamp("2007-01-01 10:11:13.789123Z"), | ||||
|             ] | ||||
|         ) | ||||
|  | ||||
|         with tm.assert_produces_warning(UserWarning): | ||||
|             # warning that timezone info will be lost | ||||
|             period = index.to_period(freq="ms") | ||||
|         assert 2 == len(period) | ||||
|         assert period[0] == Period("2007-01-01 10:11:12.123Z", "ms") | ||||
|         assert period[1] == Period("2007-01-01 10:11:13.789Z", "ms") | ||||
|  | ||||
|     def test_to_period_microsecond(self): | ||||
|         index = DatetimeIndex( | ||||
|             [ | ||||
|                 Timestamp("2007-01-01 10:11:12.123456Z"), | ||||
|                 Timestamp("2007-01-01 10:11:13.789123Z"), | ||||
|             ] | ||||
|         ) | ||||
|  | ||||
|         with tm.assert_produces_warning(UserWarning): | ||||
|             # warning that timezone info will be lost | ||||
|             period = index.to_period(freq="us") | ||||
|         assert 2 == len(period) | ||||
|         assert period[0] == Period("2007-01-01 10:11:12.123456Z", "us") | ||||
|         assert period[1] == Period("2007-01-01 10:11:13.789123Z", "us") | ||||
|  | ||||
|     @pytest.mark.parametrize( | ||||
|         "tz", | ||||
|         ["US/Eastern", pytz.utc, tzlocal(), "dateutil/US/Eastern", dateutil.tz.tzutc()], | ||||
|     ) | ||||
|     def test_to_period_tz(self, tz): | ||||
|         ts = date_range("1/1/2000", "2/1/2000", tz=tz) | ||||
|  | ||||
|         with tm.assert_produces_warning(UserWarning): | ||||
|             # GH#21333 warning that timezone info will be lost | ||||
|             # filter warning about freq deprecation | ||||
|  | ||||
|             result = ts.to_period()[0] | ||||
|             expected = ts[0].to_period(ts.freq) | ||||
|  | ||||
|         assert result == expected | ||||
|  | ||||
|         expected = date_range("1/1/2000", "2/1/2000").to_period() | ||||
|  | ||||
|         with tm.assert_produces_warning(UserWarning): | ||||
|             # GH#21333 warning that timezone info will be lost | ||||
|             result = ts.to_period(ts.freq) | ||||
|  | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|     @pytest.mark.parametrize("tz", ["Etc/GMT-1", "Etc/GMT+1"]) | ||||
|     def test_to_period_tz_utc_offset_consistency(self, tz): | ||||
|         # GH#22905 | ||||
|         ts = date_range("1/1/2000", "2/1/2000", tz="Etc/GMT-1") | ||||
|         with tm.assert_produces_warning(UserWarning): | ||||
|             result = ts.to_period()[0] | ||||
|             expected = ts[0].to_period(ts.freq) | ||||
|             assert result == expected | ||||
|  | ||||
|     def test_to_period_nofreq(self): | ||||
|         idx = DatetimeIndex(["2000-01-01", "2000-01-02", "2000-01-04"]) | ||||
|         msg = "You must pass a freq argument as current index has none." | ||||
|         with pytest.raises(ValueError, match=msg): | ||||
|             idx.to_period() | ||||
|  | ||||
|         idx = DatetimeIndex(["2000-01-01", "2000-01-02", "2000-01-03"], freq="infer") | ||||
|         assert idx.freqstr == "D" | ||||
|         expected = PeriodIndex(["2000-01-01", "2000-01-02", "2000-01-03"], freq="D") | ||||
|         tm.assert_index_equal(idx.to_period(), expected) | ||||
|  | ||||
|         # GH#7606 | ||||
|         idx = DatetimeIndex(["2000-01-01", "2000-01-02", "2000-01-03"]) | ||||
|         assert idx.freqstr is None | ||||
|         tm.assert_index_equal(idx.to_period(), expected) | ||||
|  | ||||
|     @pytest.mark.parametrize("freq", ["2BMS", "1SME-15"]) | ||||
|     def test_to_period_offsets_not_supported(self, freq): | ||||
|         # GH#56243 | ||||
|         msg = f"{freq[1:]} is not supported as period frequency" | ||||
|         ts = date_range("1/1/2012", periods=4, freq=freq) | ||||
|         with pytest.raises(ValueError, match=msg): | ||||
|             ts.to_period() | ||||
| @ -0,0 +1,51 @@ | ||||
| from datetime import ( | ||||
|     datetime, | ||||
|     timezone, | ||||
| ) | ||||
|  | ||||
| import dateutil.parser | ||||
| import dateutil.tz | ||||
| from dateutil.tz import tzlocal | ||||
| import numpy as np | ||||
|  | ||||
| from pandas import ( | ||||
|     DatetimeIndex, | ||||
|     date_range, | ||||
|     to_datetime, | ||||
| ) | ||||
| import pandas._testing as tm | ||||
| from pandas.tests.indexes.datetimes.test_timezones import FixedOffset | ||||
|  | ||||
| fixed_off = FixedOffset(-420, "-07:00") | ||||
|  | ||||
|  | ||||
| class TestToPyDatetime: | ||||
|     def test_dti_to_pydatetime(self): | ||||
|         dt = dateutil.parser.parse("2012-06-13T01:39:00Z") | ||||
|         dt = dt.replace(tzinfo=tzlocal()) | ||||
|  | ||||
|         arr = np.array([dt], dtype=object) | ||||
|  | ||||
|         result = to_datetime(arr, utc=True) | ||||
|         assert result.tz is timezone.utc | ||||
|  | ||||
|         rng = date_range("2012-11-03 03:00", "2012-11-05 03:00", tz=tzlocal()) | ||||
|         arr = rng.to_pydatetime() | ||||
|         result = to_datetime(arr, utc=True) | ||||
|         assert result.tz is timezone.utc | ||||
|  | ||||
|     def test_dti_to_pydatetime_fizedtz(self): | ||||
|         dates = np.array( | ||||
|             [ | ||||
|                 datetime(2000, 1, 1, tzinfo=fixed_off), | ||||
|                 datetime(2000, 1, 2, tzinfo=fixed_off), | ||||
|                 datetime(2000, 1, 3, tzinfo=fixed_off), | ||||
|             ] | ||||
|         ) | ||||
|         dti = DatetimeIndex(dates) | ||||
|  | ||||
|         result = dti.to_pydatetime() | ||||
|         tm.assert_numpy_array_equal(dates, result) | ||||
|  | ||||
|         result = dti._mpl_repr() | ||||
|         tm.assert_numpy_array_equal(dates, result) | ||||
| @ -0,0 +1,18 @@ | ||||
| import numpy as np | ||||
|  | ||||
| from pandas import ( | ||||
|     DatetimeIndex, | ||||
|     Series, | ||||
| ) | ||||
| import pandas._testing as tm | ||||
|  | ||||
|  | ||||
| class TestToSeries: | ||||
|     def test_to_series(self): | ||||
|         naive = DatetimeIndex(["2013-1-1 13:00", "2013-1-2 14:00"], name="B") | ||||
|         idx = naive.tz_localize("US/Pacific") | ||||
|  | ||||
|         expected = Series(np.array(idx.tolist(), dtype="object"), name="B") | ||||
|         result = idx.to_series(index=[0, 1]) | ||||
|         assert expected.dtype == idx.dtype | ||||
|         tm.assert_series_equal(result, expected) | ||||
| @ -0,0 +1,283 @@ | ||||
| from datetime import datetime | ||||
|  | ||||
| import dateutil.tz | ||||
| from dateutil.tz import gettz | ||||
| import numpy as np | ||||
| import pytest | ||||
| import pytz | ||||
|  | ||||
| from pandas._libs.tslibs import timezones | ||||
|  | ||||
| from pandas import ( | ||||
|     DatetimeIndex, | ||||
|     Index, | ||||
|     NaT, | ||||
|     Timestamp, | ||||
|     date_range, | ||||
|     offsets, | ||||
| ) | ||||
| import pandas._testing as tm | ||||
|  | ||||
|  | ||||
| class TestTZConvert: | ||||
|     def test_tz_convert_nat(self): | ||||
|         # GH#5546 | ||||
|         dates = [NaT] | ||||
|         idx = DatetimeIndex(dates) | ||||
|         idx = idx.tz_localize("US/Pacific") | ||||
|         tm.assert_index_equal(idx, DatetimeIndex(dates, tz="US/Pacific")) | ||||
|         idx = idx.tz_convert("US/Eastern") | ||||
|         tm.assert_index_equal(idx, DatetimeIndex(dates, tz="US/Eastern")) | ||||
|         idx = idx.tz_convert("UTC") | ||||
|         tm.assert_index_equal(idx, DatetimeIndex(dates, tz="UTC")) | ||||
|  | ||||
|         dates = ["2010-12-01 00:00", "2010-12-02 00:00", NaT] | ||||
|         idx = DatetimeIndex(dates) | ||||
|         idx = idx.tz_localize("US/Pacific") | ||||
|         tm.assert_index_equal(idx, DatetimeIndex(dates, tz="US/Pacific")) | ||||
|         idx = idx.tz_convert("US/Eastern") | ||||
|         expected = ["2010-12-01 03:00", "2010-12-02 03:00", NaT] | ||||
|         tm.assert_index_equal(idx, DatetimeIndex(expected, tz="US/Eastern")) | ||||
|  | ||||
|         idx = idx + offsets.Hour(5) | ||||
|         expected = ["2010-12-01 08:00", "2010-12-02 08:00", NaT] | ||||
|         tm.assert_index_equal(idx, DatetimeIndex(expected, tz="US/Eastern")) | ||||
|         idx = idx.tz_convert("US/Pacific") | ||||
|         expected = ["2010-12-01 05:00", "2010-12-02 05:00", NaT] | ||||
|         tm.assert_index_equal(idx, DatetimeIndex(expected, tz="US/Pacific")) | ||||
|  | ||||
|         idx = idx + np.timedelta64(3, "h") | ||||
|         expected = ["2010-12-01 08:00", "2010-12-02 08:00", NaT] | ||||
|         tm.assert_index_equal(idx, DatetimeIndex(expected, tz="US/Pacific")) | ||||
|  | ||||
|         idx = idx.tz_convert("US/Eastern") | ||||
|         expected = ["2010-12-01 11:00", "2010-12-02 11:00", NaT] | ||||
|         tm.assert_index_equal(idx, DatetimeIndex(expected, tz="US/Eastern")) | ||||
|  | ||||
|     @pytest.mark.parametrize("prefix", ["", "dateutil/"]) | ||||
|     def test_dti_tz_convert_compat_timestamp(self, prefix): | ||||
|         strdates = ["1/1/2012", "3/1/2012", "4/1/2012"] | ||||
|         idx = DatetimeIndex(strdates, tz=prefix + "US/Eastern") | ||||
|  | ||||
|         conv = idx[0].tz_convert(prefix + "US/Pacific") | ||||
|         expected = idx.tz_convert(prefix + "US/Pacific")[0] | ||||
|  | ||||
|         assert conv == expected | ||||
|  | ||||
|     def test_dti_tz_convert_hour_overflow_dst(self): | ||||
|         # Regression test for GH#13306 | ||||
|  | ||||
|         # sorted case US/Eastern -> UTC | ||||
|         ts = ["2008-05-12 09:50:00", "2008-12-12 09:50:35", "2009-05-12 09:50:32"] | ||||
|         tt = DatetimeIndex(ts).tz_localize("US/Eastern") | ||||
|         ut = tt.tz_convert("UTC") | ||||
|         expected = Index([13, 14, 13], dtype=np.int32) | ||||
|         tm.assert_index_equal(ut.hour, expected) | ||||
|  | ||||
|         # sorted case UTC -> US/Eastern | ||||
|         ts = ["2008-05-12 13:50:00", "2008-12-12 14:50:35", "2009-05-12 13:50:32"] | ||||
|         tt = DatetimeIndex(ts).tz_localize("UTC") | ||||
|         ut = tt.tz_convert("US/Eastern") | ||||
|         expected = Index([9, 9, 9], dtype=np.int32) | ||||
|         tm.assert_index_equal(ut.hour, expected) | ||||
|  | ||||
|         # unsorted case US/Eastern -> UTC | ||||
|         ts = ["2008-05-12 09:50:00", "2008-12-12 09:50:35", "2008-05-12 09:50:32"] | ||||
|         tt = DatetimeIndex(ts).tz_localize("US/Eastern") | ||||
|         ut = tt.tz_convert("UTC") | ||||
|         expected = Index([13, 14, 13], dtype=np.int32) | ||||
|         tm.assert_index_equal(ut.hour, expected) | ||||
|  | ||||
|         # unsorted case UTC -> US/Eastern | ||||
|         ts = ["2008-05-12 13:50:00", "2008-12-12 14:50:35", "2008-05-12 13:50:32"] | ||||
|         tt = DatetimeIndex(ts).tz_localize("UTC") | ||||
|         ut = tt.tz_convert("US/Eastern") | ||||
|         expected = Index([9, 9, 9], dtype=np.int32) | ||||
|         tm.assert_index_equal(ut.hour, expected) | ||||
|  | ||||
|     @pytest.mark.parametrize("tz", ["US/Eastern", "dateutil/US/Eastern"]) | ||||
|     def test_dti_tz_convert_hour_overflow_dst_timestamps(self, tz): | ||||
|         # Regression test for GH#13306 | ||||
|  | ||||
|         # sorted case US/Eastern -> UTC | ||||
|         ts = [ | ||||
|             Timestamp("2008-05-12 09:50:00", tz=tz), | ||||
|             Timestamp("2008-12-12 09:50:35", tz=tz), | ||||
|             Timestamp("2009-05-12 09:50:32", tz=tz), | ||||
|         ] | ||||
|         tt = DatetimeIndex(ts) | ||||
|         ut = tt.tz_convert("UTC") | ||||
|         expected = Index([13, 14, 13], dtype=np.int32) | ||||
|         tm.assert_index_equal(ut.hour, expected) | ||||
|  | ||||
|         # sorted case UTC -> US/Eastern | ||||
|         ts = [ | ||||
|             Timestamp("2008-05-12 13:50:00", tz="UTC"), | ||||
|             Timestamp("2008-12-12 14:50:35", tz="UTC"), | ||||
|             Timestamp("2009-05-12 13:50:32", tz="UTC"), | ||||
|         ] | ||||
|         tt = DatetimeIndex(ts) | ||||
|         ut = tt.tz_convert("US/Eastern") | ||||
|         expected = Index([9, 9, 9], dtype=np.int32) | ||||
|         tm.assert_index_equal(ut.hour, expected) | ||||
|  | ||||
|         # unsorted case US/Eastern -> UTC | ||||
|         ts = [ | ||||
|             Timestamp("2008-05-12 09:50:00", tz=tz), | ||||
|             Timestamp("2008-12-12 09:50:35", tz=tz), | ||||
|             Timestamp("2008-05-12 09:50:32", tz=tz), | ||||
|         ] | ||||
|         tt = DatetimeIndex(ts) | ||||
|         ut = tt.tz_convert("UTC") | ||||
|         expected = Index([13, 14, 13], dtype=np.int32) | ||||
|         tm.assert_index_equal(ut.hour, expected) | ||||
|  | ||||
|         # unsorted case UTC -> US/Eastern | ||||
|         ts = [ | ||||
|             Timestamp("2008-05-12 13:50:00", tz="UTC"), | ||||
|             Timestamp("2008-12-12 14:50:35", tz="UTC"), | ||||
|             Timestamp("2008-05-12 13:50:32", tz="UTC"), | ||||
|         ] | ||||
|         tt = DatetimeIndex(ts) | ||||
|         ut = tt.tz_convert("US/Eastern") | ||||
|         expected = Index([9, 9, 9], dtype=np.int32) | ||||
|         tm.assert_index_equal(ut.hour, expected) | ||||
|  | ||||
|     @pytest.mark.parametrize("freq, n", [("h", 1), ("min", 60), ("s", 3600)]) | ||||
|     def test_dti_tz_convert_trans_pos_plus_1__bug(self, freq, n): | ||||
|         # Regression test for tslib.tz_convert(vals, tz1, tz2). | ||||
|         # See GH#4496 for details. | ||||
|         idx = date_range(datetime(2011, 3, 26, 23), datetime(2011, 3, 27, 1), freq=freq) | ||||
|         idx = idx.tz_localize("UTC") | ||||
|         idx = idx.tz_convert("Europe/Moscow") | ||||
|  | ||||
|         expected = np.repeat(np.array([3, 4, 5]), np.array([n, n, 1])) | ||||
|         tm.assert_index_equal(idx.hour, Index(expected, dtype=np.int32)) | ||||
|  | ||||
|     def test_dti_tz_convert_dst(self): | ||||
|         for freq, n in [("h", 1), ("min", 60), ("s", 3600)]: | ||||
|             # Start DST | ||||
|             idx = date_range( | ||||
|                 "2014-03-08 23:00", "2014-03-09 09:00", freq=freq, tz="UTC" | ||||
|             ) | ||||
|             idx = idx.tz_convert("US/Eastern") | ||||
|             expected = np.repeat( | ||||
|                 np.array([18, 19, 20, 21, 22, 23, 0, 1, 3, 4, 5]), | ||||
|                 np.array([n, n, n, n, n, n, n, n, n, n, 1]), | ||||
|             ) | ||||
|             tm.assert_index_equal(idx.hour, Index(expected, dtype=np.int32)) | ||||
|  | ||||
|             idx = date_range( | ||||
|                 "2014-03-08 18:00", "2014-03-09 05:00", freq=freq, tz="US/Eastern" | ||||
|             ) | ||||
|             idx = idx.tz_convert("UTC") | ||||
|             expected = np.repeat( | ||||
|                 np.array([23, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]), | ||||
|                 np.array([n, n, n, n, n, n, n, n, n, n, 1]), | ||||
|             ) | ||||
|             tm.assert_index_equal(idx.hour, Index(expected, dtype=np.int32)) | ||||
|  | ||||
|             # End DST | ||||
|             idx = date_range( | ||||
|                 "2014-11-01 23:00", "2014-11-02 09:00", freq=freq, tz="UTC" | ||||
|             ) | ||||
|             idx = idx.tz_convert("US/Eastern") | ||||
|             expected = np.repeat( | ||||
|                 np.array([19, 20, 21, 22, 23, 0, 1, 1, 2, 3, 4]), | ||||
|                 np.array([n, n, n, n, n, n, n, n, n, n, 1]), | ||||
|             ) | ||||
|             tm.assert_index_equal(idx.hour, Index(expected, dtype=np.int32)) | ||||
|  | ||||
|             idx = date_range( | ||||
|                 "2014-11-01 18:00", "2014-11-02 05:00", freq=freq, tz="US/Eastern" | ||||
|             ) | ||||
|             idx = idx.tz_convert("UTC") | ||||
|             expected = np.repeat( | ||||
|                 np.array([22, 23, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]), | ||||
|                 np.array([n, n, n, n, n, n, n, n, n, n, n, n, 1]), | ||||
|             ) | ||||
|             tm.assert_index_equal(idx.hour, Index(expected, dtype=np.int32)) | ||||
|  | ||||
|         # daily | ||||
|         # Start DST | ||||
|         idx = date_range("2014-03-08 00:00", "2014-03-09 00:00", freq="D", tz="UTC") | ||||
|         idx = idx.tz_convert("US/Eastern") | ||||
|         tm.assert_index_equal(idx.hour, Index([19, 19], dtype=np.int32)) | ||||
|  | ||||
|         idx = date_range( | ||||
|             "2014-03-08 00:00", "2014-03-09 00:00", freq="D", tz="US/Eastern" | ||||
|         ) | ||||
|         idx = idx.tz_convert("UTC") | ||||
|         tm.assert_index_equal(idx.hour, Index([5, 5], dtype=np.int32)) | ||||
|  | ||||
|         # End DST | ||||
|         idx = date_range("2014-11-01 00:00", "2014-11-02 00:00", freq="D", tz="UTC") | ||||
|         idx = idx.tz_convert("US/Eastern") | ||||
|         tm.assert_index_equal(idx.hour, Index([20, 20], dtype=np.int32)) | ||||
|  | ||||
|         idx = date_range( | ||||
|             "2014-11-01 00:00", "2014-11-02 000:00", freq="D", tz="US/Eastern" | ||||
|         ) | ||||
|         idx = idx.tz_convert("UTC") | ||||
|         tm.assert_index_equal(idx.hour, Index([4, 4], dtype=np.int32)) | ||||
|  | ||||
|     def test_tz_convert_roundtrip(self, tz_aware_fixture): | ||||
|         tz = tz_aware_fixture | ||||
|         idx1 = date_range(start="2014-01-01", end="2014-12-31", freq="ME", tz="UTC") | ||||
|         exp1 = date_range(start="2014-01-01", end="2014-12-31", freq="ME") | ||||
|  | ||||
|         idx2 = date_range(start="2014-01-01", end="2014-12-31", freq="D", tz="UTC") | ||||
|         exp2 = date_range(start="2014-01-01", end="2014-12-31", freq="D") | ||||
|  | ||||
|         idx3 = date_range(start="2014-01-01", end="2014-03-01", freq="h", tz="UTC") | ||||
|         exp3 = date_range(start="2014-01-01", end="2014-03-01", freq="h") | ||||
|  | ||||
|         idx4 = date_range(start="2014-08-01", end="2014-10-31", freq="min", tz="UTC") | ||||
|         exp4 = date_range(start="2014-08-01", end="2014-10-31", freq="min") | ||||
|  | ||||
|         for idx, expected in [(idx1, exp1), (idx2, exp2), (idx3, exp3), (idx4, exp4)]: | ||||
|             converted = idx.tz_convert(tz) | ||||
|             reset = converted.tz_convert(None) | ||||
|             tm.assert_index_equal(reset, expected) | ||||
|             assert reset.tzinfo is None | ||||
|             expected = converted.tz_convert("UTC").tz_localize(None) | ||||
|             expected = expected._with_freq("infer") | ||||
|             tm.assert_index_equal(reset, expected) | ||||
|  | ||||
|     def test_dti_tz_convert_tzlocal(self): | ||||
|         # GH#13583 | ||||
|         # tz_convert doesn't affect to internal | ||||
|         dti = date_range(start="2001-01-01", end="2001-03-01", tz="UTC") | ||||
|         dti2 = dti.tz_convert(dateutil.tz.tzlocal()) | ||||
|         tm.assert_numpy_array_equal(dti2.asi8, dti.asi8) | ||||
|  | ||||
|         dti = date_range(start="2001-01-01", end="2001-03-01", tz=dateutil.tz.tzlocal()) | ||||
|         dti2 = dti.tz_convert(None) | ||||
|         tm.assert_numpy_array_equal(dti2.asi8, dti.asi8) | ||||
|  | ||||
|     @pytest.mark.parametrize( | ||||
|         "tz", | ||||
|         [ | ||||
|             "US/Eastern", | ||||
|             "dateutil/US/Eastern", | ||||
|             pytz.timezone("US/Eastern"), | ||||
|             gettz("US/Eastern"), | ||||
|         ], | ||||
|     ) | ||||
|     def test_dti_tz_convert_utc_to_local_no_modify(self, tz): | ||||
|         rng = date_range("3/11/2012", "3/12/2012", freq="h", tz="utc") | ||||
|         rng_eastern = rng.tz_convert(tz) | ||||
|  | ||||
|         # Values are unmodified | ||||
|         tm.assert_numpy_array_equal(rng.asi8, rng_eastern.asi8) | ||||
|  | ||||
|         assert timezones.tz_compare(rng_eastern.tz, timezones.maybe_get_tz(tz)) | ||||
|  | ||||
|     @pytest.mark.parametrize("tzstr", ["US/Eastern", "dateutil/US/Eastern"]) | ||||
|     def test_tz_convert_unsorted(self, tzstr): | ||||
|         dr = date_range("2012-03-09", freq="h", periods=100, tz="utc") | ||||
|         dr = dr.tz_convert(tzstr) | ||||
|  | ||||
|         result = dr[::-1].hour | ||||
|         exp = dr.hour[::-1] | ||||
|         tm.assert_almost_equal(result, exp) | ||||
| @ -0,0 +1,402 @@ | ||||
| from datetime import ( | ||||
|     datetime, | ||||
|     timedelta, | ||||
| ) | ||||
|  | ||||
| import dateutil.tz | ||||
| from dateutil.tz import gettz | ||||
| import numpy as np | ||||
| import pytest | ||||
| import pytz | ||||
|  | ||||
| from pandas import ( | ||||
|     DatetimeIndex, | ||||
|     Timestamp, | ||||
|     bdate_range, | ||||
|     date_range, | ||||
|     offsets, | ||||
|     to_datetime, | ||||
| ) | ||||
| import pandas._testing as tm | ||||
|  | ||||
| try: | ||||
|     from zoneinfo import ZoneInfo | ||||
| except ImportError: | ||||
|     # Cannot assign to a type  [misc] | ||||
|     ZoneInfo = None  # type: ignore[misc, assignment] | ||||
|  | ||||
|  | ||||
| easts = [pytz.timezone("US/Eastern"), gettz("US/Eastern")] | ||||
| if ZoneInfo is not None: | ||||
|     try: | ||||
|         tz = ZoneInfo("US/Eastern") | ||||
|     except KeyError: | ||||
|         # no tzdata | ||||
|         pass | ||||
|     else: | ||||
|         easts.append(tz) | ||||
|  | ||||
|  | ||||
| class TestTZLocalize: | ||||
|     def test_tz_localize_invalidates_freq(self): | ||||
|         # we only preserve freq in unambiguous cases | ||||
|  | ||||
|         # if localized to US/Eastern, this crosses a DST transition | ||||
|         dti = date_range("2014-03-08 23:00", "2014-03-09 09:00", freq="h") | ||||
|         assert dti.freq == "h" | ||||
|  | ||||
|         result = dti.tz_localize(None)  # no-op | ||||
|         assert result.freq == "h" | ||||
|  | ||||
|         result = dti.tz_localize("UTC")  # unambiguous freq preservation | ||||
|         assert result.freq == "h" | ||||
|  | ||||
|         result = dti.tz_localize("US/Eastern", nonexistent="shift_forward") | ||||
|         assert result.freq is None | ||||
|         assert result.inferred_freq is None  # i.e. we are not _too_ strict here | ||||
|  | ||||
|         # Case where we _can_ keep freq because we're length==1 | ||||
|         dti2 = dti[:1] | ||||
|         result = dti2.tz_localize("US/Eastern") | ||||
|         assert result.freq == "h" | ||||
|  | ||||
|     def test_tz_localize_utc_copies(self, utc_fixture): | ||||
|         # GH#46460 | ||||
|         times = ["2015-03-08 01:00", "2015-03-08 02:00", "2015-03-08 03:00"] | ||||
|         index = DatetimeIndex(times) | ||||
|  | ||||
|         res = index.tz_localize(utc_fixture) | ||||
|         assert not tm.shares_memory(res, index) | ||||
|  | ||||
|         res2 = index._data.tz_localize(utc_fixture) | ||||
|         assert not tm.shares_memory(index._data, res2) | ||||
|  | ||||
|     def test_dti_tz_localize_nonexistent_raise_coerce(self): | ||||
|         # GH#13057 | ||||
|         times = ["2015-03-08 01:00", "2015-03-08 02:00", "2015-03-08 03:00"] | ||||
|         index = DatetimeIndex(times) | ||||
|         tz = "US/Eastern" | ||||
|         with pytest.raises(pytz.NonExistentTimeError, match="|".join(times)): | ||||
|             index.tz_localize(tz=tz) | ||||
|  | ||||
|         with pytest.raises(pytz.NonExistentTimeError, match="|".join(times)): | ||||
|             index.tz_localize(tz=tz, nonexistent="raise") | ||||
|  | ||||
|         result = index.tz_localize(tz=tz, nonexistent="NaT") | ||||
|         test_times = ["2015-03-08 01:00-05:00", "NaT", "2015-03-08 03:00-04:00"] | ||||
|         dti = to_datetime(test_times, utc=True) | ||||
|         expected = dti.tz_convert("US/Eastern") | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|     @pytest.mark.parametrize("tz", easts) | ||||
|     def test_dti_tz_localize_ambiguous_infer(self, tz): | ||||
|         # November 6, 2011, fall back, repeat 2 AM hour | ||||
|         # With no repeated hours, we cannot infer the transition | ||||
|         dr = date_range(datetime(2011, 11, 6, 0), periods=5, freq=offsets.Hour()) | ||||
|         with pytest.raises(pytz.AmbiguousTimeError, match="Cannot infer dst time"): | ||||
|             dr.tz_localize(tz) | ||||
|  | ||||
|     @pytest.mark.parametrize("tz", easts) | ||||
|     def test_dti_tz_localize_ambiguous_infer2(self, tz, unit): | ||||
|         # With repeated hours, we can infer the transition | ||||
|         dr = date_range( | ||||
|             datetime(2011, 11, 6, 0), periods=5, freq=offsets.Hour(), tz=tz, unit=unit | ||||
|         ) | ||||
|         times = [ | ||||
|             "11/06/2011 00:00", | ||||
|             "11/06/2011 01:00", | ||||
|             "11/06/2011 01:00", | ||||
|             "11/06/2011 02:00", | ||||
|             "11/06/2011 03:00", | ||||
|         ] | ||||
|         di = DatetimeIndex(times).as_unit(unit) | ||||
|         result = di.tz_localize(tz, ambiguous="infer") | ||||
|         expected = dr._with_freq(None) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|         result2 = DatetimeIndex(times, tz=tz, ambiguous="infer").as_unit(unit) | ||||
|         tm.assert_index_equal(result2, expected) | ||||
|  | ||||
|     @pytest.mark.parametrize("tz", easts) | ||||
|     def test_dti_tz_localize_ambiguous_infer3(self, tz): | ||||
|         # When there is no dst transition, nothing special happens | ||||
|         dr = date_range(datetime(2011, 6, 1, 0), periods=10, freq=offsets.Hour()) | ||||
|         localized = dr.tz_localize(tz) | ||||
|         localized_infer = dr.tz_localize(tz, ambiguous="infer") | ||||
|         tm.assert_index_equal(localized, localized_infer) | ||||
|  | ||||
|     @pytest.mark.parametrize("tz", easts) | ||||
|     def test_dti_tz_localize_ambiguous_times(self, tz): | ||||
|         # March 13, 2011, spring forward, skip from 2 AM to 3 AM | ||||
|         dr = date_range(datetime(2011, 3, 13, 1, 30), periods=3, freq=offsets.Hour()) | ||||
|         with pytest.raises(pytz.NonExistentTimeError, match="2011-03-13 02:30:00"): | ||||
|             dr.tz_localize(tz) | ||||
|  | ||||
|         # after dst transition, it works | ||||
|         dr = date_range( | ||||
|             datetime(2011, 3, 13, 3, 30), periods=3, freq=offsets.Hour(), tz=tz | ||||
|         ) | ||||
|  | ||||
|         # November 6, 2011, fall back, repeat 2 AM hour | ||||
|         dr = date_range(datetime(2011, 11, 6, 1, 30), periods=3, freq=offsets.Hour()) | ||||
|         with pytest.raises(pytz.AmbiguousTimeError, match="Cannot infer dst time"): | ||||
|             dr.tz_localize(tz) | ||||
|  | ||||
|         # UTC is OK | ||||
|         dr = date_range( | ||||
|             datetime(2011, 3, 13), periods=48, freq=offsets.Minute(30), tz=pytz.utc | ||||
|         ) | ||||
|  | ||||
|     @pytest.mark.parametrize("tzstr", ["US/Eastern", "dateutil/US/Eastern"]) | ||||
|     def test_dti_tz_localize_pass_dates_to_utc(self, tzstr): | ||||
|         strdates = ["1/1/2012", "3/1/2012", "4/1/2012"] | ||||
|  | ||||
|         idx = DatetimeIndex(strdates) | ||||
|         conv = idx.tz_localize(tzstr) | ||||
|  | ||||
|         fromdates = DatetimeIndex(strdates, tz=tzstr) | ||||
|  | ||||
|         assert conv.tz == fromdates.tz | ||||
|         tm.assert_numpy_array_equal(conv.values, fromdates.values) | ||||
|  | ||||
|     @pytest.mark.parametrize("prefix", ["", "dateutil/"]) | ||||
|     def test_dti_tz_localize(self, prefix): | ||||
|         tzstr = prefix + "US/Eastern" | ||||
|         dti = date_range(start="1/1/2005", end="1/1/2005 0:00:30.256", freq="ms") | ||||
|         dti2 = dti.tz_localize(tzstr) | ||||
|  | ||||
|         dti_utc = date_range( | ||||
|             start="1/1/2005 05:00", end="1/1/2005 5:00:30.256", freq="ms", tz="utc" | ||||
|         ) | ||||
|  | ||||
|         tm.assert_numpy_array_equal(dti2.values, dti_utc.values) | ||||
|  | ||||
|         dti3 = dti2.tz_convert(prefix + "US/Pacific") | ||||
|         tm.assert_numpy_array_equal(dti3.values, dti_utc.values) | ||||
|  | ||||
|         dti = date_range(start="11/6/2011 1:59", end="11/6/2011 2:00", freq="ms") | ||||
|         with pytest.raises(pytz.AmbiguousTimeError, match="Cannot infer dst time"): | ||||
|             dti.tz_localize(tzstr) | ||||
|  | ||||
|         dti = date_range(start="3/13/2011 1:59", end="3/13/2011 2:00", freq="ms") | ||||
|         with pytest.raises(pytz.NonExistentTimeError, match="2011-03-13 02:00:00"): | ||||
|             dti.tz_localize(tzstr) | ||||
|  | ||||
|     @pytest.mark.parametrize( | ||||
|         "tz", | ||||
|         [ | ||||
|             "US/Eastern", | ||||
|             "dateutil/US/Eastern", | ||||
|             pytz.timezone("US/Eastern"), | ||||
|             gettz("US/Eastern"), | ||||
|         ], | ||||
|     ) | ||||
|     def test_dti_tz_localize_utc_conversion(self, tz): | ||||
|         # Localizing to time zone should: | ||||
|         #  1) check for DST ambiguities | ||||
|         #  2) convert to UTC | ||||
|  | ||||
|         rng = date_range("3/10/2012", "3/11/2012", freq="30min") | ||||
|  | ||||
|         converted = rng.tz_localize(tz) | ||||
|         expected_naive = rng + offsets.Hour(5) | ||||
|         tm.assert_numpy_array_equal(converted.asi8, expected_naive.asi8) | ||||
|  | ||||
|         # DST ambiguity, this should fail | ||||
|         rng = date_range("3/11/2012", "3/12/2012", freq="30min") | ||||
|         # Is this really how it should fail?? | ||||
|         with pytest.raises(pytz.NonExistentTimeError, match="2012-03-11 02:00:00"): | ||||
|             rng.tz_localize(tz) | ||||
|  | ||||
|     def test_dti_tz_localize_roundtrip(self, tz_aware_fixture): | ||||
|         # note: this tz tests that a tz-naive index can be localized | ||||
|         # and de-localized successfully, when there are no DST transitions | ||||
|         # in the range. | ||||
|         idx = date_range(start="2014-06-01", end="2014-08-30", freq="15min") | ||||
|         tz = tz_aware_fixture | ||||
|         localized = idx.tz_localize(tz) | ||||
|         # can't localize a tz-aware object | ||||
|         with pytest.raises( | ||||
|             TypeError, match="Already tz-aware, use tz_convert to convert" | ||||
|         ): | ||||
|             localized.tz_localize(tz) | ||||
|         reset = localized.tz_localize(None) | ||||
|         assert reset.tzinfo is None | ||||
|         expected = idx._with_freq(None) | ||||
|         tm.assert_index_equal(reset, expected) | ||||
|  | ||||
|     def test_dti_tz_localize_naive(self): | ||||
|         rng = date_range("1/1/2011", periods=100, freq="h") | ||||
|  | ||||
|         conv = rng.tz_localize("US/Pacific") | ||||
|         exp = date_range("1/1/2011", periods=100, freq="h", tz="US/Pacific") | ||||
|  | ||||
|         tm.assert_index_equal(conv, exp._with_freq(None)) | ||||
|  | ||||
|     def test_dti_tz_localize_tzlocal(self): | ||||
|         # GH#13583 | ||||
|         offset = dateutil.tz.tzlocal().utcoffset(datetime(2011, 1, 1)) | ||||
|         offset = int(offset.total_seconds() * 1000000000) | ||||
|  | ||||
|         dti = date_range(start="2001-01-01", end="2001-03-01") | ||||
|         dti2 = dti.tz_localize(dateutil.tz.tzlocal()) | ||||
|         tm.assert_numpy_array_equal(dti2.asi8 + offset, dti.asi8) | ||||
|  | ||||
|         dti = date_range(start="2001-01-01", end="2001-03-01", tz=dateutil.tz.tzlocal()) | ||||
|         dti2 = dti.tz_localize(None) | ||||
|         tm.assert_numpy_array_equal(dti2.asi8 - offset, dti.asi8) | ||||
|  | ||||
|     @pytest.mark.parametrize("tz", easts) | ||||
|     def test_dti_tz_localize_ambiguous_nat(self, tz): | ||||
|         times = [ | ||||
|             "11/06/2011 00:00", | ||||
|             "11/06/2011 01:00", | ||||
|             "11/06/2011 01:00", | ||||
|             "11/06/2011 02:00", | ||||
|             "11/06/2011 03:00", | ||||
|         ] | ||||
|         di = DatetimeIndex(times) | ||||
|         localized = di.tz_localize(tz, ambiguous="NaT") | ||||
|  | ||||
|         times = [ | ||||
|             "11/06/2011 00:00", | ||||
|             np.nan, | ||||
|             np.nan, | ||||
|             "11/06/2011 02:00", | ||||
|             "11/06/2011 03:00", | ||||
|         ] | ||||
|         di_test = DatetimeIndex(times, tz="US/Eastern") | ||||
|  | ||||
|         # left dtype is datetime64[ns, US/Eastern] | ||||
|         # right is datetime64[ns, tzfile('/usr/share/zoneinfo/US/Eastern')] | ||||
|         tm.assert_numpy_array_equal(di_test.values, localized.values) | ||||
|  | ||||
|     @pytest.mark.parametrize("tz", easts) | ||||
|     def test_dti_tz_localize_ambiguous_flags(self, tz, unit): | ||||
|         # November 6, 2011, fall back, repeat 2 AM hour | ||||
|  | ||||
|         # Pass in flags to determine right dst transition | ||||
|         dr = date_range( | ||||
|             datetime(2011, 11, 6, 0), periods=5, freq=offsets.Hour(), tz=tz, unit=unit | ||||
|         ) | ||||
|         times = [ | ||||
|             "11/06/2011 00:00", | ||||
|             "11/06/2011 01:00", | ||||
|             "11/06/2011 01:00", | ||||
|             "11/06/2011 02:00", | ||||
|             "11/06/2011 03:00", | ||||
|         ] | ||||
|  | ||||
|         # Test tz_localize | ||||
|         di = DatetimeIndex(times).as_unit(unit) | ||||
|         is_dst = [1, 1, 0, 0, 0] | ||||
|         localized = di.tz_localize(tz, ambiguous=is_dst) | ||||
|         expected = dr._with_freq(None) | ||||
|         tm.assert_index_equal(expected, localized) | ||||
|  | ||||
|         result = DatetimeIndex(times, tz=tz, ambiguous=is_dst).as_unit(unit) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         localized = di.tz_localize(tz, ambiguous=np.array(is_dst)) | ||||
|         tm.assert_index_equal(dr, localized) | ||||
|  | ||||
|         localized = di.tz_localize(tz, ambiguous=np.array(is_dst).astype("bool")) | ||||
|         tm.assert_index_equal(dr, localized) | ||||
|  | ||||
|         # Test constructor | ||||
|         localized = DatetimeIndex(times, tz=tz, ambiguous=is_dst).as_unit(unit) | ||||
|         tm.assert_index_equal(dr, localized) | ||||
|  | ||||
|         # Test duplicate times where inferring the dst fails | ||||
|         times += times | ||||
|         di = DatetimeIndex(times).as_unit(unit) | ||||
|  | ||||
|         # When the sizes are incompatible, make sure error is raised | ||||
|         msg = "Length of ambiguous bool-array must be the same size as vals" | ||||
|         with pytest.raises(Exception, match=msg): | ||||
|             di.tz_localize(tz, ambiguous=is_dst) | ||||
|  | ||||
|         # When sizes are compatible and there are repeats ('infer' won't work) | ||||
|         is_dst = np.hstack((is_dst, is_dst)) | ||||
|         localized = di.tz_localize(tz, ambiguous=is_dst) | ||||
|         dr = dr.append(dr) | ||||
|         tm.assert_index_equal(dr, localized) | ||||
|  | ||||
|     @pytest.mark.parametrize("tz", easts) | ||||
|     def test_dti_tz_localize_ambiguous_flags2(self, tz, unit): | ||||
|         # When there is no dst transition, nothing special happens | ||||
|         dr = date_range(datetime(2011, 6, 1, 0), periods=10, freq=offsets.Hour()) | ||||
|         is_dst = np.array([1] * 10) | ||||
|         localized = dr.tz_localize(tz) | ||||
|         localized_is_dst = dr.tz_localize(tz, ambiguous=is_dst) | ||||
|         tm.assert_index_equal(localized, localized_is_dst) | ||||
|  | ||||
|     def test_dti_tz_localize_bdate_range(self): | ||||
|         dr = bdate_range("1/1/2009", "1/1/2010") | ||||
|         dr_utc = bdate_range("1/1/2009", "1/1/2010", tz=pytz.utc) | ||||
|         localized = dr.tz_localize(pytz.utc) | ||||
|         tm.assert_index_equal(dr_utc, localized) | ||||
|  | ||||
|     @pytest.mark.parametrize( | ||||
|         "start_ts, tz, end_ts, shift", | ||||
|         [ | ||||
|             ["2015-03-29 02:20:00", "Europe/Warsaw", "2015-03-29 03:00:00", "forward"], | ||||
|             [ | ||||
|                 "2015-03-29 02:20:00", | ||||
|                 "Europe/Warsaw", | ||||
|                 "2015-03-29 01:59:59.999999999", | ||||
|                 "backward", | ||||
|             ], | ||||
|             [ | ||||
|                 "2015-03-29 02:20:00", | ||||
|                 "Europe/Warsaw", | ||||
|                 "2015-03-29 03:20:00", | ||||
|                 timedelta(hours=1), | ||||
|             ], | ||||
|             [ | ||||
|                 "2015-03-29 02:20:00", | ||||
|                 "Europe/Warsaw", | ||||
|                 "2015-03-29 01:20:00", | ||||
|                 timedelta(hours=-1), | ||||
|             ], | ||||
|             ["2018-03-11 02:33:00", "US/Pacific", "2018-03-11 03:00:00", "forward"], | ||||
|             [ | ||||
|                 "2018-03-11 02:33:00", | ||||
|                 "US/Pacific", | ||||
|                 "2018-03-11 01:59:59.999999999", | ||||
|                 "backward", | ||||
|             ], | ||||
|             [ | ||||
|                 "2018-03-11 02:33:00", | ||||
|                 "US/Pacific", | ||||
|                 "2018-03-11 03:33:00", | ||||
|                 timedelta(hours=1), | ||||
|             ], | ||||
|             [ | ||||
|                 "2018-03-11 02:33:00", | ||||
|                 "US/Pacific", | ||||
|                 "2018-03-11 01:33:00", | ||||
|                 timedelta(hours=-1), | ||||
|             ], | ||||
|         ], | ||||
|     ) | ||||
|     @pytest.mark.parametrize("tz_type", ["", "dateutil/"]) | ||||
|     def test_dti_tz_localize_nonexistent_shift( | ||||
|         self, start_ts, tz, end_ts, shift, tz_type, unit | ||||
|     ): | ||||
|         # GH#8917 | ||||
|         tz = tz_type + tz | ||||
|         if isinstance(shift, str): | ||||
|             shift = "shift_" + shift | ||||
|         dti = DatetimeIndex([Timestamp(start_ts)]).as_unit(unit) | ||||
|         result = dti.tz_localize(tz, nonexistent=shift) | ||||
|         expected = DatetimeIndex([Timestamp(end_ts)]).tz_localize(tz).as_unit(unit) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|     @pytest.mark.parametrize("offset", [-1, 1]) | ||||
|     def test_dti_tz_localize_nonexistent_shift_invalid(self, offset, warsaw): | ||||
|         # GH#8917 | ||||
|         tz = warsaw | ||||
|         dti = DatetimeIndex([Timestamp("2015-03-29 02:20:00")]) | ||||
|         msg = "The provided timedelta will relocalize on a nonexistent time" | ||||
|         with pytest.raises(ValueError, match=msg): | ||||
|             dti.tz_localize(tz, nonexistent=timedelta(seconds=offset)) | ||||
| @ -0,0 +1,77 @@ | ||||
| from datetime import ( | ||||
|     datetime, | ||||
|     timedelta, | ||||
| ) | ||||
|  | ||||
| from pandas import ( | ||||
|     DatetimeIndex, | ||||
|     NaT, | ||||
|     Timestamp, | ||||
| ) | ||||
| import pandas._testing as tm | ||||
|  | ||||
|  | ||||
| def test_unique(tz_naive_fixture): | ||||
|     idx = DatetimeIndex(["2017"] * 2, tz=tz_naive_fixture) | ||||
|     expected = idx[:1] | ||||
|  | ||||
|     result = idx.unique() | ||||
|     tm.assert_index_equal(result, expected) | ||||
|     # GH#21737 | ||||
|     # Ensure the underlying data is consistent | ||||
|     assert result[0] == expected[0] | ||||
|  | ||||
|  | ||||
| def test_index_unique(rand_series_with_duplicate_datetimeindex): | ||||
|     dups = rand_series_with_duplicate_datetimeindex | ||||
|     index = dups.index | ||||
|  | ||||
|     uniques = index.unique() | ||||
|     expected = DatetimeIndex( | ||||
|         [ | ||||
|             datetime(2000, 1, 2), | ||||
|             datetime(2000, 1, 3), | ||||
|             datetime(2000, 1, 4), | ||||
|             datetime(2000, 1, 5), | ||||
|         ], | ||||
|         dtype=index.dtype, | ||||
|     ) | ||||
|     assert uniques.dtype == index.dtype  # sanity | ||||
|     tm.assert_index_equal(uniques, expected) | ||||
|     assert index.nunique() == 4 | ||||
|  | ||||
|     # GH#2563 | ||||
|     assert isinstance(uniques, DatetimeIndex) | ||||
|  | ||||
|     dups_local = index.tz_localize("US/Eastern") | ||||
|     dups_local.name = "foo" | ||||
|     result = dups_local.unique() | ||||
|     expected = DatetimeIndex(expected, name="foo") | ||||
|     expected = expected.tz_localize("US/Eastern") | ||||
|     assert result.tz is not None | ||||
|     assert result.name == "foo" | ||||
|     tm.assert_index_equal(result, expected) | ||||
|  | ||||
|  | ||||
| def test_index_unique2(): | ||||
|     # NaT, note this is excluded | ||||
|     arr = [1370745748 + t for t in range(20)] + [NaT._value] | ||||
|     idx = DatetimeIndex(arr * 3) | ||||
|     tm.assert_index_equal(idx.unique(), DatetimeIndex(arr)) | ||||
|     assert idx.nunique() == 20 | ||||
|     assert idx.nunique(dropna=False) == 21 | ||||
|  | ||||
|  | ||||
| def test_index_unique3(): | ||||
|     arr = [ | ||||
|         Timestamp("2013-06-09 02:42:28") + timedelta(seconds=t) for t in range(20) | ||||
|     ] + [NaT] | ||||
|     idx = DatetimeIndex(arr * 3) | ||||
|     tm.assert_index_equal(idx.unique(), DatetimeIndex(arr)) | ||||
|     assert idx.nunique() == 20 | ||||
|     assert idx.nunique(dropna=False) == 21 | ||||
|  | ||||
|  | ||||
| def test_is_unique_monotonic(rand_series_with_duplicate_datetimeindex): | ||||
|     index = rand_series_with_duplicate_datetimeindex.index | ||||
|     assert not index.is_unique | ||||
		Reference in New Issue
	
	Block a user