PageRenderTime 33ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/pandas/tseries/tests/test_tslib.py

http://github.com/wesm/pandas
Python | 1521 lines | 1371 code | 97 blank | 53 comment | 45 complexity | 8251afb93cd201813c2241ec5e70c891 MD5 | raw file
Possible License(s): BSD-3-Clause, Apache-2.0
  1. import nose
  2. from distutils.version import LooseVersion
  3. import numpy as np
  4. from pandas import tslib, lib
  5. import pandas._period as period
  6. import datetime
  7. import pandas as pd
  8. from pandas.core.api import (Timestamp, Index, Series, Timedelta, Period,
  9. to_datetime)
  10. from pandas.tslib import get_timezone
  11. from pandas._period import period_asfreq, period_ordinal
  12. from pandas.tseries.index import date_range, DatetimeIndex
  13. from pandas.tseries.frequencies import (
  14. get_freq,
  15. US_RESO, MS_RESO, S_RESO, H_RESO, D_RESO, T_RESO
  16. )
  17. import pandas.tseries.tools as tools
  18. import pandas.tseries.offsets as offsets
  19. import pandas.util.testing as tm
  20. import pandas.compat as compat
  21. from pandas.compat.numpy import (np_datetime64_compat,
  22. np_array_datetime64_compat)
  23. from pandas.util.testing import assert_series_equal, _skip_if_has_locale
  24. class TestTsUtil(tm.TestCase):
  25. def test_try_parse_dates(self):
  26. from dateutil.parser import parse
  27. arr = np.array(['5/1/2000', '6/1/2000', '7/1/2000'], dtype=object)
  28. result = lib.try_parse_dates(arr, dayfirst=True)
  29. expected = [parse(d, dayfirst=True) for d in arr]
  30. self.assertTrue(np.array_equal(result, expected))
  31. def test_min_valid(self):
  32. # Ensure that Timestamp.min is a valid Timestamp
  33. Timestamp(Timestamp.min)
  34. def test_max_valid(self):
  35. # Ensure that Timestamp.max is a valid Timestamp
  36. Timestamp(Timestamp.max)
  37. def test_to_datetime_bijective(self):
  38. # Ensure that converting to datetime and back only loses precision
  39. # by going from nanoseconds to microseconds.
  40. self.assertEqual(
  41. Timestamp(Timestamp.max.to_pydatetime()).value / 1000,
  42. Timestamp.max.value / 1000)
  43. self.assertEqual(
  44. Timestamp(Timestamp.min.to_pydatetime()).value / 1000,
  45. Timestamp.min.value / 1000)
  46. class TestTimestamp(tm.TestCase):
  47. def test_constructor(self):
  48. base_str = '2014-07-01 09:00'
  49. base_dt = datetime.datetime(2014, 7, 1, 9)
  50. base_expected = 1404205200000000000
  51. # confirm base representation is correct
  52. import calendar
  53. self.assertEqual(calendar.timegm(base_dt.timetuple()) * 1000000000,
  54. base_expected)
  55. tests = [(base_str, base_dt, base_expected),
  56. ('2014-07-01 10:00', datetime.datetime(2014, 7, 1, 10),
  57. base_expected + 3600 * 1000000000),
  58. ('2014-07-01 09:00:00.000008000',
  59. datetime.datetime(2014, 7, 1, 9, 0, 0, 8),
  60. base_expected + 8000),
  61. ('2014-07-01 09:00:00.000000005',
  62. Timestamp('2014-07-01 09:00:00.000000005'),
  63. base_expected + 5)]
  64. tm._skip_if_no_pytz()
  65. tm._skip_if_no_dateutil()
  66. import pytz
  67. import dateutil
  68. timezones = [(None, 0), ('UTC', 0), (pytz.utc, 0), ('Asia/Tokyo', 9),
  69. ('US/Eastern', -4), ('dateutil/US/Pacific', -7),
  70. (pytz.FixedOffset(-180), -3),
  71. (dateutil.tz.tzoffset(None, 18000), 5)]
  72. for date_str, date, expected in tests:
  73. for result in [Timestamp(date_str), Timestamp(date)]:
  74. # only with timestring
  75. self.assertEqual(result.value, expected)
  76. self.assertEqual(tslib.pydt_to_i8(result), expected)
  77. # re-creation shouldn't affect to internal value
  78. result = Timestamp(result)
  79. self.assertEqual(result.value, expected)
  80. self.assertEqual(tslib.pydt_to_i8(result), expected)
  81. # with timezone
  82. for tz, offset in timezones:
  83. for result in [Timestamp(date_str, tz=tz), Timestamp(date,
  84. tz=tz)]:
  85. expected_tz = expected - offset * 3600 * 1000000000
  86. self.assertEqual(result.value, expected_tz)
  87. self.assertEqual(tslib.pydt_to_i8(result), expected_tz)
  88. # should preserve tz
  89. result = Timestamp(result)
  90. self.assertEqual(result.value, expected_tz)
  91. self.assertEqual(tslib.pydt_to_i8(result), expected_tz)
  92. # should convert to UTC
  93. result = Timestamp(result, tz='UTC')
  94. expected_utc = expected - offset * 3600 * 1000000000
  95. self.assertEqual(result.value, expected_utc)
  96. self.assertEqual(tslib.pydt_to_i8(result), expected_utc)
  97. def test_constructor_with_stringoffset(self):
  98. # GH 7833
  99. base_str = '2014-07-01 11:00:00+02:00'
  100. base_dt = datetime.datetime(2014, 7, 1, 9)
  101. base_expected = 1404205200000000000
  102. # confirm base representation is correct
  103. import calendar
  104. self.assertEqual(calendar.timegm(base_dt.timetuple()) * 1000000000,
  105. base_expected)
  106. tests = [(base_str, base_expected),
  107. ('2014-07-01 12:00:00+02:00',
  108. base_expected + 3600 * 1000000000),
  109. ('2014-07-01 11:00:00.000008000+02:00', base_expected + 8000),
  110. ('2014-07-01 11:00:00.000000005+02:00', base_expected + 5)]
  111. tm._skip_if_no_pytz()
  112. tm._skip_if_no_dateutil()
  113. import pytz
  114. import dateutil
  115. timezones = [(None, 0), ('UTC', 0), (pytz.utc, 0), ('Asia/Tokyo', 9),
  116. ('US/Eastern', -4), ('dateutil/US/Pacific', -7),
  117. (pytz.FixedOffset(-180), -3),
  118. (dateutil.tz.tzoffset(None, 18000), 5)]
  119. for date_str, expected in tests:
  120. for result in [Timestamp(date_str)]:
  121. # only with timestring
  122. self.assertEqual(result.value, expected)
  123. self.assertEqual(tslib.pydt_to_i8(result), expected)
  124. # re-creation shouldn't affect to internal value
  125. result = Timestamp(result)
  126. self.assertEqual(result.value, expected)
  127. self.assertEqual(tslib.pydt_to_i8(result), expected)
  128. # with timezone
  129. for tz, offset in timezones:
  130. result = Timestamp(date_str, tz=tz)
  131. expected_tz = expected
  132. self.assertEqual(result.value, expected_tz)
  133. self.assertEqual(tslib.pydt_to_i8(result), expected_tz)
  134. # should preserve tz
  135. result = Timestamp(result)
  136. self.assertEqual(result.value, expected_tz)
  137. self.assertEqual(tslib.pydt_to_i8(result), expected_tz)
  138. # should convert to UTC
  139. result = Timestamp(result, tz='UTC')
  140. expected_utc = expected
  141. self.assertEqual(result.value, expected_utc)
  142. self.assertEqual(tslib.pydt_to_i8(result), expected_utc)
  143. # This should be 2013-11-01 05:00 in UTC
  144. # converted to Chicago tz
  145. result = Timestamp('2013-11-01 00:00:00-0500', tz='America/Chicago')
  146. self.assertEqual(result.value, Timestamp('2013-11-01 05:00').value)
  147. expected = "Timestamp('2013-11-01 00:00:00-0500', tz='America/Chicago')" # noqa
  148. self.assertEqual(repr(result), expected)
  149. self.assertEqual(result, eval(repr(result)))
  150. # This should be 2013-11-01 05:00 in UTC
  151. # converted to Tokyo tz (+09:00)
  152. result = Timestamp('2013-11-01 00:00:00-0500', tz='Asia/Tokyo')
  153. self.assertEqual(result.value, Timestamp('2013-11-01 05:00').value)
  154. expected = "Timestamp('2013-11-01 14:00:00+0900', tz='Asia/Tokyo')"
  155. self.assertEqual(repr(result), expected)
  156. self.assertEqual(result, eval(repr(result)))
  157. # GH11708
  158. # This should be 2015-11-18 10:00 in UTC
  159. # converted to Asia/Katmandu
  160. result = Timestamp("2015-11-18 15:45:00+05:45", tz="Asia/Katmandu")
  161. self.assertEqual(result.value, Timestamp("2015-11-18 10:00").value)
  162. expected = "Timestamp('2015-11-18 15:45:00+0545', tz='Asia/Katmandu')"
  163. self.assertEqual(repr(result), expected)
  164. self.assertEqual(result, eval(repr(result)))
  165. # This should be 2015-11-18 10:00 in UTC
  166. # converted to Asia/Kolkata
  167. result = Timestamp("2015-11-18 15:30:00+05:30", tz="Asia/Kolkata")
  168. self.assertEqual(result.value, Timestamp("2015-11-18 10:00").value)
  169. expected = "Timestamp('2015-11-18 15:30:00+0530', tz='Asia/Kolkata')"
  170. self.assertEqual(repr(result), expected)
  171. self.assertEqual(result, eval(repr(result)))
  172. def test_constructor_invalid(self):
  173. with tm.assertRaisesRegexp(TypeError, 'Cannot convert input'):
  174. Timestamp(slice(2))
  175. with tm.assertRaisesRegexp(ValueError, 'Cannot convert Period'):
  176. Timestamp(Period('1000-01-01'))
  177. def test_constructor_positional(self):
  178. # GH 10758
  179. with tm.assertRaises(TypeError):
  180. Timestamp(2000, 1)
  181. with tm.assertRaises(ValueError):
  182. Timestamp(2000, 0, 1)
  183. with tm.assertRaises(ValueError):
  184. Timestamp(2000, 13, 1)
  185. with tm.assertRaises(ValueError):
  186. Timestamp(2000, 1, 0)
  187. with tm.assertRaises(ValueError):
  188. Timestamp(2000, 1, 32)
  189. # GH 11630
  190. self.assertEqual(
  191. repr(Timestamp(2015, 11, 12)),
  192. repr(Timestamp('20151112')))
  193. self.assertEqual(
  194. repr(Timestamp(2015, 11, 12, 1, 2, 3, 999999)),
  195. repr(Timestamp('2015-11-12 01:02:03.999999')))
  196. self.assertIs(Timestamp(None), pd.NaT)
  197. def test_constructor_keyword(self):
  198. # GH 10758
  199. with tm.assertRaises(TypeError):
  200. Timestamp(year=2000, month=1)
  201. with tm.assertRaises(ValueError):
  202. Timestamp(year=2000, month=0, day=1)
  203. with tm.assertRaises(ValueError):
  204. Timestamp(year=2000, month=13, day=1)
  205. with tm.assertRaises(ValueError):
  206. Timestamp(year=2000, month=1, day=0)
  207. with tm.assertRaises(ValueError):
  208. Timestamp(year=2000, month=1, day=32)
  209. self.assertEqual(
  210. repr(Timestamp(year=2015, month=11, day=12)),
  211. repr(Timestamp('20151112')))
  212. self.assertEqual(
  213. repr(Timestamp(year=2015, month=11, day=12,
  214. hour=1, minute=2, second=3, microsecond=999999)),
  215. repr(Timestamp('2015-11-12 01:02:03.999999')))
  216. def test_constructor_fromordinal(self):
  217. base = datetime.datetime(2000, 1, 1)
  218. ts = Timestamp.fromordinal(base.toordinal(), freq='D')
  219. self.assertEqual(base, ts)
  220. self.assertEqual(ts.freq, 'D')
  221. self.assertEqual(base.toordinal(), ts.toordinal())
  222. ts = Timestamp.fromordinal(base.toordinal(), tz='US/Eastern')
  223. self.assertEqual(pd.Timestamp('2000-01-01', tz='US/Eastern'), ts)
  224. self.assertEqual(base.toordinal(), ts.toordinal())
  225. def test_constructor_offset_depr(self):
  226. # GH 12160
  227. with tm.assert_produces_warning(FutureWarning,
  228. check_stacklevel=False):
  229. ts = Timestamp('2011-01-01', offset='D')
  230. self.assertEqual(ts.freq, 'D')
  231. with tm.assert_produces_warning(FutureWarning,
  232. check_stacklevel=False):
  233. self.assertEqual(ts.offset, 'D')
  234. msg = "Can only specify freq or offset, not both"
  235. with tm.assertRaisesRegexp(TypeError, msg):
  236. Timestamp('2011-01-01', offset='D', freq='D')
  237. def test_constructor_offset_depr_fromordinal(self):
  238. # GH 12160
  239. base = datetime.datetime(2000, 1, 1)
  240. with tm.assert_produces_warning(FutureWarning,
  241. check_stacklevel=False):
  242. ts = Timestamp.fromordinal(base.toordinal(), offset='D')
  243. self.assertEqual(pd.Timestamp('2000-01-01'), ts)
  244. self.assertEqual(ts.freq, 'D')
  245. self.assertEqual(base.toordinal(), ts.toordinal())
  246. msg = "Can only specify freq or offset, not both"
  247. with tm.assertRaisesRegexp(TypeError, msg):
  248. Timestamp.fromordinal(base.toordinal(), offset='D', freq='D')
  249. def test_conversion(self):
  250. # GH 9255
  251. ts = Timestamp('2000-01-01')
  252. result = ts.to_pydatetime()
  253. expected = datetime.datetime(2000, 1, 1)
  254. self.assertEqual(result, expected)
  255. self.assertEqual(type(result), type(expected))
  256. result = ts.to_datetime64()
  257. expected = np.datetime64(ts.value, 'ns')
  258. self.assertEqual(result, expected)
  259. self.assertEqual(type(result), type(expected))
  260. self.assertEqual(result.dtype, expected.dtype)
  261. def test_repr(self):
  262. tm._skip_if_no_pytz()
  263. tm._skip_if_no_dateutil()
  264. dates = ['2014-03-07', '2014-01-01 09:00',
  265. '2014-01-01 00:00:00.000000001']
  266. # dateutil zone change (only matters for repr)
  267. import dateutil
  268. if dateutil.__version__ >= LooseVersion(
  269. '2.3') and dateutil.__version__ <= LooseVersion('2.4.0'):
  270. timezones = ['UTC', 'Asia/Tokyo', 'US/Eastern',
  271. 'dateutil/US/Pacific']
  272. else:
  273. timezones = ['UTC', 'Asia/Tokyo', 'US/Eastern',
  274. 'dateutil/America/Los_Angeles']
  275. freqs = ['D', 'M', 'S', 'N']
  276. for date in dates:
  277. for tz in timezones:
  278. for freq in freqs:
  279. # avoid to match with timezone name
  280. freq_repr = "'{0}'".format(freq)
  281. if tz.startswith('dateutil'):
  282. tz_repr = tz.replace('dateutil', '')
  283. else:
  284. tz_repr = tz
  285. date_only = Timestamp(date)
  286. self.assertIn(date, repr(date_only))
  287. self.assertNotIn(tz_repr, repr(date_only))
  288. self.assertNotIn(freq_repr, repr(date_only))
  289. self.assertEqual(date_only, eval(repr(date_only)))
  290. date_tz = Timestamp(date, tz=tz)
  291. self.assertIn(date, repr(date_tz))
  292. self.assertIn(tz_repr, repr(date_tz))
  293. self.assertNotIn(freq_repr, repr(date_tz))
  294. self.assertEqual(date_tz, eval(repr(date_tz)))
  295. date_freq = Timestamp(date, freq=freq)
  296. self.assertIn(date, repr(date_freq))
  297. self.assertNotIn(tz_repr, repr(date_freq))
  298. self.assertIn(freq_repr, repr(date_freq))
  299. self.assertEqual(date_freq, eval(repr(date_freq)))
  300. date_tz_freq = Timestamp(date, tz=tz, freq=freq)
  301. self.assertIn(date, repr(date_tz_freq))
  302. self.assertIn(tz_repr, repr(date_tz_freq))
  303. self.assertIn(freq_repr, repr(date_tz_freq))
  304. self.assertEqual(date_tz_freq, eval(repr(date_tz_freq)))
  305. # this can cause the tz field to be populated, but it's redundant to
  306. # information in the datestring
  307. tm._skip_if_no_pytz()
  308. import pytz # noqa
  309. date_with_utc_offset = Timestamp('2014-03-13 00:00:00-0400', tz=None)
  310. self.assertIn('2014-03-13 00:00:00-0400', repr(date_with_utc_offset))
  311. self.assertNotIn('tzoffset', repr(date_with_utc_offset))
  312. self.assertIn('pytz.FixedOffset(-240)', repr(date_with_utc_offset))
  313. expr = repr(date_with_utc_offset).replace("'pytz.FixedOffset(-240)'",
  314. 'pytz.FixedOffset(-240)')
  315. self.assertEqual(date_with_utc_offset, eval(expr))
  316. def test_bounds_with_different_units(self):
  317. out_of_bounds_dates = ('1677-09-21', '2262-04-12', )
  318. time_units = ('D', 'h', 'm', 's', 'ms', 'us')
  319. for date_string in out_of_bounds_dates:
  320. for unit in time_units:
  321. self.assertRaises(ValueError, Timestamp, np.datetime64(
  322. date_string, dtype='M8[%s]' % unit))
  323. in_bounds_dates = ('1677-09-23', '2262-04-11', )
  324. for date_string in in_bounds_dates:
  325. for unit in time_units:
  326. Timestamp(np.datetime64(date_string, dtype='M8[%s]' % unit))
  327. def test_tz(self):
  328. t = '2014-02-01 09:00'
  329. ts = Timestamp(t)
  330. local = ts.tz_localize('Asia/Tokyo')
  331. self.assertEqual(local.hour, 9)
  332. self.assertEqual(local, Timestamp(t, tz='Asia/Tokyo'))
  333. conv = local.tz_convert('US/Eastern')
  334. self.assertEqual(conv, Timestamp('2014-01-31 19:00', tz='US/Eastern'))
  335. self.assertEqual(conv.hour, 19)
  336. # preserves nanosecond
  337. ts = Timestamp(t) + offsets.Nano(5)
  338. local = ts.tz_localize('Asia/Tokyo')
  339. self.assertEqual(local.hour, 9)
  340. self.assertEqual(local.nanosecond, 5)
  341. conv = local.tz_convert('US/Eastern')
  342. self.assertEqual(conv.nanosecond, 5)
  343. self.assertEqual(conv.hour, 19)
  344. def test_tz_localize_ambiguous(self):
  345. ts = Timestamp('2014-11-02 01:00')
  346. ts_dst = ts.tz_localize('US/Eastern', ambiguous=True)
  347. ts_no_dst = ts.tz_localize('US/Eastern', ambiguous=False)
  348. rng = date_range('2014-11-02', periods=3, freq='H', tz='US/Eastern')
  349. self.assertEqual(rng[1], ts_dst)
  350. self.assertEqual(rng[2], ts_no_dst)
  351. self.assertRaises(ValueError, ts.tz_localize, 'US/Eastern',
  352. ambiguous='infer')
  353. # GH 8025
  354. with tm.assertRaisesRegexp(TypeError,
  355. 'Cannot localize tz-aware Timestamp, use '
  356. 'tz_convert for conversions'):
  357. Timestamp('2011-01-01', tz='US/Eastern').tz_localize('Asia/Tokyo')
  358. with tm.assertRaisesRegexp(TypeError,
  359. 'Cannot convert tz-naive Timestamp, use '
  360. 'tz_localize to localize'):
  361. Timestamp('2011-01-01').tz_convert('Asia/Tokyo')
  362. def test_tz_localize_nonexistent(self):
  363. # See issue 13057
  364. from pytz.exceptions import NonExistentTimeError
  365. times = ['2015-03-08 02:00', '2015-03-08 02:30',
  366. '2015-03-29 02:00', '2015-03-29 02:30']
  367. timezones = ['US/Eastern', 'US/Pacific',
  368. 'Europe/Paris', 'Europe/Belgrade']
  369. for t, tz in zip(times, timezones):
  370. ts = Timestamp(t)
  371. self.assertRaises(NonExistentTimeError, ts.tz_localize,
  372. tz)
  373. self.assertRaises(NonExistentTimeError, ts.tz_localize,
  374. tz, errors='raise')
  375. self.assertIs(ts.tz_localize(tz, errors='coerce'),
  376. pd.NaT)
  377. def test_tz_localize_errors_ambiguous(self):
  378. # See issue 13057
  379. from pytz.exceptions import AmbiguousTimeError
  380. ts = pd.Timestamp('2015-11-1 01:00')
  381. self.assertRaises(AmbiguousTimeError,
  382. ts.tz_localize, 'US/Pacific', errors='coerce')
  383. def test_tz_localize_roundtrip(self):
  384. for tz in ['UTC', 'Asia/Tokyo', 'US/Eastern', 'dateutil/US/Pacific']:
  385. for t in ['2014-02-01 09:00', '2014-07-08 09:00',
  386. '2014-11-01 17:00', '2014-11-05 00:00']:
  387. ts = Timestamp(t)
  388. localized = ts.tz_localize(tz)
  389. self.assertEqual(localized, Timestamp(t, tz=tz))
  390. with tm.assertRaises(TypeError):
  391. localized.tz_localize(tz)
  392. reset = localized.tz_localize(None)
  393. self.assertEqual(reset, ts)
  394. self.assertTrue(reset.tzinfo is None)
  395. def test_tz_convert_roundtrip(self):
  396. for tz in ['UTC', 'Asia/Tokyo', 'US/Eastern', 'dateutil/US/Pacific']:
  397. for t in ['2014-02-01 09:00', '2014-07-08 09:00',
  398. '2014-11-01 17:00', '2014-11-05 00:00']:
  399. ts = Timestamp(t, tz='UTC')
  400. converted = ts.tz_convert(tz)
  401. reset = converted.tz_convert(None)
  402. self.assertEqual(reset, Timestamp(t))
  403. self.assertTrue(reset.tzinfo is None)
  404. self.assertEqual(reset,
  405. converted.tz_convert('UTC').tz_localize(None))
  406. def test_barely_oob_dts(self):
  407. one_us = np.timedelta64(1).astype('timedelta64[us]')
  408. # By definition we can't go out of bounds in [ns], so we
  409. # convert the datetime64s to [us] so we can go out of bounds
  410. min_ts_us = np.datetime64(Timestamp.min).astype('M8[us]')
  411. max_ts_us = np.datetime64(Timestamp.max).astype('M8[us]')
  412. # No error for the min/max datetimes
  413. Timestamp(min_ts_us)
  414. Timestamp(max_ts_us)
  415. # One us less than the minimum is an error
  416. self.assertRaises(ValueError, Timestamp, min_ts_us - one_us)
  417. # One us more than the maximum is an error
  418. self.assertRaises(ValueError, Timestamp, max_ts_us + one_us)
  419. def test_utc_z_designator(self):
  420. self.assertEqual(get_timezone(
  421. Timestamp('2014-11-02 01:00Z').tzinfo), 'UTC')
  422. def test_now(self):
  423. # #9000
  424. ts_from_string = Timestamp('now')
  425. ts_from_method = Timestamp.now()
  426. ts_datetime = datetime.datetime.now()
  427. ts_from_string_tz = Timestamp('now', tz='US/Eastern')
  428. ts_from_method_tz = Timestamp.now(tz='US/Eastern')
  429. # Check that the delta between the times is less than 1s (arbitrarily
  430. # small)
  431. delta = Timedelta(seconds=1)
  432. self.assertTrue(abs(ts_from_method - ts_from_string) < delta)
  433. self.assertTrue(abs(ts_datetime - ts_from_method) < delta)
  434. self.assertTrue(abs(ts_from_method_tz - ts_from_string_tz) < delta)
  435. self.assertTrue(abs(ts_from_string_tz.tz_localize(None) -
  436. ts_from_method_tz.tz_localize(None)) < delta)
  437. def test_today(self):
  438. ts_from_string = Timestamp('today')
  439. ts_from_method = Timestamp.today()
  440. ts_datetime = datetime.datetime.today()
  441. ts_from_string_tz = Timestamp('today', tz='US/Eastern')
  442. ts_from_method_tz = Timestamp.today(tz='US/Eastern')
  443. # Check that the delta between the times is less than 1s (arbitrarily
  444. # small)
  445. delta = Timedelta(seconds=1)
  446. self.assertTrue(abs(ts_from_method - ts_from_string) < delta)
  447. self.assertTrue(abs(ts_datetime - ts_from_method) < delta)
  448. self.assertTrue(abs(ts_from_method_tz - ts_from_string_tz) < delta)
  449. self.assertTrue(abs(ts_from_string_tz.tz_localize(None) -
  450. ts_from_method_tz.tz_localize(None)) < delta)
  451. def test_asm8(self):
  452. np.random.seed(7960929)
  453. ns = [Timestamp.min.value, Timestamp.max.value, 1000, ]
  454. for n in ns:
  455. self.assertEqual(Timestamp(n).asm8.view('i8'),
  456. np.datetime64(n, 'ns').view('i8'), n)
  457. self.assertEqual(Timestamp('nat').asm8.view('i8'),
  458. np.datetime64('nat', 'ns').view('i8'))
  459. def test_fields(self):
  460. def check(value, equal):
  461. # that we are int/long like
  462. self.assertTrue(isinstance(value, (int, compat.long)))
  463. self.assertEqual(value, equal)
  464. # GH 10050
  465. ts = Timestamp('2015-05-10 09:06:03.000100001')
  466. check(ts.year, 2015)
  467. check(ts.month, 5)
  468. check(ts.day, 10)
  469. check(ts.hour, 9)
  470. check(ts.minute, 6)
  471. check(ts.second, 3)
  472. self.assertRaises(AttributeError, lambda: ts.millisecond)
  473. check(ts.microsecond, 100)
  474. check(ts.nanosecond, 1)
  475. check(ts.dayofweek, 6)
  476. check(ts.quarter, 2)
  477. check(ts.dayofyear, 130)
  478. check(ts.week, 19)
  479. check(ts.daysinmonth, 31)
  480. check(ts.daysinmonth, 31)
  481. def test_nat_fields(self):
  482. # GH 10050
  483. ts = Timestamp('NaT')
  484. self.assertTrue(np.isnan(ts.year))
  485. self.assertTrue(np.isnan(ts.month))
  486. self.assertTrue(np.isnan(ts.day))
  487. self.assertTrue(np.isnan(ts.hour))
  488. self.assertTrue(np.isnan(ts.minute))
  489. self.assertTrue(np.isnan(ts.second))
  490. self.assertTrue(np.isnan(ts.microsecond))
  491. self.assertTrue(np.isnan(ts.nanosecond))
  492. self.assertTrue(np.isnan(ts.dayofweek))
  493. self.assertTrue(np.isnan(ts.quarter))
  494. self.assertTrue(np.isnan(ts.dayofyear))
  495. self.assertTrue(np.isnan(ts.week))
  496. self.assertTrue(np.isnan(ts.daysinmonth))
  497. self.assertTrue(np.isnan(ts.days_in_month))
  498. def test_pprint(self):
  499. # GH12622
  500. import pprint
  501. nested_obj = {'foo': 1,
  502. 'bar': [{'w': {'a': Timestamp('2011-01-01')}}] * 10}
  503. result = pprint.pformat(nested_obj, width=50)
  504. expected = r"""{'bar': [{'w': {'a': Timestamp('2011-01-01 00:00:00')}},
  505. {'w': {'a': Timestamp('2011-01-01 00:00:00')}},
  506. {'w': {'a': Timestamp('2011-01-01 00:00:00')}},
  507. {'w': {'a': Timestamp('2011-01-01 00:00:00')}},
  508. {'w': {'a': Timestamp('2011-01-01 00:00:00')}},
  509. {'w': {'a': Timestamp('2011-01-01 00:00:00')}},
  510. {'w': {'a': Timestamp('2011-01-01 00:00:00')}},
  511. {'w': {'a': Timestamp('2011-01-01 00:00:00')}},
  512. {'w': {'a': Timestamp('2011-01-01 00:00:00')}},
  513. {'w': {'a': Timestamp('2011-01-01 00:00:00')}}],
  514. 'foo': 1}"""
  515. self.assertEqual(result, expected)
  516. class TestDatetimeParsingWrappers(tm.TestCase):
  517. def test_does_not_convert_mixed_integer(self):
  518. bad_date_strings = ('-50000', '999', '123.1234', 'm', 'T')
  519. for bad_date_string in bad_date_strings:
  520. self.assertFalse(tslib._does_string_look_like_datetime(
  521. bad_date_string))
  522. good_date_strings = ('2012-01-01',
  523. '01/01/2012',
  524. 'Mon Sep 16, 2013',
  525. '01012012',
  526. '0101',
  527. '1-1', )
  528. for good_date_string in good_date_strings:
  529. self.assertTrue(tslib._does_string_look_like_datetime(
  530. good_date_string))
  531. def test_parsers(self):
  532. # https://github.com/dateutil/dateutil/issues/217
  533. import dateutil
  534. yearfirst = dateutil.__version__ >= LooseVersion('2.5.0')
  535. cases = {'2011-01-01': datetime.datetime(2011, 1, 1),
  536. '2Q2005': datetime.datetime(2005, 4, 1),
  537. '2Q05': datetime.datetime(2005, 4, 1),
  538. '2005Q1': datetime.datetime(2005, 1, 1),
  539. '05Q1': datetime.datetime(2005, 1, 1),
  540. '2011Q3': datetime.datetime(2011, 7, 1),
  541. '11Q3': datetime.datetime(2011, 7, 1),
  542. '3Q2011': datetime.datetime(2011, 7, 1),
  543. '3Q11': datetime.datetime(2011, 7, 1),
  544. # quarterly without space
  545. '2000Q4': datetime.datetime(2000, 10, 1),
  546. '00Q4': datetime.datetime(2000, 10, 1),
  547. '4Q2000': datetime.datetime(2000, 10, 1),
  548. '4Q00': datetime.datetime(2000, 10, 1),
  549. '2000q4': datetime.datetime(2000, 10, 1),
  550. '2000-Q4': datetime.datetime(2000, 10, 1),
  551. '00-Q4': datetime.datetime(2000, 10, 1),
  552. '4Q-2000': datetime.datetime(2000, 10, 1),
  553. '4Q-00': datetime.datetime(2000, 10, 1),
  554. '2000q4': datetime.datetime(2000, 10, 1),
  555. '00q4': datetime.datetime(2000, 10, 1),
  556. '2005': datetime.datetime(2005, 1, 1),
  557. '2005-11': datetime.datetime(2005, 11, 1),
  558. '2005 11': datetime.datetime(2005, 11, 1),
  559. '11-2005': datetime.datetime(2005, 11, 1),
  560. '11 2005': datetime.datetime(2005, 11, 1),
  561. '200511': datetime.datetime(2020, 5, 11),
  562. '20051109': datetime.datetime(2005, 11, 9),
  563. '20051109 10:15': datetime.datetime(2005, 11, 9, 10, 15),
  564. '20051109 08H': datetime.datetime(2005, 11, 9, 8, 0),
  565. '2005-11-09 10:15': datetime.datetime(2005, 11, 9, 10, 15),
  566. '2005-11-09 08H': datetime.datetime(2005, 11, 9, 8, 0),
  567. '2005/11/09 10:15': datetime.datetime(2005, 11, 9, 10, 15),
  568. '2005/11/09 08H': datetime.datetime(2005, 11, 9, 8, 0),
  569. "Thu Sep 25 10:36:28 2003": datetime.datetime(2003, 9, 25, 10,
  570. 36, 28),
  571. "Thu Sep 25 2003": datetime.datetime(2003, 9, 25),
  572. "Sep 25 2003": datetime.datetime(2003, 9, 25),
  573. "January 1 2014": datetime.datetime(2014, 1, 1),
  574. # GH 10537
  575. '2014-06': datetime.datetime(2014, 6, 1),
  576. '06-2014': datetime.datetime(2014, 6, 1),
  577. '2014-6': datetime.datetime(2014, 6, 1),
  578. '6-2014': datetime.datetime(2014, 6, 1),
  579. '20010101 12': datetime.datetime(2001, 1, 1, 12),
  580. '20010101 1234': datetime.datetime(2001, 1, 1, 12, 34),
  581. '20010101 123456': datetime.datetime(2001, 1, 1, 12, 34, 56),
  582. }
  583. for date_str, expected in compat.iteritems(cases):
  584. result1, _, _ = tools.parse_time_string(date_str,
  585. yearfirst=yearfirst)
  586. result2 = to_datetime(date_str, yearfirst=yearfirst)
  587. result3 = to_datetime([date_str], yearfirst=yearfirst)
  588. # result5 is used below
  589. result4 = to_datetime(np.array([date_str], dtype=object),
  590. yearfirst=yearfirst)
  591. result6 = DatetimeIndex([date_str], yearfirst=yearfirst)
  592. # result7 is used below
  593. result8 = DatetimeIndex(Index([date_str]), yearfirst=yearfirst)
  594. result9 = DatetimeIndex(Series([date_str]), yearfirst=yearfirst)
  595. for res in [result1, result2]:
  596. self.assertEqual(res, expected)
  597. for res in [result3, result4, result6, result8, result9]:
  598. exp = DatetimeIndex([pd.Timestamp(expected)])
  599. tm.assert_index_equal(res, exp)
  600. # these really need to have yearfist, but we don't support
  601. if not yearfirst:
  602. result5 = Timestamp(date_str)
  603. self.assertEqual(result5, expected)
  604. result7 = date_range(date_str, freq='S', periods=1,
  605. yearfirst=yearfirst)
  606. self.assertEqual(result7, expected)
  607. # NaT
  608. result1, _, _ = tools.parse_time_string('NaT')
  609. result2 = to_datetime('NaT')
  610. result3 = Timestamp('NaT')
  611. result4 = DatetimeIndex(['NaT'])[0]
  612. self.assertTrue(result1 is tslib.NaT)
  613. self.assertTrue(result1 is tslib.NaT)
  614. self.assertTrue(result1 is tslib.NaT)
  615. self.assertTrue(result1 is tslib.NaT)
  616. def test_parsers_quarter_invalid(self):
  617. cases = ['2Q 2005', '2Q-200A', '2Q-200', '22Q2005', '6Q-20', '2Q200.']
  618. for case in cases:
  619. self.assertRaises(ValueError, tools.parse_time_string, case)
  620. def test_parsers_dayfirst_yearfirst(self):
  621. tm._skip_if_no_dateutil()
  622. # OK
  623. # 2.5.1 10-11-12 [dayfirst=0, yearfirst=0] -> 2012-10-11 00:00:00
  624. # 2.5.2 10-11-12 [dayfirst=0, yearfirst=1] -> 2012-10-11 00:00:00
  625. # 2.5.3 10-11-12 [dayfirst=0, yearfirst=0] -> 2012-10-11 00:00:00
  626. # OK
  627. # 2.5.1 10-11-12 [dayfirst=0, yearfirst=1] -> 2010-11-12 00:00:00
  628. # 2.5.2 10-11-12 [dayfirst=0, yearfirst=1] -> 2010-11-12 00:00:00
  629. # 2.5.3 10-11-12 [dayfirst=0, yearfirst=1] -> 2010-11-12 00:00:00
  630. # bug fix in 2.5.2
  631. # 2.5.1 10-11-12 [dayfirst=1, yearfirst=1] -> 2010-11-12 00:00:00
  632. # 2.5.2 10-11-12 [dayfirst=1, yearfirst=1] -> 2010-12-11 00:00:00
  633. # 2.5.3 10-11-12 [dayfirst=1, yearfirst=1] -> 2010-12-11 00:00:00
  634. # OK
  635. # 2.5.1 10-11-12 [dayfirst=1, yearfirst=0] -> 2012-11-10 00:00:00
  636. # 2.5.2 10-11-12 [dayfirst=1, yearfirst=0] -> 2012-11-10 00:00:00
  637. # 2.5.3 10-11-12 [dayfirst=1, yearfirst=0] -> 2012-11-10 00:00:00
  638. # OK
  639. # 2.5.1 20/12/21 [dayfirst=0, yearfirst=0] -> 2021-12-20 00:00:00
  640. # 2.5.2 20/12/21 [dayfirst=0, yearfirst=0] -> 2021-12-20 00:00:00
  641. # 2.5.3 20/12/21 [dayfirst=0, yearfirst=0] -> 2021-12-20 00:00:00
  642. # OK
  643. # 2.5.1 20/12/21 [dayfirst=0, yearfirst=1] -> 2020-12-21 00:00:00
  644. # 2.5.2 20/12/21 [dayfirst=0, yearfirst=1] -> 2020-12-21 00:00:00
  645. # 2.5.3 20/12/21 [dayfirst=0, yearfirst=1] -> 2020-12-21 00:00:00
  646. # revert of bug in 2.5.2
  647. # 2.5.1 20/12/21 [dayfirst=1, yearfirst=1] -> 2020-12-21 00:00:00
  648. # 2.5.2 20/12/21 [dayfirst=1, yearfirst=1] -> month must be in 1..12
  649. # 2.5.3 20/12/21 [dayfirst=1, yearfirst=1] -> 2020-12-21 00:00:00
  650. # OK
  651. # 2.5.1 20/12/21 [dayfirst=1, yearfirst=0] -> 2021-12-20 00:00:00
  652. # 2.5.2 20/12/21 [dayfirst=1, yearfirst=0] -> 2021-12-20 00:00:00
  653. # 2.5.3 20/12/21 [dayfirst=1, yearfirst=0] -> 2021-12-20 00:00:00
  654. import dateutil
  655. is_lt_253 = dateutil.__version__ < LooseVersion('2.5.3')
  656. # str : dayfirst, yearfirst, expected
  657. cases = {'10-11-12': [(False, False,
  658. datetime.datetime(2012, 10, 11)),
  659. (True, False,
  660. datetime.datetime(2012, 11, 10)),
  661. (False, True,
  662. datetime.datetime(2010, 11, 12)),
  663. (True, True,
  664. datetime.datetime(2010, 12, 11))],
  665. '20/12/21': [(False, False,
  666. datetime.datetime(2021, 12, 20)),
  667. (True, False,
  668. datetime.datetime(2021, 12, 20)),
  669. (False, True,
  670. datetime.datetime(2020, 12, 21)),
  671. (True, True,
  672. datetime.datetime(2020, 12, 21))]}
  673. from dateutil.parser import parse
  674. for date_str, values in compat.iteritems(cases):
  675. for dayfirst, yearfirst, expected in values:
  676. # odd comparisons across version
  677. # let's just skip
  678. if dayfirst and yearfirst and is_lt_253:
  679. continue
  680. # compare with dateutil result
  681. dateutil_result = parse(date_str, dayfirst=dayfirst,
  682. yearfirst=yearfirst)
  683. self.assertEqual(dateutil_result, expected)
  684. result1, _, _ = tools.parse_time_string(date_str,
  685. dayfirst=dayfirst,
  686. yearfirst=yearfirst)
  687. # we don't support dayfirst/yearfirst here:
  688. if not dayfirst and not yearfirst:
  689. result2 = Timestamp(date_str)
  690. self.assertEqual(result2, expected)
  691. result3 = to_datetime(date_str, dayfirst=dayfirst,
  692. yearfirst=yearfirst)
  693. result4 = DatetimeIndex([date_str], dayfirst=dayfirst,
  694. yearfirst=yearfirst)[0]
  695. self.assertEqual(result1, expected)
  696. self.assertEqual(result3, expected)
  697. self.assertEqual(result4, expected)
  698. def test_parsers_timestring(self):
  699. tm._skip_if_no_dateutil()
  700. from dateutil.parser import parse
  701. # must be the same as dateutil result
  702. cases = {'10:15': (parse('10:15'), datetime.datetime(1, 1, 1, 10, 15)),
  703. '9:05': (parse('9:05'), datetime.datetime(1, 1, 1, 9, 5))}
  704. for date_str, (exp_now, exp_def) in compat.iteritems(cases):
  705. result1, _, _ = tools.parse_time_string(date_str)
  706. result2 = to_datetime(date_str)
  707. result3 = to_datetime([date_str])
  708. result4 = Timestamp(date_str)
  709. result5 = DatetimeIndex([date_str])[0]
  710. # parse time string return time string based on default date
  711. # others are not, and can't be changed because it is used in
  712. # time series plot
  713. self.assertEqual(result1, exp_def)
  714. self.assertEqual(result2, exp_now)
  715. self.assertEqual(result3, exp_now)
  716. self.assertEqual(result4, exp_now)
  717. self.assertEqual(result5, exp_now)
  718. def test_parsers_time(self):
  719. # GH11818
  720. _skip_if_has_locale()
  721. strings = ["14:15", "1415", "2:15pm", "0215pm", "14:15:00", "141500",
  722. "2:15:00pm", "021500pm", datetime.time(14, 15)]
  723. expected = datetime.time(14, 15)
  724. for time_string in strings:
  725. self.assertEqual(tools.to_time(time_string), expected)
  726. new_string = "14.15"
  727. self.assertRaises(ValueError, tools.to_time, new_string)
  728. self.assertEqual(tools.to_time(new_string, format="%H.%M"), expected)
  729. arg = ["14:15", "20:20"]
  730. expected_arr = [datetime.time(14, 15), datetime.time(20, 20)]
  731. self.assertEqual(tools.to_time(arg), expected_arr)
  732. self.assertEqual(tools.to_time(arg, format="%H:%M"), expected_arr)
  733. self.assertEqual(tools.to_time(arg, infer_time_format=True),
  734. expected_arr)
  735. self.assertEqual(tools.to_time(arg, format="%I:%M%p", errors="coerce"),
  736. [None, None])
  737. res = tools.to_time(arg, format="%I:%M%p", errors="ignore")
  738. self.assert_numpy_array_equal(res, np.array(arg, dtype=np.object_))
  739. with tm.assertRaises(ValueError):
  740. tools.to_time(arg, format="%I:%M%p", errors="raise")
  741. self.assert_series_equal(tools.to_time(Series(arg, name="test")),
  742. Series(expected_arr, name="test"))
  743. res = tools.to_time(np.array(arg))
  744. self.assertIsInstance(res, list)
  745. self.assert_equal(res, expected_arr)
  746. def test_parsers_monthfreq(self):
  747. cases = {'201101': datetime.datetime(2011, 1, 1, 0, 0),
  748. '200005': datetime.datetime(2000, 5, 1, 0, 0)}
  749. for date_str, expected in compat.iteritems(cases):
  750. result1, _, _ = tools.parse_time_string(date_str, freq='M')
  751. self.assertEqual(result1, expected)
  752. def test_parsers_quarterly_with_freq(self):
  753. msg = ('Incorrect quarterly string is given, quarter '
  754. 'must be between 1 and 4: 2013Q5')
  755. with tm.assertRaisesRegexp(tslib.DateParseError, msg):
  756. tools.parse_time_string('2013Q5')
  757. # GH 5418
  758. msg = ('Unable to retrieve month information from given freq: '
  759. 'INVLD-L-DEC-SAT')
  760. with tm.assertRaisesRegexp(tslib.DateParseError, msg):
  761. tools.parse_time_string('2013Q1', freq='INVLD-L-DEC-SAT')
  762. cases = {('2013Q2', None): datetime.datetime(2013, 4, 1),
  763. ('2013Q2', 'A-APR'): datetime.datetime(2012, 8, 1),
  764. ('2013-Q2', 'A-DEC'): datetime.datetime(2013, 4, 1)}
  765. for (date_str, freq), exp in compat.iteritems(cases):
  766. result, _, _ = tools.parse_time_string(date_str, freq=freq)
  767. self.assertEqual(result, exp)
  768. def test_parsers_timezone_minute_offsets_roundtrip(self):
  769. # GH11708
  770. base = to_datetime("2013-01-01 00:00:00")
  771. dt_strings = [
  772. ('2013-01-01 05:45+0545',
  773. "Asia/Katmandu",
  774. "Timestamp('2013-01-01 05:45:00+0545', tz='Asia/Katmandu')"),
  775. ('2013-01-01 05:30+0530',
  776. "Asia/Kolkata",
  777. "Timestamp('2013-01-01 05:30:00+0530', tz='Asia/Kolkata')")
  778. ]
  779. for dt_string, tz, dt_string_repr in dt_strings:
  780. dt_time = to_datetime(dt_string)
  781. self.assertEqual(base, dt_time)
  782. converted_time = dt_time.tz_localize('UTC').tz_convert(tz)
  783. self.assertEqual(dt_string_repr, repr(converted_time))
  784. def test_parsers_iso8601(self):
  785. # GH 12060
  786. # test only the iso parser - flexibility to different
  787. # separators and leadings 0s
  788. # Timestamp construction falls back to dateutil
  789. cases = {'2011-01-02': datetime.datetime(2011, 1, 2),
  790. '2011-1-2': datetime.datetime(2011, 1, 2),
  791. '2011-01': datetime.datetime(2011, 1, 1),
  792. '2011-1': datetime.datetime(2011, 1, 1),
  793. '2011 01 02': datetime.datetime(2011, 1, 2),
  794. '2011.01.02': datetime.datetime(2011, 1, 2),
  795. '2011/01/02': datetime.datetime(2011, 1, 2),
  796. '2011\\01\\02': datetime.datetime(2011, 1, 2),
  797. '2013-01-01 05:30:00': datetime.datetime(2013, 1, 1, 5, 30),
  798. '2013-1-1 5:30:00': datetime.datetime(2013, 1, 1, 5, 30)}
  799. for date_str, exp in compat.iteritems(cases):
  800. actual = tslib._test_parse_iso8601(date_str)
  801. self.assertEqual(actual, exp)
  802. # seperators must all match - YYYYMM not valid
  803. invalid_cases = ['2011-01/02', '2011^11^11',
  804. '201401', '201111', '200101',
  805. # mixed separated and unseparated
  806. '2005-0101', '200501-01',
  807. '20010101 12:3456', '20010101 1234:56',
  808. # HHMMSS must have two digits in each component
  809. # if unseparated
  810. '20010101 1', '20010101 123', '20010101 12345',
  811. '20010101 12345Z',
  812. # wrong separator for HHMMSS
  813. '2001-01-01 12-34-56']
  814. for date_str in invalid_cases:
  815. with tm.assertRaises(ValueError):
  816. tslib._test_parse_iso8601(date_str)
  817. # If no ValueError raised, let me know which case failed.
  818. raise Exception(date_str)
  819. class TestArrayToDatetime(tm.TestCase):
  820. def test_parsing_valid_dates(self):
  821. arr = np.array(['01-01-2013', '01-02-2013'], dtype=object)
  822. self.assert_numpy_array_equal(
  823. tslib.array_to_datetime(arr),
  824. np_array_datetime64_compat(
  825. [
  826. '2013-01-01T00:00:00.000000000-0000',
  827. '2013-01-02T00:00:00.000000000-0000'
  828. ],
  829. dtype='M8[ns]'
  830. )
  831. )
  832. arr = np.array(['Mon Sep 16 2013', 'Tue Sep 17 2013'], dtype=object)
  833. self.assert_numpy_array_equal(
  834. tslib.array_to_datetime(arr),
  835. np_array_datetime64_compat(
  836. [
  837. '2013-09-16T00:00:00.000000000-0000',
  838. '2013-09-17T00:00:00.000000000-0000'
  839. ],
  840. dtype='M8[ns]'
  841. )
  842. )
  843. def test_number_looking_strings_not_into_datetime(self):
  844. # #4601
  845. # These strings don't look like datetimes so they shouldn't be
  846. # attempted to be converted
  847. arr = np.array(['-352.737091', '183.575577'], dtype=object)
  848. self.assert_numpy_array_equal(
  849. tslib.array_to_datetime(arr, errors='ignore'), arr)
  850. arr = np.array(['1', '2', '3', '4', '5'], dtype=object)
  851. self.assert_numpy_array_equal(
  852. tslib.array_to_datetime(arr, errors='ignore'), arr)
  853. def test_coercing_dates_outside_of_datetime64_ns_bounds(self):
  854. invalid_dates = [
  855. datetime.date(1000, 1, 1),
  856. datetime.datetime(1000, 1, 1),
  857. '1000-01-01',
  858. 'Jan 1, 1000',
  859. np.datetime64('1000-01-01'),
  860. ]
  861. for invalid_date in invalid_dates:
  862. self.assertRaises(ValueError,
  863. tslib.array_to_datetime,
  864. np.array(
  865. [invalid_date], dtype='object'),
  866. errors='raise', )
  867. self.assert_numpy_array_equal(
  868. tslib.array_to_datetime(
  869. np.array([invalid_date], dtype='object'),
  870. errors='coerce'),
  871. np.array([tslib.iNaT], dtype='M8[ns]')
  872. )
  873. arr = np.array(['1/1/1000', '1/1/2000'], dtype=object)
  874. self.assert_numpy_array_equal(
  875. tslib.array_to_datetime(arr, errors='coerce'),
  876. np_array_datetime64_compat(
  877. [
  878. tslib.iNaT,
  879. '2000-01-01T00:00:00.000000000-0000'
  880. ],
  881. dtype='M8[ns]'
  882. )
  883. )
  884. def test_coerce_of_invalid_datetimes(self):
  885. arr = np.array(['01-01-2013', 'not_a_date', '1'], dtype=object)
  886. # Without coercing, the presence of any invalid dates prevents
  887. # any values from being converted
  888. self.assert_numpy_array_equal(
  889. tslib.array_to_datetime(arr, errors='ignore'), arr)
  890. # With coercing, the invalid dates becomes iNaT
  891. self.assert_numpy_array_equal(
  892. tslib.array_to_datetime(arr, errors='coerce'),
  893. np_array_datetime64_compat(
  894. [
  895. '2013-01-01T00:00:00.000000000-0000',
  896. tslib.iNaT,
  897. tslib.iNaT
  898. ],
  899. dtype='M8[ns]'
  900. )
  901. )
  902. def test_parsing_timezone_offsets(self):
  903. # All of these datetime strings with offsets are equivalent
  904. # to the same datetime after the timezone offset is added
  905. dt_strings = [
  906. '01-01-2013 08:00:00+08:00',
  907. '2013-01-01T08:00:00.000000000+0800',
  908. '2012-12-31T16:00:00.000000000-0800',
  909. '12-31-2012 23:00:00-01:00'
  910. ]
  911. expected_output = tslib.array_to_datetime(np.array(
  912. ['01-01-2013 00:00:00'], dtype=object))
  913. for dt_string in dt_strings:
  914. self.assert_numpy_array_equal(
  915. tslib.array_to_datetime(
  916. np.array([dt_string], dtype=object)
  917. ),
  918. expected_output
  919. )
  920. class TestTimestampNsOperations(tm.TestCase):
  921. def setUp(self):
  922. self.timestamp = Timestamp(datetime.datetime.utcnow())
  923. def assert_ns_timedelta(self, modified_timestamp, expected_value):
  924. value = self.timestamp.value
  925. modified_value = modified_timestamp.value
  926. self.assertEqual(modified_value - value, expected_value)
  927. def test_timedelta_ns_arithmetic(self):
  928. self.assert_ns_timedelta(self.timestamp + np.timedelta64(-123, 'ns'),
  929. -123)
  930. def test_timedelta_ns_based_arithmetic(self):
  931. self.assert_ns_timedelta(self.timestamp + np.timedelta64(
  932. 1234567898, 'ns'), 1234567898)
  933. def test_timedelta_us_arithmetic(self):
  934. self.assert_ns_timedelta(self.timestamp + np.timedelta64(-123, 'us'),
  935. -123000)
  936. def test_timedelta_ms_arithmetic(self):
  937. time = self.timestamp + np.timedelta64(-123, 'ms')
  938. self.assert_ns_timedelta(time, -123000000)
  939. def test_nanosecond_string_parsing(self):
  940. ts = Timestamp('2013-05-01 07:15:45.123456789')
  941. # GH 7878
  942. expected_repr = '2013-05-01 07:15:45.123456789'
  943. expected_value = 1367392545123456789
  944. self.assertEqual(ts.value, expected_value)
  945. self.assertIn(expected_repr, repr(ts))
  946. ts = Timestamp('2013-05-01 07:15:45.123456789+09:00', tz='Asia/Tokyo')
  947. self.assertEqual(ts.value, expected_value - 9 * 3600 * 1000000000)
  948. self.assertIn(expected_repr, repr(ts))
  949. ts = Timestamp('2013-05-01 07:15:45.123456789', tz='UTC')
  950. self.assertEqual(ts.value, expected_value)
  951. self.assertIn(expected_repr, repr(ts))
  952. ts = Timestamp('2013-05-01 07:15:45.123456789', tz='US/Eastern')
  953. self.assertEqual(ts.value, expected_value + 4 * 3600 * 1000000000)
  954. self.assertIn(expected_repr, repr(ts))
  955. # GH 10041
  956. ts = Timestamp('20130501T071545.123456789')
  957. self.assertEqual(ts.value, expected_value)
  958. self.assertIn(expected_repr, repr(ts))
  959. def test_nanosecond_timestamp(self):
  960. # GH 7610
  961. expected = 1293840000000000005
  962. t = Timestamp('2011-01-01') + offsets.Nano(5)
  963. self.assertEqual(repr(t), "Timestamp('2011-01-01 00:00:00.000000005')")
  964. self.assertEqual(t.value, expected)
  965. self.assertEqual(t.nanosecond, 5)
  966. t = Timestamp(t)
  967. self.assertEqual(repr(t), "Timestamp('2011-01-01 00:00:00.000000005')")
  968. self.assertEqual(t.value, expected)
  969. self.assertEqual(t.nanosecond, 5)
  970. t = Timestamp(np_datetime64_compat('2011-01-01 00:00:00.000000005Z'))
  971. self.assertEqual(repr(t), "Timestamp('2011-01-01 00:00:00.000000005')")
  972. self.assertEqual(t.value, expected)
  973. self.assertEqual(t.nanosecond, 5)
  974. expected = 1293840000000000010
  975. t = t + offsets.Nano(5)
  976. self.assertEqual(repr(t), "Timestamp('2011-01-01 00:00:00.000000010')")
  977. self.assertEqual(t.value, expected)
  978. self.assertEqual(t.nanosecond, 10)
  979. t = Timestamp(t)
  980. self.assertEqual(repr(t), "Timestamp('2011-01-01 00:00:00.000000010')")
  981. self.assertEqual(t.value, expected)
  982. self.assertEqual(t.nanosecond, 10)
  983. t = Timestamp(np_datetime64_compat('2011-01-01 00:00:00.000000010Z'))
  984. self.assertEqual(repr(t), "Timestamp('2011-01-01 00:00:00.000000010')")
  985. self.assertEqual(t.value, expected)
  986. self.assertEqual(t.nanosecond, 10)
  987. def test_nat_arithmetic(self):
  988. # GH 6873
  989. i = 2
  990. f = 1.5
  991. for (left, right) in [(pd.NaT, i), (pd.NaT, f), (pd.NaT, np.nan)]:
  992. self.assertIs(left / right, pd.NaT)
  993. self.assertIs(left * right, pd.NaT)
  994. self.assertIs(right * left, pd.NaT)
  995. with tm.assertRaises(TypeError):
  996. right / left
  997. # Timestamp / datetime
  998. t = Timestamp('2014-01-01')
  999. dt = datetime.datetime(2014, 1, 1)
  1000. for (left, right) in [(pd.NaT, pd.NaT), (pd.NaT, t), (pd.NaT, dt)]:
  1001. # NaT __add__ or __sub__ Timestamp-like (or inverse) returns NaT
  1002. self.assertIs(right + left, pd.NaT)
  1003. self.assertIs(left + right, pd.NaT)
  1004. self.assertIs(left - right, pd.NaT)
  1005. self.assertIs(right - left, pd.NaT)
  1006. # timedelta-like
  1007. # offsets are tested in test_offsets.py
  1008. delta = datetime.timedelta(3600)
  1009. td = Timedelta('5s')
  1010. for (left, right) in [(pd.NaT, delta), (pd.NaT, td)]:
  1011. # NaT + timedelta-like returns NaT
  1012. self.assertIs(right + left, pd.NaT)
  1013. self.assertIs(left + right, pd.NaT)
  1014. self.assertIs(right - left, pd.NaT)
  1015. self.assertIs(left - right, pd.NaT)
  1016. # GH 11718
  1017. tm._skip_if_no_pytz()
  1018. import pytz
  1019. t_utc = Timestamp('2014-01-01', tz='UTC')
  1020. t_tz = Timestamp('2014-01-01', tz='US/Eastern')
  1021. dt_tz = pytz.timezone('Asia/Tokyo').localize(dt)
  1022. for (left, right) in [(pd.NaT, t_utc), (pd.NaT, t_tz),
  1023. (pd.NaT, dt_tz)]:
  1024. # NaT __add__ or __sub__ Timestamp-like (or inverse) returns NaT
  1025. self.assertIs(right + left, pd.NaT)
  1026. self.assertIs(left + right, pd.NaT)
  1027. self.assertIs(left - right, pd.NaT)
  1028. self.assertIs(right - left, pd.NaT)
  1029. # int addition / subtraction
  1030. for (left, right) in [(pd.NaT, 2), (pd.NaT, 0), (pd.NaT, -3)]:
  1031. self.assertIs(right + left, pd.NaT)
  1032. self.assertIs(left + right, pd.NaT)
  1033. self.assertIs(left - right, pd.NaT)
  1034. self.assertIs(right - left, pd.NaT)
  1035. def test_nat_arithmetic_index(self):
  1036. # GH 11718
  1037. # datetime
  1038. tm._skip_if_no_pytz()
  1039. dti = pd.DatetimeIndex(['2011-01-01', '2011-01-02'], name='x')
  1040. exp = pd.DatetimeIndex([pd.NaT, pd.NaT], name='x')
  1041. self.assert_index_equal(dti + pd.NaT, exp)
  1042. self.assert_index_equal(pd.NaT + dti, exp)
  1043. dti_tz = pd.DatetimeIndex(['2011-01-01', '2011-01-02'],
  1044. tz='US/Eastern', name='x')
  1045. exp = pd.DatetimeIndex([pd.NaT, pd.NaT], name='x', tz='US/Eastern')
  1046. self.assert_index_equal(dti_tz + pd.NaT, exp)
  1047. self.assert_index_equal(pd.NaT + dti_tz, exp)
  1048. exp = pd.TimedeltaIndex([pd.NaT, pd.NaT], name='x')
  1049. for (left, right) in [(pd.NaT, dti), (pd.NaT, dti_tz)]:
  1050. self.assert_index_equal(left - right, exp)
  1051. self.assert_index_equal(right - left, exp)
  1052. # timedelta
  1053. tdi = pd.TimedeltaIndex(['1 day', '2 day'], name='x')
  1054. exp = pd.DatetimeIndex([pd.NaT, pd.NaT], name='x')
  1055. for (left, right) in [(pd.NaT, tdi)]:
  1056. self.assert_index_equal(left + right, exp)
  1057. self.assert_index_equal(right + left, exp)
  1058. self.assert_index_equal(left - right, exp)
  1059. self.assert_index_equal(right - left, exp)
  1060. class TestTslib(tm.TestCase):
  1061. def test_intraday_conversion_factors(self):
  1062. self.assertEqual(period_asfreq(
  1063. 1, get_freq('D'), get_freq('H'), False), 24)
  1064. self.assertEqual(period_asfreq(
  1065. 1, get_freq('D'), get_freq('T'), False), 1440)
  1066. self.assertEqual(period_asfreq(
  1067. 1, get_freq('D'), get_freq('S'), False), 86400)
  1068. self.assertEqual(period_asfreq(1, get_freq(
  1069. 'D'), get_freq('L'), False), 86400000)
  1070. self.assertEqual(period_asfreq(1, get_freq(
  1071. 'D'), get_freq('U'), False), 86400000000)
  1072. self.assertEqual(period_asfreq(1, get_freq(
  1073. 'D'), get_freq('N'), False), 86400000000000)
  1074. self.assertEqual(period_asfreq(
  1075. 1, get_freq('H'), get_freq('T'), False), 60)
  1076. self.assertEqual(period_asfreq(
  1077. 1, get_freq('H'), get_freq('S'), False), 3600)
  1078. self.assertEqual(period_asfreq(1, get_freq('H'),
  1079. get_freq('L'), False), 3600000)
  1080. self.assertEqual(period_asfreq(1, get_freq(
  1081. 'H'), get_freq('U'), False), 3600000000)
  1082. self.assertEqual(period_asfreq(1, get_freq(
  1083. 'H'), get_freq('N'), False), 3600000000000)
  1084. self.assertEqual(period_asfreq(
  1085. 1, get_freq('T'), get_freq('S'), False), 60)
  1086. self.assertEqual(period_asfreq(
  1087. 1, get_freq('T'), get_freq('L'), False), 60000)
  1088. self.assertEqual(period_asfreq(1, get_freq(
  1089. 'T'), get_freq('U'), False), 60000000)
  1090. self.assertEqual(period_asfreq(1, get_freq(
  1091. 'T'), get_freq('N'), False), 60000000000)
  1092. self.assertEqual(period_asfreq(
  1093. 1, get_freq('S'), get_freq('L'), False), 1000)
  1094. self.assertEqual(period_asfreq(1, get_freq('S'),
  1095. get_freq('U'), False), 1000000)
  1096. self.assertEqual(period_asfreq(1, get_freq(
  1097. 'S'), get_freq('N'), False), 1000000000)
  1098. self.assertEqual(period_asfreq(
  1099. 1, get_freq('L'), get_freq('U'), False), 1000)
  1100. self.assertEqual(period_asfreq(1, get_freq('L'),
  1101. get_freq('N'), False), 1000000)
  1102. self.assertEqual(period_asfreq(
  1103. 1, get_freq('U'), get_freq('N'), False), 1000)
  1104. def test_period_ordinal_start_values(self):
  1105. # information for 1.1.1970
  1106. self.assertEqual(0, period_ordinal(1970, 1, 1, 0, 0, 0, 0, 0,
  1107. get_freq('A')))
  1108. self.assertEqual(0, period_ordinal(1970, 1, 1, 0, 0, 0, 0, 0,
  1109. get_freq('M')))
  1110. self.assertEqual(1, period_ordinal(1970, 1, 1, 0, 0, 0, 0, 0,
  1111. get_freq('W')))
  1112. self.assertEqual(0, period_ordinal(1970, 1, 1, 0, 0, 0, 0, 0,
  1113. get_freq('D')))
  1114. self.assertEqual(0, period_ordinal(1970, 1, 1, 0, 0, 0, 0, 0,
  1115. get_freq('B')))
  1116. def test_period_ordinal_week(self):
  1117. self.assertEqual(1, period_ordinal(1970, 1, 4, 0, 0, 0, 0, 0,
  1118. get_freq('W')))
  1119. self.assertEqual(2, period_ordinal(1970, 1, 5, 0, 0, 0, 0, 0,
  1120. get_freq('W')))
  1121. self.assertEqual(2284, period_ordinal(2013, 10, 6, 0, 0, 0, 0, 0,
  1122. get_freq('W')))
  1123. self.assertEqual(2285, period_ordinal(2013, 10, 7, 0, 0, 0, 0, 0,
  1124. get_freq('W')))
  1125. def test_period_ordinal_business_day(self):
  1126. # Thursday
  1127. self.assertEqual(11415, period_ordinal(2013, 10, 3, 0, 0, 0, 0, 0,
  1128. get_freq('B')))
  1129. # Friday
  1130. self.assertEqual(11416, period_ordinal(2013, 10, 4, 0, 0, 0, 0, 0,
  1131. get_freq('B')))
  1132. # Saturday
  1133. self.assertEqual(11417, period_ordinal(2013, 10, 5, 0, 0, 0, 0, 0,
  1134. get_freq('B')))
  1135. # Sunday
  1136. self.assertEqual(11417, period_ordinal(2013, 10, 6, 0, 0, 0, 0, 0,
  1137. get_freq('B')))
  1138. # Monday
  1139. self.assertEqual(11417, period_ordinal(2013, 10, 7, 0, 0, 0, 0, 0,
  1140. get_freq('B')))
  1141. # Tuesday
  1142. self.assertEqual(11418, period_ordinal(2013, 10, 8, 0, 0, 0, 0, 0,
  1143. get_freq('B')))
  1144. def test_tslib_tz_convert(self):
  1145. def compare_utc_to_local(tz_didx, utc_didx):
  1146. f = lambda x: tslib.tz_convert_single(x, 'UTC', tz_didx.tz)
  1147. result = tslib.tz_convert(tz_didx.asi8, 'UTC', tz_didx.tz)
  1148. result_single = np.vectorize(f)(tz_didx.asi8)
  1149. self.assert_numpy_array_equal(result, result_single)
  1150. def compare_local_to_utc(tz_didx, utc_didx):
  1151. f = lambda x: tslib.tz_convert_single(x, tz_didx.tz, 'UTC')
  1152. result = tslib.tz_convert(utc_didx.asi8, tz_didx.tz, 'UTC')
  1153. result_single = np.vectorize(f)(utc_didx.asi8)
  1154. self.assert_numpy_array_equal(result, result_single)
  1155. for tz in ['UTC', 'Asia/Tokyo', 'US/Eastern', 'Europe/Moscow']:
  1156. # US: 2014-03-09 - 2014-11-11
  1157. # MOSCOW: 2014-10-26 / 2014-12-31
  1158. tz_didx = date_range('2014-03-01', '2015-01-10', freq='H', tz=tz)
  1159. utc_didx = date_range('2014-03-01', '2015-01-10', freq='H')
  1160. compare_utc_to_local(tz_didx, utc_didx)
  1161. # local tz to UTC can be differ in hourly (or higher) freqs because
  1162. # of DST
  1163. compare_local_to_utc(tz_didx, utc_didx)
  1164. tz_didx = date_range('2000-01-01', '2020-01-01', freq='D', tz=tz)
  1165. utc_didx = date_range('2000-01-01', '2020-01-01', freq='D')
  1166. compare_utc_to_local(tz_didx, utc_didx)
  1167. compare_local_to_utc(tz_didx, utc_didx)
  1168. tz_didx = date_range('2000-01-01', '2100-01-01', freq='A', tz=tz)
  1169. utc_didx = date_range('2000-01-01', '2100-01-01', freq='A')
  1170. compare_utc_to_local(tz_didx, utc_didx)
  1171. compare_local_to_utc(tz_didx, utc_didx)
  1172. # Check empty array
  1173. result = tslib.tz_convert(np.array([], dtype=np.int64),
  1174. tslib.maybe_get_tz('US/Eastern'),
  1175. tslib.maybe_get_tz('Asia/Tokyo'))
  1176. self.assert_numpy_array_equal(result, np.array([], dtype=np.int64))
  1177. # Check all-NaT array
  1178. result = tslib.tz_convert(np.array([tslib.iNaT], dtype=np.int64),
  1179. tslib.maybe_get_tz('US/Eastern'),
  1180. tslib.maybe_get_tz('Asia/Tokyo'))
  1181. self.assert_numpy_array_equal(result, np.array(
  1182. [tslib.iNaT], dtype=np.int64))
  1183. def test_shift_months(self):
  1184. s = DatetimeIndex([Timestamp('2000-01-05 00:15:00'), Timestamp(
  1185. '2000-01-31 00:23:00'), Timestamp('2000-01-01'), Timestamp(
  1186. '2000-02-29'), Timestamp('2000-12-31')])
  1187. for years in [-1, 0, 1]:
  1188. for months in [-2, 0, 2]:
  1189. actual = DatetimeIndex(tslib.shift_months(s.asi8, years * 12 +
  1190. months))
  1191. expected = DatetimeIndex([x + offsets.DateOffset(
  1192. years=years, months=months) for x in s])
  1193. tm.assert_index_equal(actual, expected)
  1194. def test_round(self):
  1195. stamp = Timestamp('2000-01-05 05:09:15.13')
  1196. def _check_round(freq, expected):
  1197. result = stamp.round(freq=freq)
  1198. self.assertEqual(result, expected)
  1199. for freq, expected in [('D', Timestamp('2000-01-05 00:00:00')),
  1200. ('H', Timestamp('2000-01-05 05:00:00')),
  1201. ('S', Timestamp('2000-01-05 05:09:15'))]:
  1202. _check_round(freq, expected)
  1203. msg = pd.tseries.frequencies._INVALID_FREQ_ERROR
  1204. with self.assertRaisesRegexp(ValueError, msg):
  1205. stamp.round('foo')
  1206. class TestTimestampOps(tm.TestCase):
  1207. def test_timestamp_and_datetime(self):
  1208. self.assertEqual((Timestamp(datetime.datetime(
  1209. 2013, 10, 13)) - datetime.datetime(2013, 10, 12)).days, 1)
  1210. self.assertEqual((datetime.datetime(2013, 10, 12) -
  1211. Timestamp(datetime.datetime(2013, 10, 13))).days, -1)
  1212. def test_timestamp_and_series(self):
  1213. timestamp_series = Series(date_range('2014-03-17', periods=2, freq='D',
  1214. tz='US/Eastern'))
  1215. first_timestamp = timestamp_series[0]
  1216. delta_series = Series([np.timedelta64(0, 'D'), np.timedelta64(1, 'D')])
  1217. assert_series_equal(timestamp_series - first_timestamp, delta_series)
  1218. assert_series_equal(first_timestamp - timestamp_series, -delta_series)
  1219. def test_addition_subtraction_types(self):
  1220. # Assert on the types resulting from Timestamp +/- various date/time
  1221. # objects
  1222. datetime_instance = datetime.datetime(2014, 3, 4)
  1223. timedelta_instance = datetime.timedelta(seconds=1)
  1224. # build a timestamp with a frequency, since then it supports
  1225. # addition/subtraction of integers
  1226. timestamp_instance = date_range(datetime_instance, periods=1,
  1227. freq='D')[0]
  1228. self.assertEqual(type(timestamp_instance + 1), Timestamp)
  1229. self.assertEqual(type(timestamp_instance - 1), Timestamp)
  1230. # Timestamp + datetime not supported, though subtraction is supported
  1231. # and yields timedelta more tests in tseries/base/tests/test_base.py
  1232. self.assertEqual(
  1233. type(timestamp_instance - datetime_instance), Timedelta)
  1234. self.assertEqual(
  1235. type(timestamp_instance + timedelta_instance), Timestamp)
  1236. self.assertEqual(
  1237. type(timestamp_instance - timedelta_instance), Timestamp)
  1238. # Timestamp +/- datetime64 not supported, so not tested (could possibly
  1239. # assert error raised?)
  1240. timedelta64_instance = np.timedelta64(1, 'D')
  1241. self.assertEqual(
  1242. type(timestamp_instance + timedelta64_instance), Timestamp)
  1243. self.assertEqual(
  1244. type(timestamp_instance - timedelta64_instance), Timestamp)
  1245. def test_addition_subtraction_preserve_frequency(self):
  1246. timestamp_instance = date_range('2014-03-05', periods=1, freq='D')[0]
  1247. timedelta_instance = datetime.timedelta(days=1)
  1248. original_freq = timestamp_instance.freq
  1249. self.assertEqual((timestamp_instance + 1).freq, original_freq)
  1250. self.assertEqual((timestamp_instance - 1).freq, original_freq)
  1251. self.assertEqual(
  1252. (timestamp_instance + timedelta_instance).freq, original_freq)
  1253. self.assertEqual(
  1254. (timestamp_instance - timedelta_instance).freq, original_freq)
  1255. timedelta64_instance = np.timedelta64(1, 'D')
  1256. self.assertEqual(
  1257. (timestamp_instance + timedelta64_instance).freq, original_freq)
  1258. self.assertEqual(
  1259. (timestamp_instance - timedelta64_instance).freq, original_freq)
  1260. def test_resolution(self):
  1261. for freq, expected in zip(['A', 'Q', 'M', 'D', 'H', 'T',
  1262. 'S', 'L', 'U'],
  1263. [D_RESO, D_RESO,
  1264. D_RESO, D_RESO,
  1265. H_RESO, T_RESO,
  1266. S_RESO, MS_RESO,
  1267. US_RESO]):
  1268. for tz in [None, 'Asia/Tokyo', 'US/Eastern',
  1269. 'dateutil/US/Eastern']:
  1270. idx = date_range(start='2013-04-01', periods=30, freq=freq,
  1271. tz=tz)
  1272. result = period.resolution(idx.asi8, idx.tz)
  1273. self.assertEqual(result, expected)
  1274. if __name__ == '__main__':
  1275. nose.runmodule(argv=[__file__, '-vvs', '-x', '--pdb', '--pdb-failure'],
  1276. exit=False)