123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098 |
- from datetime import (
- datetime,
- timedelta,
- timezone,
- )
- from functools import partial
- from operator import attrgetter
- import dateutil
- import numpy as np
- import pytest
- import pytz
- from pandas._libs.tslibs import (
- OutOfBoundsDatetime,
- astype_overflowsafe,
- )
- import pandas as pd
- from pandas import (
- DatetimeIndex,
- Index,
- Timestamp,
- date_range,
- offsets,
- to_datetime,
- )
- import pandas._testing as tm
- from pandas.core.arrays import (
- DatetimeArray,
- period_array,
- )
- class TestDatetimeIndex:
- def test_from_dt64_unsupported_unit(self):
- # GH#49292
- val = np.datetime64(1, "D")
- result = DatetimeIndex([val], tz="US/Pacific")
- expected = DatetimeIndex([val.astype("M8[s]")], tz="US/Pacific")
- tm.assert_index_equal(result, expected)
- def test_explicit_tz_none(self):
- # GH#48659
- dti = date_range("2016-01-01", periods=10, tz="UTC")
- msg = "Passed data is timezone-aware, incompatible with 'tz=None'"
- with pytest.raises(ValueError, match=msg):
- DatetimeIndex(dti, tz=None)
- with pytest.raises(ValueError, match=msg):
- DatetimeIndex(np.array(dti), tz=None)
- msg = "Cannot pass both a timezone-aware dtype and tz=None"
- with pytest.raises(ValueError, match=msg):
- DatetimeIndex([], dtype="M8[ns, UTC]", tz=None)
- @pytest.mark.parametrize(
- "dt_cls", [DatetimeIndex, DatetimeArray._from_sequence_not_strict]
- )
- def test_freq_validation_with_nat(self, dt_cls):
- # GH#11587 make sure we get a useful error message when generate_range
- # raises
- msg = (
- "Inferred frequency None from passed values does not conform "
- "to passed frequency D"
- )
- with pytest.raises(ValueError, match=msg):
- dt_cls([pd.NaT, Timestamp("2011-01-01")], freq="D")
- with pytest.raises(ValueError, match=msg):
- dt_cls([pd.NaT, Timestamp("2011-01-01")._value], freq="D")
- # TODO: better place for tests shared by DTI/TDI?
- @pytest.mark.parametrize(
- "index",
- [
- date_range("2016-01-01", periods=5, tz="US/Pacific"),
- pd.timedelta_range("1 Day", periods=5),
- ],
- )
- def test_shallow_copy_inherits_array_freq(self, index):
- # If we pass a DTA/TDA to shallow_copy and dont specify a freq,
- # we should inherit the array's freq, not our own.
- array = index._data
- arr = array[[0, 3, 2, 4, 1]]
- assert arr.freq is None
- result = index._shallow_copy(arr)
- assert result.freq is None
- def test_categorical_preserves_tz(self):
- # GH#18664 retain tz when going DTI-->Categorical-->DTI
- dti = DatetimeIndex(
- [pd.NaT, "2015-01-01", "1999-04-06 15:14:13", "2015-01-01"], tz="US/Eastern"
- )
- for dtobj in [dti, dti._data]:
- # works for DatetimeIndex or DatetimeArray
- ci = pd.CategoricalIndex(dtobj)
- carr = pd.Categorical(dtobj)
- cser = pd.Series(ci)
- for obj in [ci, carr, cser]:
- result = DatetimeIndex(obj)
- tm.assert_index_equal(result, dti)
- def test_dti_with_period_data_raises(self):
- # GH#23675
- data = pd.PeriodIndex(["2016Q1", "2016Q2"], freq="Q")
- with pytest.raises(TypeError, match="PeriodDtype data is invalid"):
- DatetimeIndex(data)
- with pytest.raises(TypeError, match="PeriodDtype data is invalid"):
- to_datetime(data)
- with pytest.raises(TypeError, match="PeriodDtype data is invalid"):
- DatetimeIndex(period_array(data))
- with pytest.raises(TypeError, match="PeriodDtype data is invalid"):
- to_datetime(period_array(data))
- def test_dti_with_timedelta64_data_raises(self):
- # GH#23675 deprecated, enforrced in GH#29794
- data = np.array([0], dtype="m8[ns]")
- msg = r"timedelta64\[ns\] cannot be converted to datetime64"
- with pytest.raises(TypeError, match=msg):
- DatetimeIndex(data)
- with pytest.raises(TypeError, match=msg):
- to_datetime(data)
- with pytest.raises(TypeError, match=msg):
- DatetimeIndex(pd.TimedeltaIndex(data))
- with pytest.raises(TypeError, match=msg):
- to_datetime(pd.TimedeltaIndex(data))
- def test_constructor_from_sparse_array(self):
- # https://github.com/pandas-dev/pandas/issues/35843
- values = [
- Timestamp("2012-05-01T01:00:00.000000"),
- Timestamp("2016-05-01T01:00:00.000000"),
- ]
- arr = pd.arrays.SparseArray(values)
- result = Index(arr)
- assert type(result) is Index
- assert result.dtype == arr.dtype
- def test_construction_caching(self):
- df = pd.DataFrame(
- {
- "dt": date_range("20130101", periods=3),
- "dttz": date_range("20130101", periods=3, tz="US/Eastern"),
- "dt_with_null": [
- Timestamp("20130101"),
- pd.NaT,
- Timestamp("20130103"),
- ],
- "dtns": date_range("20130101", periods=3, freq="ns"),
- }
- )
- assert df.dttz.dtype.tz.zone == "US/Eastern"
- @pytest.mark.parametrize(
- "kwargs",
- [{"tz": "dtype.tz"}, {"dtype": "dtype"}, {"dtype": "dtype", "tz": "dtype.tz"}],
- )
- def test_construction_with_alt(self, kwargs, tz_aware_fixture):
- tz = tz_aware_fixture
- i = date_range("20130101", periods=5, freq="H", tz=tz)
- kwargs = {key: attrgetter(val)(i) for key, val in kwargs.items()}
- result = DatetimeIndex(i, **kwargs)
- tm.assert_index_equal(i, result)
- @pytest.mark.parametrize(
- "kwargs",
- [{"tz": "dtype.tz"}, {"dtype": "dtype"}, {"dtype": "dtype", "tz": "dtype.tz"}],
- )
- def test_construction_with_alt_tz_localize(self, kwargs, tz_aware_fixture):
- tz = tz_aware_fixture
- i = date_range("20130101", periods=5, freq="H", tz=tz)
- i = i._with_freq(None)
- kwargs = {key: attrgetter(val)(i) for key, val in kwargs.items()}
- if "tz" in kwargs:
- result = DatetimeIndex(i.asi8, tz="UTC").tz_convert(kwargs["tz"])
- expected = DatetimeIndex(i, **kwargs)
- tm.assert_index_equal(result, expected)
- # localize into the provided tz
- i2 = DatetimeIndex(i.tz_localize(None).asi8, tz="UTC")
- expected = i.tz_localize(None).tz_localize("UTC")
- tm.assert_index_equal(i2, expected)
- # incompat tz/dtype
- msg = "cannot supply both a tz and a dtype with a tz"
- with pytest.raises(ValueError, match=msg):
- DatetimeIndex(i.tz_localize(None).asi8, dtype=i.dtype, tz="US/Pacific")
- def test_construction_index_with_mixed_timezones(self):
- # gh-11488: no tz results in DatetimeIndex
- result = Index([Timestamp("2011-01-01"), Timestamp("2011-01-02")], name="idx")
- exp = DatetimeIndex(
- [Timestamp("2011-01-01"), Timestamp("2011-01-02")], name="idx"
- )
- tm.assert_index_equal(result, exp, exact=True)
- assert isinstance(result, DatetimeIndex)
- assert result.tz is None
- # same tz results in DatetimeIndex
- result = Index(
- [
- Timestamp("2011-01-01 10:00", tz="Asia/Tokyo"),
- Timestamp("2011-01-02 10:00", tz="Asia/Tokyo"),
- ],
- name="idx",
- )
- exp = DatetimeIndex(
- [Timestamp("2011-01-01 10:00"), Timestamp("2011-01-02 10:00")],
- tz="Asia/Tokyo",
- name="idx",
- )
- tm.assert_index_equal(result, exp, exact=True)
- assert isinstance(result, DatetimeIndex)
- assert result.tz is not None
- assert result.tz == exp.tz
- # same tz results in DatetimeIndex (DST)
- result = Index(
- [
- Timestamp("2011-01-01 10:00", tz="US/Eastern"),
- Timestamp("2011-08-01 10:00", tz="US/Eastern"),
- ],
- name="idx",
- )
- exp = DatetimeIndex(
- [Timestamp("2011-01-01 10:00"), Timestamp("2011-08-01 10:00")],
- tz="US/Eastern",
- name="idx",
- )
- tm.assert_index_equal(result, exp, exact=True)
- assert isinstance(result, DatetimeIndex)
- assert result.tz is not None
- assert result.tz == exp.tz
- # Different tz results in Index(dtype=object)
- result = Index(
- [
- Timestamp("2011-01-01 10:00"),
- Timestamp("2011-01-02 10:00", tz="US/Eastern"),
- ],
- name="idx",
- )
- exp = Index(
- [
- Timestamp("2011-01-01 10:00"),
- Timestamp("2011-01-02 10:00", tz="US/Eastern"),
- ],
- dtype="object",
- name="idx",
- )
- tm.assert_index_equal(result, exp, exact=True)
- assert not isinstance(result, DatetimeIndex)
- result = Index(
- [
- Timestamp("2011-01-01 10:00", tz="Asia/Tokyo"),
- Timestamp("2011-01-02 10:00", tz="US/Eastern"),
- ],
- name="idx",
- )
- exp = Index(
- [
- Timestamp("2011-01-01 10:00", tz="Asia/Tokyo"),
- Timestamp("2011-01-02 10:00", tz="US/Eastern"),
- ],
- dtype="object",
- name="idx",
- )
- tm.assert_index_equal(result, exp, exact=True)
- assert not isinstance(result, DatetimeIndex)
- # length = 1
- result = Index([Timestamp("2011-01-01")], name="idx")
- exp = DatetimeIndex([Timestamp("2011-01-01")], name="idx")
- tm.assert_index_equal(result, exp, exact=True)
- assert isinstance(result, DatetimeIndex)
- assert result.tz is None
- # length = 1 with tz
- result = Index([Timestamp("2011-01-01 10:00", tz="Asia/Tokyo")], name="idx")
- exp = DatetimeIndex(
- [Timestamp("2011-01-01 10:00")], tz="Asia/Tokyo", name="idx"
- )
- tm.assert_index_equal(result, exp, exact=True)
- assert isinstance(result, DatetimeIndex)
- assert result.tz is not None
- assert result.tz == exp.tz
- def test_construction_index_with_mixed_timezones_with_NaT(self):
- # see gh-11488
- result = Index(
- [pd.NaT, Timestamp("2011-01-01"), pd.NaT, Timestamp("2011-01-02")],
- name="idx",
- )
- exp = DatetimeIndex(
- [pd.NaT, Timestamp("2011-01-01"), pd.NaT, Timestamp("2011-01-02")],
- name="idx",
- )
- tm.assert_index_equal(result, exp, exact=True)
- assert isinstance(result, DatetimeIndex)
- assert result.tz is None
- # Same tz results in DatetimeIndex
- result = Index(
- [
- pd.NaT,
- Timestamp("2011-01-01 10:00", tz="Asia/Tokyo"),
- pd.NaT,
- Timestamp("2011-01-02 10:00", tz="Asia/Tokyo"),
- ],
- name="idx",
- )
- exp = DatetimeIndex(
- [
- pd.NaT,
- Timestamp("2011-01-01 10:00"),
- pd.NaT,
- Timestamp("2011-01-02 10:00"),
- ],
- tz="Asia/Tokyo",
- name="idx",
- )
- tm.assert_index_equal(result, exp, exact=True)
- assert isinstance(result, DatetimeIndex)
- assert result.tz is not None
- assert result.tz == exp.tz
- # same tz results in DatetimeIndex (DST)
- result = Index(
- [
- Timestamp("2011-01-01 10:00", tz="US/Eastern"),
- pd.NaT,
- Timestamp("2011-08-01 10:00", tz="US/Eastern"),
- ],
- name="idx",
- )
- exp = DatetimeIndex(
- [Timestamp("2011-01-01 10:00"), pd.NaT, Timestamp("2011-08-01 10:00")],
- tz="US/Eastern",
- name="idx",
- )
- tm.assert_index_equal(result, exp, exact=True)
- assert isinstance(result, DatetimeIndex)
- assert result.tz is not None
- assert result.tz == exp.tz
- # different tz results in Index(dtype=object)
- result = Index(
- [
- pd.NaT,
- Timestamp("2011-01-01 10:00"),
- pd.NaT,
- Timestamp("2011-01-02 10:00", tz="US/Eastern"),
- ],
- name="idx",
- )
- exp = Index(
- [
- pd.NaT,
- Timestamp("2011-01-01 10:00"),
- pd.NaT,
- Timestamp("2011-01-02 10:00", tz="US/Eastern"),
- ],
- dtype="object",
- name="idx",
- )
- tm.assert_index_equal(result, exp, exact=True)
- assert not isinstance(result, DatetimeIndex)
- result = Index(
- [
- pd.NaT,
- Timestamp("2011-01-01 10:00", tz="Asia/Tokyo"),
- pd.NaT,
- Timestamp("2011-01-02 10:00", tz="US/Eastern"),
- ],
- name="idx",
- )
- exp = Index(
- [
- pd.NaT,
- Timestamp("2011-01-01 10:00", tz="Asia/Tokyo"),
- pd.NaT,
- Timestamp("2011-01-02 10:00", tz="US/Eastern"),
- ],
- dtype="object",
- name="idx",
- )
- tm.assert_index_equal(result, exp, exact=True)
- assert not isinstance(result, DatetimeIndex)
- # all NaT
- result = Index([pd.NaT, pd.NaT], name="idx")
- exp = DatetimeIndex([pd.NaT, pd.NaT], name="idx")
- tm.assert_index_equal(result, exp, exact=True)
- assert isinstance(result, DatetimeIndex)
- assert result.tz is None
- def test_construction_dti_with_mixed_timezones(self):
- # GH 11488 (not changed, added explicit tests)
- # no tz results in DatetimeIndex
- result = DatetimeIndex(
- [Timestamp("2011-01-01"), Timestamp("2011-01-02")], name="idx"
- )
- exp = DatetimeIndex(
- [Timestamp("2011-01-01"), Timestamp("2011-01-02")], name="idx"
- )
- tm.assert_index_equal(result, exp, exact=True)
- assert isinstance(result, DatetimeIndex)
- # same tz results in DatetimeIndex
- result = DatetimeIndex(
- [
- Timestamp("2011-01-01 10:00", tz="Asia/Tokyo"),
- Timestamp("2011-01-02 10:00", tz="Asia/Tokyo"),
- ],
- name="idx",
- )
- exp = DatetimeIndex(
- [Timestamp("2011-01-01 10:00"), Timestamp("2011-01-02 10:00")],
- tz="Asia/Tokyo",
- name="idx",
- )
- tm.assert_index_equal(result, exp, exact=True)
- assert isinstance(result, DatetimeIndex)
- # same tz results in DatetimeIndex (DST)
- result = DatetimeIndex(
- [
- Timestamp("2011-01-01 10:00", tz="US/Eastern"),
- Timestamp("2011-08-01 10:00", tz="US/Eastern"),
- ],
- name="idx",
- )
- exp = DatetimeIndex(
- [Timestamp("2011-01-01 10:00"), Timestamp("2011-08-01 10:00")],
- tz="US/Eastern",
- name="idx",
- )
- tm.assert_index_equal(result, exp, exact=True)
- assert isinstance(result, DatetimeIndex)
- # tz mismatch affecting to tz-aware raises TypeError/ValueError
- msg = "cannot be converted to datetime64"
- with pytest.raises(ValueError, match=msg):
- DatetimeIndex(
- [
- Timestamp("2011-01-01 10:00", tz="Asia/Tokyo"),
- Timestamp("2011-01-02 10:00", tz="US/Eastern"),
- ],
- name="idx",
- )
- # pre-2.0 this raised bc of awareness mismatch. in 2.0 with a tz#
- # specified we behave as if this was called pointwise, so
- # the naive Timestamp is treated as a wall time.
- dti = DatetimeIndex(
- [
- Timestamp("2011-01-01 10:00"),
- Timestamp("2011-01-02 10:00", tz="US/Eastern"),
- ],
- tz="Asia/Tokyo",
- name="idx",
- )
- expected = DatetimeIndex(
- [
- Timestamp("2011-01-01 10:00", tz="Asia/Tokyo"),
- Timestamp("2011-01-02 10:00", tz="US/Eastern").tz_convert("Asia/Tokyo"),
- ],
- tz="Asia/Tokyo",
- name="idx",
- )
- tm.assert_index_equal(dti, expected)
- # pre-2.0 mixed-tz scalars raised even if a tz/dtype was specified.
- # as of 2.0 we successfully return the requested tz/dtype
- dti = DatetimeIndex(
- [
- Timestamp("2011-01-01 10:00", tz="Asia/Tokyo"),
- Timestamp("2011-01-02 10:00", tz="US/Eastern"),
- ],
- tz="US/Eastern",
- name="idx",
- )
- expected = DatetimeIndex(
- [
- Timestamp("2011-01-01 10:00", tz="Asia/Tokyo").tz_convert("US/Eastern"),
- Timestamp("2011-01-02 10:00", tz="US/Eastern"),
- ],
- tz="US/Eastern",
- name="idx",
- )
- tm.assert_index_equal(dti, expected)
- # same thing but pass dtype instead of tz
- dti = DatetimeIndex(
- [
- Timestamp("2011-01-01 10:00", tz="Asia/Tokyo"),
- Timestamp("2011-01-02 10:00", tz="US/Eastern"),
- ],
- dtype="M8[ns, US/Eastern]",
- name="idx",
- )
- tm.assert_index_equal(dti, expected)
- def test_construction_base_constructor(self):
- arr = [Timestamp("2011-01-01"), pd.NaT, Timestamp("2011-01-03")]
- tm.assert_index_equal(Index(arr), DatetimeIndex(arr))
- tm.assert_index_equal(Index(np.array(arr)), DatetimeIndex(np.array(arr)))
- arr = [np.nan, pd.NaT, Timestamp("2011-01-03")]
- tm.assert_index_equal(Index(arr), DatetimeIndex(arr))
- tm.assert_index_equal(Index(np.array(arr)), DatetimeIndex(np.array(arr)))
- def test_construction_outofbounds(self):
- # GH 13663
- dates = [
- datetime(3000, 1, 1),
- datetime(4000, 1, 1),
- datetime(5000, 1, 1),
- datetime(6000, 1, 1),
- ]
- exp = Index(dates, dtype=object)
- # coerces to object
- tm.assert_index_equal(Index(dates), exp)
- msg = "^Out of bounds nanosecond timestamp: 3000-01-01 00:00:00, at position 0$"
- with pytest.raises(OutOfBoundsDatetime, match=msg):
- # can't create DatetimeIndex
- DatetimeIndex(dates)
- def test_construction_with_ndarray(self):
- # GH 5152
- dates = [datetime(2013, 10, 7), datetime(2013, 10, 8), datetime(2013, 10, 9)]
- data = DatetimeIndex(dates, freq=offsets.BDay()).values
- result = DatetimeIndex(data, freq=offsets.BDay())
- expected = DatetimeIndex(["2013-10-07", "2013-10-08", "2013-10-09"], freq="B")
- tm.assert_index_equal(result, expected)
- def test_integer_values_and_tz_interpreted_as_utc(self):
- # GH-24559
- val = np.datetime64("2000-01-01 00:00:00", "ns")
- values = np.array([val.view("i8")])
- result = DatetimeIndex(values).tz_localize("US/Central")
- expected = DatetimeIndex(["2000-01-01T00:00:00"], tz="US/Central")
- tm.assert_index_equal(result, expected)
- # but UTC is *not* deprecated.
- with tm.assert_produces_warning(None):
- result = DatetimeIndex(values, tz="UTC")
- expected = DatetimeIndex(["2000-01-01T00:00:00"], tz="US/Central")
- def test_constructor_coverage(self):
- rng = date_range("1/1/2000", periods=10.5)
- exp = date_range("1/1/2000", periods=10)
- tm.assert_index_equal(rng, exp)
- msg = "periods must be a number, got foo"
- with pytest.raises(TypeError, match=msg):
- date_range(start="1/1/2000", periods="foo", freq="D")
- msg = r"DatetimeIndex\(\.\.\.\) must be called with a collection"
- with pytest.raises(TypeError, match=msg):
- DatetimeIndex("1/1/2000")
- # generator expression
- gen = (datetime(2000, 1, 1) + timedelta(i) for i in range(10))
- result = DatetimeIndex(gen)
- expected = DatetimeIndex(
- [datetime(2000, 1, 1) + timedelta(i) for i in range(10)]
- )
- tm.assert_index_equal(result, expected)
- # NumPy string array
- strings = np.array(["2000-01-01", "2000-01-02", "2000-01-03"])
- result = DatetimeIndex(strings)
- expected = DatetimeIndex(strings.astype("O"))
- tm.assert_index_equal(result, expected)
- from_ints = DatetimeIndex(expected.asi8)
- tm.assert_index_equal(from_ints, expected)
- # string with NaT
- strings = np.array(["2000-01-01", "2000-01-02", "NaT"])
- result = DatetimeIndex(strings)
- expected = DatetimeIndex(strings.astype("O"))
- tm.assert_index_equal(result, expected)
- from_ints = DatetimeIndex(expected.asi8)
- tm.assert_index_equal(from_ints, expected)
- # non-conforming
- msg = (
- "Inferred frequency None from passed values does not conform "
- "to passed frequency D"
- )
- with pytest.raises(ValueError, match=msg):
- DatetimeIndex(["2000-01-01", "2000-01-02", "2000-01-04"], freq="D")
- msg = (
- "Of the four parameters: start, end, periods, and freq, exactly "
- "three must be specified"
- )
- with pytest.raises(ValueError, match=msg):
- date_range(start="2011-01-01", freq="b")
- with pytest.raises(ValueError, match=msg):
- date_range(end="2011-01-01", freq="B")
- with pytest.raises(ValueError, match=msg):
- date_range(periods=10, freq="D")
- @pytest.mark.parametrize("freq", ["AS", "W-SUN"])
- def test_constructor_datetime64_tzformat(self, freq):
- # see GH#6572: ISO 8601 format results in stdlib timezone object
- idx = date_range(
- "2013-01-01T00:00:00-05:00", "2016-01-01T23:59:59-05:00", freq=freq
- )
- expected = date_range(
- "2013-01-01T00:00:00",
- "2016-01-01T23:59:59",
- freq=freq,
- tz=timezone(timedelta(minutes=-300)),
- )
- tm.assert_index_equal(idx, expected)
- # Unable to use `US/Eastern` because of DST
- expected_i8 = date_range(
- "2013-01-01T00:00:00", "2016-01-01T23:59:59", freq=freq, tz="America/Lima"
- )
- tm.assert_numpy_array_equal(idx.asi8, expected_i8.asi8)
- idx = date_range(
- "2013-01-01T00:00:00+09:00", "2016-01-01T23:59:59+09:00", freq=freq
- )
- expected = date_range(
- "2013-01-01T00:00:00",
- "2016-01-01T23:59:59",
- freq=freq,
- tz=timezone(timedelta(minutes=540)),
- )
- tm.assert_index_equal(idx, expected)
- expected_i8 = date_range(
- "2013-01-01T00:00:00", "2016-01-01T23:59:59", freq=freq, tz="Asia/Tokyo"
- )
- tm.assert_numpy_array_equal(idx.asi8, expected_i8.asi8)
- # Non ISO 8601 format results in dateutil.tz.tzoffset
- idx = date_range("2013/1/1 0:00:00-5:00", "2016/1/1 23:59:59-5:00", freq=freq)
- expected = date_range(
- "2013-01-01T00:00:00",
- "2016-01-01T23:59:59",
- freq=freq,
- tz=timezone(timedelta(minutes=-300)),
- )
- tm.assert_index_equal(idx, expected)
- # Unable to use `US/Eastern` because of DST
- expected_i8 = date_range(
- "2013-01-01T00:00:00", "2016-01-01T23:59:59", freq=freq, tz="America/Lima"
- )
- tm.assert_numpy_array_equal(idx.asi8, expected_i8.asi8)
- idx = date_range("2013/1/1 0:00:00+9:00", "2016/1/1 23:59:59+09:00", freq=freq)
- expected = date_range(
- "2013-01-01T00:00:00",
- "2016-01-01T23:59:59",
- freq=freq,
- tz=timezone(timedelta(minutes=540)),
- )
- tm.assert_index_equal(idx, expected)
- expected_i8 = date_range(
- "2013-01-01T00:00:00", "2016-01-01T23:59:59", freq=freq, tz="Asia/Tokyo"
- )
- tm.assert_numpy_array_equal(idx.asi8, expected_i8.asi8)
- def test_constructor_dtype(self):
- # passing a dtype with a tz should localize
- idx = DatetimeIndex(
- ["2013-01-01", "2013-01-02"], dtype="datetime64[ns, US/Eastern]"
- )
- expected = DatetimeIndex(["2013-01-01", "2013-01-02"]).tz_localize("US/Eastern")
- tm.assert_index_equal(idx, expected)
- idx = DatetimeIndex(["2013-01-01", "2013-01-02"], tz="US/Eastern")
- tm.assert_index_equal(idx, expected)
- def test_constructor_dtype_tz_mismatch_raises(self):
- # if we already have a tz and its not the same, then raise
- idx = DatetimeIndex(
- ["2013-01-01", "2013-01-02"], dtype="datetime64[ns, US/Eastern]"
- )
- msg = (
- "cannot supply both a tz and a timezone-naive dtype "
- r"\(i\.e\. datetime64\[ns\]\)"
- )
- with pytest.raises(ValueError, match=msg):
- DatetimeIndex(idx, dtype="datetime64[ns]")
- # this is effectively trying to convert tz's
- msg = "data is already tz-aware US/Eastern, unable to set specified tz: CET"
- with pytest.raises(TypeError, match=msg):
- DatetimeIndex(idx, dtype="datetime64[ns, CET]")
- msg = "cannot supply both a tz and a dtype with a tz"
- with pytest.raises(ValueError, match=msg):
- DatetimeIndex(idx, tz="CET", dtype="datetime64[ns, US/Eastern]")
- result = DatetimeIndex(idx, dtype="datetime64[ns, US/Eastern]")
- tm.assert_index_equal(idx, result)
- @pytest.mark.parametrize("dtype", [object, np.int32, np.int64])
- def test_constructor_invalid_dtype_raises(self, dtype):
- # GH 23986
- msg = "Unexpected value for 'dtype'"
- with pytest.raises(ValueError, match=msg):
- DatetimeIndex([1, 2], dtype=dtype)
- def test_constructor_name(self):
- idx = date_range(start="2000-01-01", periods=1, freq="A", name="TEST")
- assert idx.name == "TEST"
- def test_000constructor_resolution(self):
- # 2252
- t1 = Timestamp((1352934390 * 1000000000) + 1000000 + 1000 + 1)
- idx = DatetimeIndex([t1])
- assert idx.nanosecond[0] == t1.nanosecond
- def test_disallow_setting_tz(self):
- # GH 3746
- dti = DatetimeIndex(["2010"], tz="UTC")
- msg = "Cannot directly set timezone"
- with pytest.raises(AttributeError, match=msg):
- dti.tz = pytz.timezone("US/Pacific")
- @pytest.mark.parametrize(
- "tz",
- [
- None,
- "America/Los_Angeles",
- pytz.timezone("America/Los_Angeles"),
- Timestamp("2000", tz="America/Los_Angeles").tz,
- ],
- )
- def test_constructor_start_end_with_tz(self, tz):
- # GH 18595
- start = Timestamp("2013-01-01 06:00:00", tz="America/Los_Angeles")
- end = Timestamp("2013-01-02 06:00:00", tz="America/Los_Angeles")
- result = date_range(freq="D", start=start, end=end, tz=tz)
- expected = DatetimeIndex(
- ["2013-01-01 06:00:00", "2013-01-02 06:00:00"],
- tz="America/Los_Angeles",
- freq="D",
- )
- tm.assert_index_equal(result, expected)
- # Especially assert that the timezone is consistent for pytz
- assert pytz.timezone("America/Los_Angeles") is result.tz
- @pytest.mark.parametrize("tz", ["US/Pacific", "US/Eastern", "Asia/Tokyo"])
- def test_constructor_with_non_normalized_pytz(self, tz):
- # GH 18595
- non_norm_tz = Timestamp("2010", tz=tz).tz
- result = DatetimeIndex(["2010"], tz=non_norm_tz)
- assert pytz.timezone(tz) is result.tz
- def test_constructor_timestamp_near_dst(self):
- # GH 20854
- ts = [
- Timestamp("2016-10-30 03:00:00+0300", tz="Europe/Helsinki"),
- Timestamp("2016-10-30 03:00:00+0200", tz="Europe/Helsinki"),
- ]
- result = DatetimeIndex(ts)
- expected = DatetimeIndex([ts[0].to_pydatetime(), ts[1].to_pydatetime()])
- tm.assert_index_equal(result, expected)
- @pytest.mark.parametrize("klass", [Index, DatetimeIndex])
- @pytest.mark.parametrize("box", [np.array, partial(np.array, dtype=object), list])
- @pytest.mark.parametrize(
- "tz, dtype",
- [("US/Pacific", "datetime64[ns, US/Pacific]"), (None, "datetime64[ns]")],
- )
- def test_constructor_with_int_tz(self, klass, box, tz, dtype):
- # GH 20997, 20964
- ts = Timestamp("2018-01-01", tz=tz).as_unit("ns")
- result = klass(box([ts._value]), dtype=dtype)
- expected = klass([ts])
- assert result == expected
- def test_construction_int_rountrip(self, tz_naive_fixture):
- # GH 12619, GH#24559
- tz = tz_naive_fixture
- result = 1293858000000000000
- expected = DatetimeIndex([result], tz=tz).asi8[0]
- assert result == expected
- def test_construction_from_replaced_timestamps_with_dst(self):
- # GH 18785
- index = date_range(
- Timestamp(2000, 1, 1),
- Timestamp(2005, 1, 1),
- freq="MS",
- tz="Australia/Melbourne",
- )
- test = pd.DataFrame({"data": range(len(index))}, index=index)
- test = test.resample("Y").mean()
- result = DatetimeIndex([x.replace(month=6, day=1) for x in test.index])
- expected = DatetimeIndex(
- [
- "2000-06-01 00:00:00",
- "2001-06-01 00:00:00",
- "2002-06-01 00:00:00",
- "2003-06-01 00:00:00",
- "2004-06-01 00:00:00",
- "2005-06-01 00:00:00",
- ],
- tz="Australia/Melbourne",
- )
- tm.assert_index_equal(result, expected)
- def test_construction_with_tz_and_tz_aware_dti(self):
- # GH 23579
- dti = date_range("2016-01-01", periods=3, tz="US/Central")
- msg = "data is already tz-aware US/Central, unable to set specified tz"
- with pytest.raises(TypeError, match=msg):
- DatetimeIndex(dti, tz="Asia/Tokyo")
- def test_construction_with_nat_and_tzlocal(self):
- tz = dateutil.tz.tzlocal()
- result = DatetimeIndex(["2018", "NaT"], tz=tz)
- expected = DatetimeIndex([Timestamp("2018", tz=tz), pd.NaT])
- tm.assert_index_equal(result, expected)
- def test_constructor_with_ambiguous_keyword_arg(self):
- # GH 35297
- expected = DatetimeIndex(
- ["2020-11-01 01:00:00", "2020-11-02 01:00:00"],
- dtype="datetime64[ns, America/New_York]",
- freq="D",
- ambiguous=False,
- )
- # ambiguous keyword in start
- timezone = "America/New_York"
- start = Timestamp(year=2020, month=11, day=1, hour=1).tz_localize(
- timezone, ambiguous=False
- )
- result = date_range(start=start, periods=2, ambiguous=False)
- tm.assert_index_equal(result, expected)
- # ambiguous keyword in end
- timezone = "America/New_York"
- end = Timestamp(year=2020, month=11, day=2, hour=1).tz_localize(
- timezone, ambiguous=False
- )
- result = date_range(end=end, periods=2, ambiguous=False)
- tm.assert_index_equal(result, expected)
- def test_constructor_with_nonexistent_keyword_arg(self, warsaw):
- # GH 35297
- timezone = warsaw
- # nonexistent keyword in start
- start = Timestamp("2015-03-29 02:30:00").tz_localize(
- timezone, nonexistent="shift_forward"
- )
- result = date_range(start=start, periods=2, freq="H")
- expected = DatetimeIndex(
- [
- Timestamp("2015-03-29 03:00:00+02:00", tz=timezone),
- Timestamp("2015-03-29 04:00:00+02:00", tz=timezone),
- ]
- )
- tm.assert_index_equal(result, expected)
- # nonexistent keyword in end
- end = Timestamp("2015-03-29 02:30:00").tz_localize(
- timezone, nonexistent="shift_forward"
- )
- result = date_range(end=end, periods=2, freq="H")
- expected = DatetimeIndex(
- [
- Timestamp("2015-03-29 01:00:00+01:00", tz=timezone),
- Timestamp("2015-03-29 03:00:00+02:00", tz=timezone),
- ]
- )
- tm.assert_index_equal(result, expected)
- def test_constructor_no_precision_raises(self):
- # GH-24753, GH-24739
- msg = "with no precision is not allowed"
- with pytest.raises(ValueError, match=msg):
- DatetimeIndex(["2000"], dtype="datetime64")
- msg = "The 'datetime64' dtype has no unit. Please pass in"
- with pytest.raises(ValueError, match=msg):
- Index(["2000"], dtype="datetime64")
- def test_constructor_wrong_precision_raises(self):
- dti = DatetimeIndex(["2000"], dtype="datetime64[us]")
- assert dti.dtype == "M8[us]"
- assert dti[0] == Timestamp(2000, 1, 1)
- def test_index_constructor_with_numpy_object_array_and_timestamp_tz_with_nan(self):
- # GH 27011
- result = Index(np.array([Timestamp("2019", tz="UTC"), np.nan], dtype=object))
- expected = DatetimeIndex([Timestamp("2019", tz="UTC"), pd.NaT])
- tm.assert_index_equal(result, expected)
- class TestTimeSeries:
- def test_dti_constructor_preserve_dti_freq(self):
- rng = date_range("1/1/2000", "1/2/2000", freq="5min")
- rng2 = DatetimeIndex(rng)
- assert rng.freq == rng2.freq
- def test_explicit_none_freq(self):
- # Explicitly passing freq=None is respected
- rng = date_range("1/1/2000", "1/2/2000", freq="5min")
- result = DatetimeIndex(rng, freq=None)
- assert result.freq is None
- result = DatetimeIndex(rng._data, freq=None)
- assert result.freq is None
- dta = DatetimeArray(rng, freq=None)
- assert dta.freq is None
- def test_dti_constructor_years_only(self, tz_naive_fixture):
- tz = tz_naive_fixture
- # GH 6961
- rng1 = date_range("2014", "2015", freq="M", tz=tz)
- expected1 = date_range("2014-01-31", "2014-12-31", freq="M", tz=tz)
- rng2 = date_range("2014", "2015", freq="MS", tz=tz)
- expected2 = date_range("2014-01-01", "2015-01-01", freq="MS", tz=tz)
- rng3 = date_range("2014", "2020", freq="A", tz=tz)
- expected3 = date_range("2014-12-31", "2019-12-31", freq="A", tz=tz)
- rng4 = date_range("2014", "2020", freq="AS", tz=tz)
- expected4 = date_range("2014-01-01", "2020-01-01", freq="AS", tz=tz)
- for rng, expected in [
- (rng1, expected1),
- (rng2, expected2),
- (rng3, expected3),
- (rng4, expected4),
- ]:
- tm.assert_index_equal(rng, expected)
- def test_dti_constructor_small_int(self, any_int_numpy_dtype):
- # see gh-13721
- exp = DatetimeIndex(
- [
- "1970-01-01 00:00:00.00000000",
- "1970-01-01 00:00:00.00000001",
- "1970-01-01 00:00:00.00000002",
- ]
- )
- arr = np.array([0, 10, 20], dtype=any_int_numpy_dtype)
- tm.assert_index_equal(DatetimeIndex(arr), exp)
- def test_ctor_str_intraday(self):
- rng = DatetimeIndex(["1-1-2000 00:00:01"])
- assert rng[0].second == 1
- def test_is_(self):
- dti = date_range(start="1/1/2005", end="12/1/2005", freq="M")
- assert dti.is_(dti)
- assert dti.is_(dti.view())
- assert not dti.is_(dti.copy())
- def test_index_cast_datetime64_other_units(self):
- arr = np.arange(0, 100, 10, dtype=np.int64).view("M8[D]")
- idx = Index(arr)
- assert (idx.values == astype_overflowsafe(arr, dtype=np.dtype("M8[ns]"))).all()
- def test_constructor_int64_nocopy(self):
- # GH#1624
- arr = np.arange(1000, dtype=np.int64)
- index = DatetimeIndex(arr)
- arr[50:100] = -1
- assert (index.asi8[50:100] == -1).all()
- arr = np.arange(1000, dtype=np.int64)
- index = DatetimeIndex(arr, copy=True)
- arr[50:100] = -1
- assert (index.asi8[50:100] != -1).all()
- @pytest.mark.parametrize(
- "freq", ["M", "Q", "A", "D", "B", "BH", "T", "S", "L", "U", "H", "N", "C"]
- )
- def test_from_freq_recreate_from_data(self, freq):
- org = date_range(start="2001/02/01 09:00", freq=freq, periods=1)
- idx = DatetimeIndex(org, freq=freq)
- tm.assert_index_equal(idx, org)
- org = date_range(
- start="2001/02/01 09:00", freq=freq, tz="US/Pacific", periods=1
- )
- idx = DatetimeIndex(org, freq=freq, tz="US/Pacific")
- tm.assert_index_equal(idx, org)
- def test_datetimeindex_constructor_misc(self):
- arr = ["1/1/2005", "1/2/2005", "Jn 3, 2005", "2005-01-04"]
- msg = r"(\(')?Unknown datetime string format(:', 'Jn 3, 2005'\))?"
- with pytest.raises(ValueError, match=msg):
- DatetimeIndex(arr)
- arr = ["1/1/2005", "1/2/2005", "1/3/2005", "2005-01-04"]
- idx1 = DatetimeIndex(arr)
- arr = [datetime(2005, 1, 1), "1/2/2005", "1/3/2005", "2005-01-04"]
- idx2 = DatetimeIndex(arr)
- arr = [Timestamp(datetime(2005, 1, 1)), "1/2/2005", "1/3/2005", "2005-01-04"]
- idx3 = DatetimeIndex(arr)
- arr = np.array(["1/1/2005", "1/2/2005", "1/3/2005", "2005-01-04"], dtype="O")
- idx4 = DatetimeIndex(arr)
- idx5 = DatetimeIndex(["12/05/2007", "25/01/2008"], dayfirst=True)
- idx6 = DatetimeIndex(
- ["2007/05/12", "2008/01/25"], dayfirst=False, yearfirst=True
- )
- tm.assert_index_equal(idx5, idx6)
- for other in [idx2, idx3, idx4]:
- assert (idx1.values == other.values).all()
- sdate = datetime(1999, 12, 25)
- edate = datetime(2000, 1, 1)
- idx = date_range(start=sdate, freq="1B", periods=20)
- assert len(idx) == 20
- assert idx[0] == sdate + 0 * offsets.BDay()
- assert idx.freq == "B"
- idx1 = date_range(start=sdate, end=edate, freq="W-SUN")
- idx2 = date_range(start=sdate, end=edate, freq=offsets.Week(weekday=6))
- assert len(idx1) == len(idx2)
- assert idx1.freq == idx2.freq
- idx1 = date_range(start=sdate, end=edate, freq="QS")
- idx2 = date_range(
- start=sdate, end=edate, freq=offsets.QuarterBegin(startingMonth=1)
- )
- assert len(idx1) == len(idx2)
- assert idx1.freq == idx2.freq
- idx1 = date_range(start=sdate, end=edate, freq="BQ")
- idx2 = date_range(
- start=sdate, end=edate, freq=offsets.BQuarterEnd(startingMonth=12)
- )
- assert len(idx1) == len(idx2)
- assert idx1.freq == idx2.freq
- def test_pass_datetimeindex_to_index(self):
- # Bugs in #1396
- rng = date_range("1/1/2000", "3/1/2000")
- idx = Index(rng, dtype=object)
- expected = Index(rng.to_pydatetime(), dtype=object)
- tm.assert_numpy_array_equal(idx.values, expected.values)
- def test_date_range_tuple_freq_raises(self):
- # GH#34703
- edate = datetime(2000, 1, 1)
- with pytest.raises(TypeError, match="pass as a string instead"):
- date_range(end=edate, freq=("D", 5), periods=20)
|