test_construction.py 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794
  1. from datetime import timedelta
  2. from functools import partial
  3. from operator import attrgetter
  4. import dateutil
  5. import numpy as np
  6. import pytest
  7. import pytz
  8. from pandas._libs.tslibs import OutOfBoundsDatetime, conversion
  9. import pandas as pd
  10. from pandas import (
  11. DatetimeIndex, Index, Timestamp, date_range, datetime, offsets,
  12. to_datetime)
  13. from pandas.core.arrays import DatetimeArray, period_array
  14. import pandas.util.testing as tm
  15. class TestDatetimeIndex(object):
  16. @pytest.mark.parametrize('dt_cls', [DatetimeIndex,
  17. DatetimeArray._from_sequence])
  18. def test_freq_validation_with_nat(self, dt_cls):
  19. # GH#11587 make sure we get a useful error message when generate_range
  20. # raises
  21. msg = ("Inferred frequency None from passed values does not conform "
  22. "to passed frequency D")
  23. with pytest.raises(ValueError, match=msg):
  24. dt_cls([pd.NaT, pd.Timestamp('2011-01-01')], freq='D')
  25. with pytest.raises(ValueError, match=msg):
  26. dt_cls([pd.NaT, pd.Timestamp('2011-01-01').value],
  27. freq='D')
  28. def test_categorical_preserves_tz(self):
  29. # GH#18664 retain tz when going DTI-->Categorical-->DTI
  30. # TODO: parametrize over DatetimeIndex/DatetimeArray
  31. # once CategoricalIndex(DTA) works
  32. dti = pd.DatetimeIndex(
  33. [pd.NaT, '2015-01-01', '1999-04-06 15:14:13', '2015-01-01'],
  34. tz='US/Eastern')
  35. ci = pd.CategoricalIndex(dti)
  36. carr = pd.Categorical(dti)
  37. cser = pd.Series(ci)
  38. for obj in [ci, carr, cser]:
  39. result = pd.DatetimeIndex(obj)
  40. tm.assert_index_equal(result, dti)
  41. def test_dti_with_period_data_raises(self):
  42. # GH#23675
  43. data = pd.PeriodIndex(['2016Q1', '2016Q2'], freq='Q')
  44. with pytest.raises(TypeError, match="PeriodDtype data is invalid"):
  45. DatetimeIndex(data)
  46. with pytest.raises(TypeError, match="PeriodDtype data is invalid"):
  47. to_datetime(data)
  48. with pytest.raises(TypeError, match="PeriodDtype data is invalid"):
  49. DatetimeIndex(period_array(data))
  50. with pytest.raises(TypeError, match="PeriodDtype data is invalid"):
  51. to_datetime(period_array(data))
  52. def test_dti_with_timedelta64_data_deprecation(self):
  53. # GH#23675
  54. data = np.array([0], dtype='m8[ns]')
  55. with tm.assert_produces_warning(FutureWarning):
  56. result = DatetimeIndex(data)
  57. assert result[0] == Timestamp('1970-01-01')
  58. with tm.assert_produces_warning(FutureWarning, check_stacklevel=False):
  59. result = to_datetime(data)
  60. assert result[0] == Timestamp('1970-01-01')
  61. with tm.assert_produces_warning(FutureWarning):
  62. result = DatetimeIndex(pd.TimedeltaIndex(data))
  63. assert result[0] == Timestamp('1970-01-01')
  64. with tm.assert_produces_warning(FutureWarning, check_stacklevel=False):
  65. result = to_datetime(pd.TimedeltaIndex(data))
  66. assert result[0] == Timestamp('1970-01-01')
  67. def test_construction_caching(self):
  68. df = pd.DataFrame({'dt': pd.date_range('20130101', periods=3),
  69. 'dttz': pd.date_range('20130101', periods=3,
  70. tz='US/Eastern'),
  71. 'dt_with_null': [pd.Timestamp('20130101'), pd.NaT,
  72. pd.Timestamp('20130103')],
  73. 'dtns': pd.date_range('20130101', periods=3,
  74. freq='ns')})
  75. assert df.dttz.dtype.tz.zone == 'US/Eastern'
  76. @pytest.mark.parametrize('kwargs', [
  77. {'tz': 'dtype.tz'},
  78. {'dtype': 'dtype'},
  79. {'dtype': 'dtype', 'tz': 'dtype.tz'}])
  80. def test_construction_with_alt(self, kwargs, tz_aware_fixture):
  81. tz = tz_aware_fixture
  82. i = pd.date_range('20130101', periods=5, freq='H', tz=tz)
  83. kwargs = {key: attrgetter(val)(i) for key, val in kwargs.items()}
  84. result = DatetimeIndex(i, **kwargs)
  85. tm.assert_index_equal(i, result)
  86. @pytest.mark.parametrize('kwargs', [
  87. {'tz': 'dtype.tz'},
  88. {'dtype': 'dtype'},
  89. {'dtype': 'dtype', 'tz': 'dtype.tz'}])
  90. def test_construction_with_alt_tz_localize(self, kwargs, tz_aware_fixture):
  91. tz = tz_aware_fixture
  92. i = pd.date_range('20130101', periods=5, freq='H', tz=tz)
  93. kwargs = {key: attrgetter(val)(i) for key, val in kwargs.items()}
  94. if str(tz) in ('UTC', 'tzutc()'):
  95. warn = None
  96. else:
  97. warn = FutureWarning
  98. with tm.assert_produces_warning(warn, check_stacklevel=False):
  99. result = DatetimeIndex(i.tz_localize(None).asi8, **kwargs)
  100. expected = DatetimeIndex(i, **kwargs)
  101. tm.assert_index_equal(result, expected)
  102. # localize into the provided tz
  103. i2 = DatetimeIndex(i.tz_localize(None).asi8, tz='UTC')
  104. expected = i.tz_localize(None).tz_localize('UTC')
  105. tm.assert_index_equal(i2, expected)
  106. # incompat tz/dtype
  107. pytest.raises(ValueError, lambda: DatetimeIndex(
  108. i.tz_localize(None).asi8, dtype=i.dtype, tz='US/Pacific'))
  109. def test_construction_index_with_mixed_timezones(self):
  110. # gh-11488: no tz results in DatetimeIndex
  111. result = Index([Timestamp('2011-01-01'),
  112. Timestamp('2011-01-02')], name='idx')
  113. exp = DatetimeIndex([Timestamp('2011-01-01'),
  114. Timestamp('2011-01-02')], name='idx')
  115. tm.assert_index_equal(result, exp, exact=True)
  116. assert isinstance(result, DatetimeIndex)
  117. assert result.tz is None
  118. # same tz results in DatetimeIndex
  119. result = Index([Timestamp('2011-01-01 10:00', tz='Asia/Tokyo'),
  120. Timestamp('2011-01-02 10:00', tz='Asia/Tokyo')],
  121. name='idx')
  122. exp = DatetimeIndex(
  123. [Timestamp('2011-01-01 10:00'), Timestamp('2011-01-02 10:00')
  124. ], tz='Asia/Tokyo', name='idx')
  125. tm.assert_index_equal(result, exp, exact=True)
  126. assert isinstance(result, DatetimeIndex)
  127. assert result.tz is not None
  128. assert result.tz == exp.tz
  129. # same tz results in DatetimeIndex (DST)
  130. result = Index([Timestamp('2011-01-01 10:00', tz='US/Eastern'),
  131. Timestamp('2011-08-01 10:00', tz='US/Eastern')],
  132. name='idx')
  133. exp = DatetimeIndex([Timestamp('2011-01-01 10:00'),
  134. Timestamp('2011-08-01 10:00')],
  135. tz='US/Eastern', name='idx')
  136. tm.assert_index_equal(result, exp, exact=True)
  137. assert isinstance(result, DatetimeIndex)
  138. assert result.tz is not None
  139. assert result.tz == exp.tz
  140. # Different tz results in Index(dtype=object)
  141. result = Index([Timestamp('2011-01-01 10:00'),
  142. Timestamp('2011-01-02 10:00', tz='US/Eastern')],
  143. name='idx')
  144. exp = Index([Timestamp('2011-01-01 10:00'),
  145. Timestamp('2011-01-02 10:00', tz='US/Eastern')],
  146. dtype='object', name='idx')
  147. tm.assert_index_equal(result, exp, exact=True)
  148. assert not isinstance(result, DatetimeIndex)
  149. result = Index([Timestamp('2011-01-01 10:00', tz='Asia/Tokyo'),
  150. Timestamp('2011-01-02 10:00', tz='US/Eastern')],
  151. name='idx')
  152. exp = Index([Timestamp('2011-01-01 10:00', tz='Asia/Tokyo'),
  153. Timestamp('2011-01-02 10:00', tz='US/Eastern')],
  154. dtype='object', name='idx')
  155. tm.assert_index_equal(result, exp, exact=True)
  156. assert not isinstance(result, DatetimeIndex)
  157. # length = 1
  158. result = Index([Timestamp('2011-01-01')], name='idx')
  159. exp = DatetimeIndex([Timestamp('2011-01-01')], name='idx')
  160. tm.assert_index_equal(result, exp, exact=True)
  161. assert isinstance(result, DatetimeIndex)
  162. assert result.tz is None
  163. # length = 1 with tz
  164. result = Index(
  165. [Timestamp('2011-01-01 10:00', tz='Asia/Tokyo')], name='idx')
  166. exp = DatetimeIndex([Timestamp('2011-01-01 10:00')], tz='Asia/Tokyo',
  167. name='idx')
  168. tm.assert_index_equal(result, exp, exact=True)
  169. assert isinstance(result, DatetimeIndex)
  170. assert result.tz is not None
  171. assert result.tz == exp.tz
  172. def test_construction_index_with_mixed_timezones_with_NaT(self):
  173. # see gh-11488
  174. result = Index([pd.NaT, Timestamp('2011-01-01'),
  175. pd.NaT, Timestamp('2011-01-02')], name='idx')
  176. exp = DatetimeIndex([pd.NaT, Timestamp('2011-01-01'),
  177. pd.NaT, Timestamp('2011-01-02')], name='idx')
  178. tm.assert_index_equal(result, exp, exact=True)
  179. assert isinstance(result, DatetimeIndex)
  180. assert result.tz is None
  181. # Same tz results in DatetimeIndex
  182. result = Index([pd.NaT, Timestamp('2011-01-01 10:00', tz='Asia/Tokyo'),
  183. pd.NaT, Timestamp('2011-01-02 10:00',
  184. tz='Asia/Tokyo')],
  185. name='idx')
  186. exp = DatetimeIndex([pd.NaT, Timestamp('2011-01-01 10:00'),
  187. pd.NaT, Timestamp('2011-01-02 10:00')],
  188. tz='Asia/Tokyo', name='idx')
  189. tm.assert_index_equal(result, exp, exact=True)
  190. assert isinstance(result, DatetimeIndex)
  191. assert result.tz is not None
  192. assert result.tz == exp.tz
  193. # same tz results in DatetimeIndex (DST)
  194. result = Index([Timestamp('2011-01-01 10:00', tz='US/Eastern'),
  195. pd.NaT,
  196. Timestamp('2011-08-01 10:00', tz='US/Eastern')],
  197. name='idx')
  198. exp = DatetimeIndex([Timestamp('2011-01-01 10:00'), pd.NaT,
  199. Timestamp('2011-08-01 10:00')],
  200. tz='US/Eastern', name='idx')
  201. tm.assert_index_equal(result, exp, exact=True)
  202. assert isinstance(result, DatetimeIndex)
  203. assert result.tz is not None
  204. assert result.tz == exp.tz
  205. # different tz results in Index(dtype=object)
  206. result = Index([pd.NaT, Timestamp('2011-01-01 10:00'),
  207. pd.NaT, Timestamp('2011-01-02 10:00',
  208. tz='US/Eastern')],
  209. name='idx')
  210. exp = Index([pd.NaT, Timestamp('2011-01-01 10:00'),
  211. pd.NaT, Timestamp('2011-01-02 10:00', tz='US/Eastern')],
  212. dtype='object', name='idx')
  213. tm.assert_index_equal(result, exp, exact=True)
  214. assert not isinstance(result, DatetimeIndex)
  215. result = Index([pd.NaT, Timestamp('2011-01-01 10:00', tz='Asia/Tokyo'),
  216. pd.NaT, Timestamp('2011-01-02 10:00',
  217. tz='US/Eastern')], name='idx')
  218. exp = Index([pd.NaT, Timestamp('2011-01-01 10:00', tz='Asia/Tokyo'),
  219. pd.NaT, Timestamp('2011-01-02 10:00', tz='US/Eastern')],
  220. dtype='object', name='idx')
  221. tm.assert_index_equal(result, exp, exact=True)
  222. assert not isinstance(result, DatetimeIndex)
  223. # all NaT
  224. result = Index([pd.NaT, pd.NaT], name='idx')
  225. exp = DatetimeIndex([pd.NaT, pd.NaT], name='idx')
  226. tm.assert_index_equal(result, exp, exact=True)
  227. assert isinstance(result, DatetimeIndex)
  228. assert result.tz is None
  229. # all NaT with tz
  230. result = Index([pd.NaT, pd.NaT], tz='Asia/Tokyo', name='idx')
  231. exp = DatetimeIndex([pd.NaT, pd.NaT], tz='Asia/Tokyo', name='idx')
  232. tm.assert_index_equal(result, exp, exact=True)
  233. assert isinstance(result, DatetimeIndex)
  234. assert result.tz is not None
  235. assert result.tz == exp.tz
  236. def test_construction_dti_with_mixed_timezones(self):
  237. # GH 11488 (not changed, added explicit tests)
  238. # no tz results in DatetimeIndex
  239. result = DatetimeIndex(
  240. [Timestamp('2011-01-01'), Timestamp('2011-01-02')], name='idx')
  241. exp = DatetimeIndex(
  242. [Timestamp('2011-01-01'), Timestamp('2011-01-02')], name='idx')
  243. tm.assert_index_equal(result, exp, exact=True)
  244. assert isinstance(result, DatetimeIndex)
  245. # same tz results in DatetimeIndex
  246. result = DatetimeIndex([Timestamp('2011-01-01 10:00', tz='Asia/Tokyo'),
  247. Timestamp('2011-01-02 10:00',
  248. tz='Asia/Tokyo')],
  249. name='idx')
  250. exp = DatetimeIndex([Timestamp('2011-01-01 10:00'),
  251. Timestamp('2011-01-02 10:00')],
  252. tz='Asia/Tokyo', name='idx')
  253. tm.assert_index_equal(result, exp, exact=True)
  254. assert isinstance(result, DatetimeIndex)
  255. # same tz results in DatetimeIndex (DST)
  256. result = DatetimeIndex([Timestamp('2011-01-01 10:00', tz='US/Eastern'),
  257. Timestamp('2011-08-01 10:00',
  258. tz='US/Eastern')],
  259. name='idx')
  260. exp = DatetimeIndex([Timestamp('2011-01-01 10:00'),
  261. Timestamp('2011-08-01 10:00')],
  262. tz='US/Eastern', name='idx')
  263. tm.assert_index_equal(result, exp, exact=True)
  264. assert isinstance(result, DatetimeIndex)
  265. # tz mismatch affecting to tz-aware raises TypeError/ValueError
  266. with pytest.raises(ValueError):
  267. DatetimeIndex([Timestamp('2011-01-01 10:00', tz='Asia/Tokyo'),
  268. Timestamp('2011-01-02 10:00', tz='US/Eastern')],
  269. name='idx')
  270. msg = 'cannot be converted to datetime64'
  271. with pytest.raises(ValueError, match=msg):
  272. DatetimeIndex([Timestamp('2011-01-01 10:00'),
  273. Timestamp('2011-01-02 10:00', tz='US/Eastern')],
  274. tz='Asia/Tokyo', name='idx')
  275. with pytest.raises(ValueError):
  276. DatetimeIndex([Timestamp('2011-01-01 10:00', tz='Asia/Tokyo'),
  277. Timestamp('2011-01-02 10:00', tz='US/Eastern')],
  278. tz='US/Eastern', name='idx')
  279. with pytest.raises(ValueError, match=msg):
  280. # passing tz should results in DatetimeIndex, then mismatch raises
  281. # TypeError
  282. Index([pd.NaT, Timestamp('2011-01-01 10:00'),
  283. pd.NaT, Timestamp('2011-01-02 10:00', tz='US/Eastern')],
  284. tz='Asia/Tokyo', name='idx')
  285. def test_construction_base_constructor(self):
  286. arr = [pd.Timestamp('2011-01-01'), pd.NaT, pd.Timestamp('2011-01-03')]
  287. tm.assert_index_equal(pd.Index(arr), pd.DatetimeIndex(arr))
  288. tm.assert_index_equal(pd.Index(np.array(arr)),
  289. pd.DatetimeIndex(np.array(arr)))
  290. arr = [np.nan, pd.NaT, pd.Timestamp('2011-01-03')]
  291. tm.assert_index_equal(pd.Index(arr), pd.DatetimeIndex(arr))
  292. tm.assert_index_equal(pd.Index(np.array(arr)),
  293. pd.DatetimeIndex(np.array(arr)))
  294. def test_construction_outofbounds(self):
  295. # GH 13663
  296. dates = [datetime(3000, 1, 1), datetime(4000, 1, 1),
  297. datetime(5000, 1, 1), datetime(6000, 1, 1)]
  298. exp = Index(dates, dtype=object)
  299. # coerces to object
  300. tm.assert_index_equal(Index(dates), exp)
  301. with pytest.raises(OutOfBoundsDatetime):
  302. # can't create DatetimeIndex
  303. DatetimeIndex(dates)
  304. def test_construction_with_ndarray(self):
  305. # GH 5152
  306. dates = [datetime(2013, 10, 7),
  307. datetime(2013, 10, 8),
  308. datetime(2013, 10, 9)]
  309. data = DatetimeIndex(dates, freq=pd.offsets.BDay()).values
  310. result = DatetimeIndex(data, freq=pd.offsets.BDay())
  311. expected = DatetimeIndex(['2013-10-07',
  312. '2013-10-08',
  313. '2013-10-09'],
  314. freq='B')
  315. tm.assert_index_equal(result, expected)
  316. def test_verify_integrity_deprecated(self):
  317. # GH#23919
  318. with tm.assert_produces_warning(FutureWarning):
  319. DatetimeIndex(['1/1/2000'], verify_integrity=False)
  320. def test_range_kwargs_deprecated(self):
  321. # GH#23919
  322. with tm.assert_produces_warning(FutureWarning):
  323. DatetimeIndex(start='1/1/2000', end='1/10/2000', freq='D')
  324. def test_integer_values_and_tz_deprecated(self):
  325. # GH-24559
  326. values = np.array([946684800000000000])
  327. with tm.assert_produces_warning(FutureWarning):
  328. result = DatetimeIndex(values, tz='US/Central')
  329. expected = pd.DatetimeIndex(['2000-01-01T00:00:00'], tz="US/Central")
  330. tm.assert_index_equal(result, expected)
  331. # but UTC is *not* deprecated.
  332. with tm.assert_produces_warning(None):
  333. result = DatetimeIndex(values, tz='UTC')
  334. expected = pd.DatetimeIndex(['2000-01-01T00:00:00'], tz="US/Central")
  335. def test_constructor_coverage(self):
  336. rng = date_range('1/1/2000', periods=10.5)
  337. exp = date_range('1/1/2000', periods=10)
  338. tm.assert_index_equal(rng, exp)
  339. msg = 'periods must be a number, got foo'
  340. with pytest.raises(TypeError, match=msg):
  341. date_range(start='1/1/2000', periods='foo', freq='D')
  342. with pytest.raises(ValueError):
  343. with tm.assert_produces_warning(FutureWarning):
  344. DatetimeIndex(start='1/1/2000', end='1/10/2000')
  345. with pytest.raises(TypeError):
  346. DatetimeIndex('1/1/2000')
  347. # generator expression
  348. gen = (datetime(2000, 1, 1) + timedelta(i) for i in range(10))
  349. result = DatetimeIndex(gen)
  350. expected = DatetimeIndex([datetime(2000, 1, 1) + timedelta(i)
  351. for i in range(10)])
  352. tm.assert_index_equal(result, expected)
  353. # NumPy string array
  354. strings = np.array(['2000-01-01', '2000-01-02', '2000-01-03'])
  355. result = DatetimeIndex(strings)
  356. expected = DatetimeIndex(strings.astype('O'))
  357. tm.assert_index_equal(result, expected)
  358. from_ints = DatetimeIndex(expected.asi8)
  359. tm.assert_index_equal(from_ints, expected)
  360. # string with NaT
  361. strings = np.array(['2000-01-01', '2000-01-02', 'NaT'])
  362. result = DatetimeIndex(strings)
  363. expected = DatetimeIndex(strings.astype('O'))
  364. tm.assert_index_equal(result, expected)
  365. from_ints = DatetimeIndex(expected.asi8)
  366. tm.assert_index_equal(from_ints, expected)
  367. # non-conforming
  368. pytest.raises(ValueError, DatetimeIndex,
  369. ['2000-01-01', '2000-01-02', '2000-01-04'], freq='D')
  370. pytest.raises(ValueError, date_range, start='2011-01-01',
  371. freq='b')
  372. pytest.raises(ValueError, date_range, end='2011-01-01',
  373. freq='B')
  374. pytest.raises(ValueError, date_range, periods=10, freq='D')
  375. @pytest.mark.parametrize('freq', ['AS', 'W-SUN'])
  376. def test_constructor_datetime64_tzformat(self, freq):
  377. # see GH#6572: ISO 8601 format results in pytz.FixedOffset
  378. idx = date_range('2013-01-01T00:00:00-05:00',
  379. '2016-01-01T23:59:59-05:00', freq=freq)
  380. expected = date_range('2013-01-01T00:00:00', '2016-01-01T23:59:59',
  381. freq=freq, tz=pytz.FixedOffset(-300))
  382. tm.assert_index_equal(idx, expected)
  383. # Unable to use `US/Eastern` because of DST
  384. expected_i8 = date_range('2013-01-01T00:00:00',
  385. '2016-01-01T23:59:59', freq=freq,
  386. tz='America/Lima')
  387. tm.assert_numpy_array_equal(idx.asi8, expected_i8.asi8)
  388. idx = date_range('2013-01-01T00:00:00+09:00',
  389. '2016-01-01T23:59:59+09:00', freq=freq)
  390. expected = date_range('2013-01-01T00:00:00', '2016-01-01T23:59:59',
  391. freq=freq, tz=pytz.FixedOffset(540))
  392. tm.assert_index_equal(idx, expected)
  393. expected_i8 = date_range('2013-01-01T00:00:00',
  394. '2016-01-01T23:59:59', freq=freq,
  395. tz='Asia/Tokyo')
  396. tm.assert_numpy_array_equal(idx.asi8, expected_i8.asi8)
  397. # Non ISO 8601 format results in dateutil.tz.tzoffset
  398. idx = date_range('2013/1/1 0:00:00-5:00', '2016/1/1 23:59:59-5:00',
  399. freq=freq)
  400. expected = date_range('2013-01-01T00:00:00', '2016-01-01T23:59:59',
  401. freq=freq, tz=pytz.FixedOffset(-300))
  402. tm.assert_index_equal(idx, expected)
  403. # Unable to use `US/Eastern` because of DST
  404. expected_i8 = date_range('2013-01-01T00:00:00',
  405. '2016-01-01T23:59:59', freq=freq,
  406. tz='America/Lima')
  407. tm.assert_numpy_array_equal(idx.asi8, expected_i8.asi8)
  408. idx = date_range('2013/1/1 0:00:00+9:00',
  409. '2016/1/1 23:59:59+09:00', freq=freq)
  410. expected = date_range('2013-01-01T00:00:00', '2016-01-01T23:59:59',
  411. freq=freq, tz=pytz.FixedOffset(540))
  412. tm.assert_index_equal(idx, expected)
  413. expected_i8 = date_range('2013-01-01T00:00:00',
  414. '2016-01-01T23:59:59', freq=freq,
  415. tz='Asia/Tokyo')
  416. tm.assert_numpy_array_equal(idx.asi8, expected_i8.asi8)
  417. def test_constructor_dtype(self):
  418. # passing a dtype with a tz should localize
  419. idx = DatetimeIndex(['2013-01-01', '2013-01-02'],
  420. dtype='datetime64[ns, US/Eastern]')
  421. expected = DatetimeIndex(['2013-01-01', '2013-01-02']
  422. ).tz_localize('US/Eastern')
  423. tm.assert_index_equal(idx, expected)
  424. idx = DatetimeIndex(['2013-01-01', '2013-01-02'],
  425. tz='US/Eastern')
  426. tm.assert_index_equal(idx, expected)
  427. # if we already have a tz and its not the same, then raise
  428. idx = DatetimeIndex(['2013-01-01', '2013-01-02'],
  429. dtype='datetime64[ns, US/Eastern]')
  430. pytest.raises(ValueError,
  431. lambda: DatetimeIndex(idx,
  432. dtype='datetime64[ns]'))
  433. # this is effectively trying to convert tz's
  434. pytest.raises(TypeError,
  435. lambda: DatetimeIndex(idx,
  436. dtype='datetime64[ns, CET]'))
  437. pytest.raises(ValueError,
  438. lambda: DatetimeIndex(
  439. idx, tz='CET',
  440. dtype='datetime64[ns, US/Eastern]'))
  441. result = DatetimeIndex(idx, dtype='datetime64[ns, US/Eastern]')
  442. tm.assert_index_equal(idx, result)
  443. def test_constructor_name(self):
  444. idx = date_range(start='2000-01-01', periods=1, freq='A',
  445. name='TEST')
  446. assert idx.name == 'TEST'
  447. def test_000constructor_resolution(self):
  448. # 2252
  449. t1 = Timestamp((1352934390 * 1000000000) + 1000000 + 1000 + 1)
  450. idx = DatetimeIndex([t1])
  451. assert idx.nanosecond[0] == t1.nanosecond
  452. def test_disallow_setting_tz(self):
  453. # GH 3746
  454. dti = DatetimeIndex(['2010'], tz='UTC')
  455. with pytest.raises(AttributeError):
  456. dti.tz = pytz.timezone('US/Pacific')
  457. @pytest.mark.parametrize('tz', [
  458. None, 'America/Los_Angeles', pytz.timezone('America/Los_Angeles'),
  459. Timestamp('2000', tz='America/Los_Angeles').tz])
  460. def test_constructor_start_end_with_tz(self, tz):
  461. # GH 18595
  462. start = Timestamp('2013-01-01 06:00:00', tz='America/Los_Angeles')
  463. end = Timestamp('2013-01-02 06:00:00', tz='America/Los_Angeles')
  464. result = date_range(freq='D', start=start, end=end, tz=tz)
  465. expected = DatetimeIndex(['2013-01-01 06:00:00',
  466. '2013-01-02 06:00:00'],
  467. tz='America/Los_Angeles')
  468. tm.assert_index_equal(result, expected)
  469. # Especially assert that the timezone is consistent for pytz
  470. assert pytz.timezone('America/Los_Angeles') is result.tz
  471. @pytest.mark.parametrize('tz', ['US/Pacific', 'US/Eastern', 'Asia/Tokyo'])
  472. def test_constructor_with_non_normalized_pytz(self, tz):
  473. # GH 18595
  474. non_norm_tz = Timestamp('2010', tz=tz).tz
  475. result = DatetimeIndex(['2010'], tz=non_norm_tz)
  476. assert pytz.timezone(tz) is result.tz
  477. def test_constructor_timestamp_near_dst(self):
  478. # GH 20854
  479. ts = [Timestamp('2016-10-30 03:00:00+0300', tz='Europe/Helsinki'),
  480. Timestamp('2016-10-30 03:00:00+0200', tz='Europe/Helsinki')]
  481. result = DatetimeIndex(ts)
  482. expected = DatetimeIndex([ts[0].to_pydatetime(),
  483. ts[1].to_pydatetime()])
  484. tm.assert_index_equal(result, expected)
  485. # TODO(GH-24559): Remove the xfail for the tz-aware case.
  486. @pytest.mark.parametrize('klass', [Index, DatetimeIndex])
  487. @pytest.mark.parametrize('box', [
  488. np.array, partial(np.array, dtype=object), list])
  489. @pytest.mark.parametrize('tz, dtype', [
  490. pytest.param('US/Pacific', 'datetime64[ns, US/Pacific]',
  491. marks=[pytest.mark.xfail(),
  492. pytest.mark.filterwarnings(
  493. "ignore:\\n Passing:FutureWarning")]),
  494. [None, 'datetime64[ns]'],
  495. ])
  496. def test_constructor_with_int_tz(self, klass, box, tz, dtype):
  497. # GH 20997, 20964
  498. ts = Timestamp('2018-01-01', tz=tz)
  499. result = klass(box([ts.value]), dtype=dtype)
  500. expected = klass([ts])
  501. assert result == expected
  502. # This is the desired future behavior
  503. @pytest.mark.xfail(reason="Future behavior", strict=False)
  504. @pytest.mark.filterwarnings("ignore:\\n Passing:FutureWarning")
  505. def test_construction_int_rountrip(self, tz_naive_fixture):
  506. # GH 12619
  507. # TODO(GH-24559): Remove xfail
  508. tz = tz_naive_fixture
  509. result = 1293858000000000000
  510. expected = DatetimeIndex([1293858000000000000], tz=tz).asi8[0]
  511. assert result == expected
  512. def test_construction_from_replaced_timestamps_with_dst(self):
  513. # GH 18785
  514. index = pd.date_range(pd.Timestamp(2000, 1, 1),
  515. pd.Timestamp(2005, 1, 1),
  516. freq='MS', tz='Australia/Melbourne')
  517. test = pd.DataFrame({'data': range(len(index))}, index=index)
  518. test = test.resample('Y').mean()
  519. result = pd.DatetimeIndex([x.replace(month=6, day=1)
  520. for x in test.index])
  521. expected = pd.DatetimeIndex(['2000-06-01 00:00:00',
  522. '2001-06-01 00:00:00',
  523. '2002-06-01 00:00:00',
  524. '2003-06-01 00:00:00',
  525. '2004-06-01 00:00:00',
  526. '2005-06-01 00:00:00'],
  527. tz='Australia/Melbourne')
  528. tm.assert_index_equal(result, expected)
  529. def test_construction_with_tz_and_tz_aware_dti(self):
  530. # GH 23579
  531. dti = date_range('2016-01-01', periods=3, tz='US/Central')
  532. with pytest.raises(TypeError):
  533. DatetimeIndex(dti, tz='Asia/Tokyo')
  534. def test_construction_with_nat_and_tzlocal(self):
  535. tz = dateutil.tz.tzlocal()
  536. result = DatetimeIndex(['2018', 'NaT'], tz=tz)
  537. expected = DatetimeIndex([Timestamp('2018', tz=tz), pd.NaT])
  538. tm.assert_index_equal(result, expected)
  539. def test_constructor_no_precision_warns(self):
  540. # GH-24753, GH-24739
  541. expected = pd.DatetimeIndex(['2000'], dtype='datetime64[ns]')
  542. # we set the stacklevel for DatetimeIndex
  543. with tm.assert_produces_warning(FutureWarning):
  544. result = pd.DatetimeIndex(['2000'], dtype='datetime64')
  545. tm.assert_index_equal(result, expected)
  546. with tm.assert_produces_warning(FutureWarning, check_stacklevel=False):
  547. result = pd.Index(['2000'], dtype='datetime64')
  548. tm.assert_index_equal(result, expected)
  549. def test_constructor_wrong_precision_raises(self):
  550. with pytest.raises(ValueError):
  551. pd.DatetimeIndex(['2000'], dtype='datetime64[us]')
  552. class TestTimeSeries(object):
  553. def test_dti_constructor_preserve_dti_freq(self):
  554. rng = date_range('1/1/2000', '1/2/2000', freq='5min')
  555. rng2 = DatetimeIndex(rng)
  556. assert rng.freq == rng2.freq
  557. def test_dti_constructor_years_only(self, tz_naive_fixture):
  558. tz = tz_naive_fixture
  559. # GH 6961
  560. rng1 = date_range('2014', '2015', freq='M', tz=tz)
  561. expected1 = date_range('2014-01-31', '2014-12-31', freq='M', tz=tz)
  562. rng2 = date_range('2014', '2015', freq='MS', tz=tz)
  563. expected2 = date_range('2014-01-01', '2015-01-01', freq='MS', tz=tz)
  564. rng3 = date_range('2014', '2020', freq='A', tz=tz)
  565. expected3 = date_range('2014-12-31', '2019-12-31', freq='A', tz=tz)
  566. rng4 = date_range('2014', '2020', freq='AS', tz=tz)
  567. expected4 = date_range('2014-01-01', '2020-01-01', freq='AS', tz=tz)
  568. for rng, expected in [(rng1, expected1), (rng2, expected2),
  569. (rng3, expected3), (rng4, expected4)]:
  570. tm.assert_index_equal(rng, expected)
  571. def test_dti_constructor_small_int(self, any_int_dtype):
  572. # see gh-13721
  573. exp = DatetimeIndex(['1970-01-01 00:00:00.00000000',
  574. '1970-01-01 00:00:00.00000001',
  575. '1970-01-01 00:00:00.00000002'])
  576. arr = np.array([0, 10, 20], dtype=any_int_dtype)
  577. tm.assert_index_equal(DatetimeIndex(arr), exp)
  578. def test_ctor_str_intraday(self):
  579. rng = DatetimeIndex(['1-1-2000 00:00:01'])
  580. assert rng[0].second == 1
  581. def test_is_(self):
  582. dti = date_range(start='1/1/2005', end='12/1/2005', freq='M')
  583. assert dti.is_(dti)
  584. assert dti.is_(dti.view())
  585. assert not dti.is_(dti.copy())
  586. def test_index_cast_datetime64_other_units(self):
  587. arr = np.arange(0, 100, 10, dtype=np.int64).view('M8[D]')
  588. idx = Index(arr)
  589. assert (idx.values == conversion.ensure_datetime64ns(arr)).all()
  590. def test_constructor_int64_nocopy(self):
  591. # GH#1624
  592. arr = np.arange(1000, dtype=np.int64)
  593. index = DatetimeIndex(arr)
  594. arr[50:100] = -1
  595. assert (index.asi8[50:100] == -1).all()
  596. arr = np.arange(1000, dtype=np.int64)
  597. index = DatetimeIndex(arr, copy=True)
  598. arr[50:100] = -1
  599. assert (index.asi8[50:100] != -1).all()
  600. @pytest.mark.parametrize('freq', ['M', 'Q', 'A', 'D', 'B', 'BH',
  601. 'T', 'S', 'L', 'U', 'H', 'N', 'C'])
  602. def test_from_freq_recreate_from_data(self, freq):
  603. org = date_range(start='2001/02/01 09:00', freq=freq, periods=1)
  604. idx = DatetimeIndex(org, freq=freq)
  605. tm.assert_index_equal(idx, org)
  606. org = date_range(start='2001/02/01 09:00', freq=freq,
  607. tz='US/Pacific', periods=1)
  608. idx = DatetimeIndex(org, freq=freq, tz='US/Pacific')
  609. tm.assert_index_equal(idx, org)
  610. def test_datetimeindex_constructor_misc(self):
  611. arr = ['1/1/2005', '1/2/2005', 'Jn 3, 2005', '2005-01-04']
  612. pytest.raises(Exception, DatetimeIndex, arr)
  613. arr = ['1/1/2005', '1/2/2005', '1/3/2005', '2005-01-04']
  614. idx1 = DatetimeIndex(arr)
  615. arr = [datetime(2005, 1, 1), '1/2/2005', '1/3/2005', '2005-01-04']
  616. idx2 = DatetimeIndex(arr)
  617. arr = [Timestamp(datetime(2005, 1, 1)), '1/2/2005', '1/3/2005',
  618. '2005-01-04']
  619. idx3 = DatetimeIndex(arr)
  620. arr = np.array(['1/1/2005', '1/2/2005', '1/3/2005',
  621. '2005-01-04'], dtype='O')
  622. idx4 = DatetimeIndex(arr)
  623. arr = to_datetime(['1/1/2005', '1/2/2005', '1/3/2005', '2005-01-04'])
  624. idx5 = DatetimeIndex(arr)
  625. arr = to_datetime(['1/1/2005', '1/2/2005', 'Jan 3, 2005', '2005-01-04'
  626. ])
  627. idx6 = DatetimeIndex(arr)
  628. idx7 = DatetimeIndex(['12/05/2007', '25/01/2008'], dayfirst=True)
  629. idx8 = DatetimeIndex(['2007/05/12', '2008/01/25'], dayfirst=False,
  630. yearfirst=True)
  631. tm.assert_index_equal(idx7, idx8)
  632. for other in [idx2, idx3, idx4, idx5, idx6]:
  633. assert (idx1.values == other.values).all()
  634. sdate = datetime(1999, 12, 25)
  635. edate = datetime(2000, 1, 1)
  636. idx = date_range(start=sdate, freq='1B', periods=20)
  637. assert len(idx) == 20
  638. assert idx[0] == sdate + 0 * offsets.BDay()
  639. assert idx.freq == 'B'
  640. idx = date_range(end=edate, freq=('D', 5), periods=20)
  641. assert len(idx) == 20
  642. assert idx[-1] == edate
  643. assert idx.freq == '5D'
  644. idx1 = date_range(start=sdate, end=edate, freq='W-SUN')
  645. idx2 = date_range(start=sdate, end=edate,
  646. freq=offsets.Week(weekday=6))
  647. assert len(idx1) == len(idx2)
  648. assert idx1.freq == idx2.freq
  649. idx1 = date_range(start=sdate, end=edate, freq='QS')
  650. idx2 = date_range(start=sdate, end=edate,
  651. freq=offsets.QuarterBegin(startingMonth=1))
  652. assert len(idx1) == len(idx2)
  653. assert idx1.freq == idx2.freq
  654. idx1 = date_range(start=sdate, end=edate, freq='BQ')
  655. idx2 = date_range(start=sdate, end=edate,
  656. freq=offsets.BQuarterEnd(startingMonth=12))
  657. assert len(idx1) == len(idx2)
  658. assert idx1.freq == idx2.freq