PageRenderTime 51ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/pandas/tseries/tests/test_tslib.py

http://github.com/pydata/pandas
Python | 491 lines | 369 code | 87 blank | 35 comment | 23 complexity | 01918ce76924545bf73f6db06dab6410 MD5 | raw file
Possible License(s): BSD-3-Clause, Apache-2.0
  1. import nose
  2. import numpy as np
  3. from pandas import tslib
  4. import datetime
  5. from pandas.core.api import Timestamp, Series
  6. from pandas.tslib import period_asfreq, period_ordinal
  7. from pandas.tseries.index import date_range
  8. from pandas.tseries.frequencies import get_freq
  9. import pandas.tseries.offsets as offsets
  10. from pandas import _np_version_under1p7
  11. import pandas.util.testing as tm
  12. from pandas.util.testing import assert_series_equal
  13. class TestTimestamp(tm.TestCase):
  14. def test_repr(self):
  15. date = '2014-03-07'
  16. tz = 'US/Eastern'
  17. freq = 'M'
  18. date_only = Timestamp(date)
  19. self.assertIn(date, repr(date_only))
  20. self.assertNotIn(tz, repr(date_only))
  21. self.assertNotIn(freq, repr(date_only))
  22. self.assertEqual(date_only, eval(repr(date_only)))
  23. date_tz = Timestamp(date, tz=tz)
  24. self.assertIn(date, repr(date_tz))
  25. self.assertIn(tz, repr(date_tz))
  26. self.assertNotIn(freq, repr(date_tz))
  27. self.assertEqual(date_tz, eval(repr(date_tz)))
  28. date_freq = Timestamp(date, offset=freq)
  29. self.assertIn(date, repr(date_freq))
  30. self.assertNotIn(tz, repr(date_freq))
  31. self.assertIn(freq, repr(date_freq))
  32. self.assertEqual(date_freq, eval(repr(date_freq)))
  33. date_tz_freq = Timestamp(date, tz=tz, offset=freq)
  34. self.assertIn(date, repr(date_tz_freq))
  35. self.assertIn(tz, repr(date_tz_freq))
  36. self.assertIn(freq, repr(date_tz_freq))
  37. self.assertEqual(date_tz_freq, eval(repr(date_tz_freq)))
  38. # this can cause the tz field to be populated, but it's redundant to information in the datestring
  39. date_with_utc_offset = Timestamp('2014-03-13 00:00:00-0400', tz=None)
  40. self.assertIn('2014-03-13 00:00:00-0400', repr(date_with_utc_offset))
  41. self.assertNotIn('tzoffset', repr(date_with_utc_offset))
  42. self.assertEqual(date_with_utc_offset, eval(repr(date_with_utc_offset)))
  43. def test_bounds_with_different_units(self):
  44. out_of_bounds_dates = (
  45. '1677-09-21',
  46. '2262-04-12',
  47. )
  48. time_units = ('D', 'h', 'm', 's', 'ms', 'us')
  49. for date_string in out_of_bounds_dates:
  50. for unit in time_units:
  51. self.assertRaises(
  52. ValueError,
  53. Timestamp,
  54. np.datetime64(date_string, dtype='M8[%s]' % unit)
  55. )
  56. in_bounds_dates = (
  57. '1677-09-23',
  58. '2262-04-11',
  59. )
  60. for date_string in in_bounds_dates:
  61. for unit in time_units:
  62. Timestamp(
  63. np.datetime64(date_string, dtype='M8[%s]' % unit)
  64. )
  65. def test_tz(self):
  66. t = '2014-02-01 09:00'
  67. ts = Timestamp(t)
  68. local = ts.tz_localize('Asia/Tokyo')
  69. self.assertEqual(local.hour, 9)
  70. self.assertEqual(local, Timestamp(t, tz='Asia/Tokyo'))
  71. conv = local.tz_convert('US/Eastern')
  72. self.assertEqual(conv,
  73. Timestamp('2014-01-31 19:00', tz='US/Eastern'))
  74. self.assertEqual(conv.hour, 19)
  75. # preserves nanosecond
  76. ts = Timestamp(t) + offsets.Nano(5)
  77. local = ts.tz_localize('Asia/Tokyo')
  78. self.assertEqual(local.hour, 9)
  79. self.assertEqual(local.nanosecond, 5)
  80. conv = local.tz_convert('US/Eastern')
  81. self.assertEqual(conv.nanosecond, 5)
  82. self.assertEqual(conv.hour, 19)
  83. def test_barely_oob_dts(self):
  84. one_us = np.timedelta64(1).astype('timedelta64[us]')
  85. # By definition we can't go out of bounds in [ns], so we
  86. # convert the datetime64s to [us] so we can go out of bounds
  87. min_ts_us = np.datetime64(Timestamp.min).astype('M8[us]')
  88. max_ts_us = np.datetime64(Timestamp.max).astype('M8[us]')
  89. # No error for the min/max datetimes
  90. Timestamp(min_ts_us)
  91. Timestamp(max_ts_us)
  92. # One us less than the minimum is an error
  93. self.assertRaises(ValueError, Timestamp, min_ts_us - one_us)
  94. # One us more than the maximum is an error
  95. self.assertRaises(ValueError, Timestamp, max_ts_us + one_us)
  96. class TestDatetimeParsingWrappers(tm.TestCase):
  97. def test_does_not_convert_mixed_integer(self):
  98. bad_date_strings = (
  99. '-50000',
  100. '999',
  101. '123.1234',
  102. 'm',
  103. 'T'
  104. )
  105. for bad_date_string in bad_date_strings:
  106. self.assertFalse(
  107. tslib._does_string_look_like_datetime(bad_date_string)
  108. )
  109. good_date_strings = (
  110. '2012-01-01',
  111. '01/01/2012',
  112. 'Mon Sep 16, 2013',
  113. '01012012',
  114. '0101',
  115. '1-1',
  116. )
  117. for good_date_string in good_date_strings:
  118. self.assertTrue(
  119. tslib._does_string_look_like_datetime(good_date_string)
  120. )
  121. class TestArrayToDatetime(tm.TestCase):
  122. def test_parsing_valid_dates(self):
  123. arr = np.array(['01-01-2013', '01-02-2013'], dtype=object)
  124. self.assert_numpy_array_equal(
  125. tslib.array_to_datetime(arr),
  126. np.array(
  127. [
  128. '2013-01-01T00:00:00.000000000-0000',
  129. '2013-01-02T00:00:00.000000000-0000'
  130. ],
  131. dtype='M8[ns]'
  132. )
  133. )
  134. arr = np.array(['Mon Sep 16 2013', 'Tue Sep 17 2013'], dtype=object)
  135. self.assert_numpy_array_equal(
  136. tslib.array_to_datetime(arr),
  137. np.array(
  138. [
  139. '2013-09-16T00:00:00.000000000-0000',
  140. '2013-09-17T00:00:00.000000000-0000'
  141. ],
  142. dtype='M8[ns]'
  143. )
  144. )
  145. def test_number_looking_strings_not_into_datetime(self):
  146. # #4601
  147. # These strings don't look like datetimes so they shouldn't be
  148. # attempted to be converted
  149. arr = np.array(['-352.737091', '183.575577'], dtype=object)
  150. self.assert_numpy_array_equal(tslib.array_to_datetime(arr), arr)
  151. arr = np.array(['1', '2', '3', '4', '5'], dtype=object)
  152. self.assert_numpy_array_equal(tslib.array_to_datetime(arr), arr)
  153. def test_coercing_dates_outside_of_datetime64_ns_bounds(self):
  154. invalid_dates = [
  155. datetime.date(1000, 1, 1),
  156. datetime.datetime(1000, 1, 1),
  157. '1000-01-01',
  158. 'Jan 1, 1000',
  159. np.datetime64('1000-01-01'),
  160. ]
  161. for invalid_date in invalid_dates:
  162. self.assertRaises(
  163. ValueError,
  164. tslib.array_to_datetime,
  165. np.array([invalid_date], dtype='object'),
  166. coerce=False,
  167. raise_=True,
  168. )
  169. self.assertTrue(
  170. np.array_equal(
  171. tslib.array_to_datetime(
  172. np.array([invalid_date], dtype='object'), coerce=True
  173. ),
  174. np.array([tslib.iNaT], dtype='M8[ns]')
  175. )
  176. )
  177. arr = np.array(['1/1/1000', '1/1/2000'], dtype=object)
  178. self.assert_numpy_array_equal(
  179. tslib.array_to_datetime(arr, coerce=True),
  180. np.array(
  181. [
  182. tslib.iNaT,
  183. '2000-01-01T00:00:00.000000000-0000'
  184. ],
  185. dtype='M8[ns]'
  186. )
  187. )
  188. def test_coerce_of_invalid_datetimes(self):
  189. arr = np.array(['01-01-2013', 'not_a_date', '1'], dtype=object)
  190. # Without coercing, the presence of any invalid dates prevents
  191. # any values from being converted
  192. self.assert_numpy_array_equal(tslib.array_to_datetime(arr), arr)
  193. # With coercing, the invalid dates becomes iNaT
  194. self.assert_numpy_array_equal(
  195. tslib.array_to_datetime(arr, coerce=True),
  196. np.array(
  197. [
  198. '2013-01-01T00:00:00.000000000-0000',
  199. tslib.iNaT,
  200. tslib.iNaT
  201. ],
  202. dtype='M8[ns]'
  203. )
  204. )
  205. def test_parsing_timezone_offsets(self):
  206. # All of these datetime strings with offsets are equivalent
  207. # to the same datetime after the timezone offset is added
  208. dt_strings = [
  209. '01-01-2013 08:00:00+08:00',
  210. '2013-01-01T08:00:00.000000000+0800',
  211. '2012-12-31T16:00:00.000000000-0800',
  212. '12-31-2012 23:00:00-01:00',
  213. ]
  214. expected_output = tslib.array_to_datetime(
  215. np.array(['01-01-2013 00:00:00'], dtype=object)
  216. )
  217. for dt_string in dt_strings:
  218. self.assert_numpy_array_equal(
  219. tslib.array_to_datetime(
  220. np.array([dt_string], dtype=object)
  221. ),
  222. expected_output
  223. )
  224. class TestTimestampNsOperations(tm.TestCase):
  225. def setUp(self):
  226. tm._skip_if_not_numpy17_friendly()
  227. self.timestamp = Timestamp(datetime.datetime.utcnow())
  228. def assert_ns_timedelta(self, modified_timestamp, expected_value):
  229. value = self.timestamp.value
  230. modified_value = modified_timestamp.value
  231. self.assertEqual(modified_value - value, expected_value)
  232. def test_timedelta_ns_arithmetic(self):
  233. self.assert_ns_timedelta(self.timestamp + np.timedelta64(-123, 'ns'), -123)
  234. def test_timedelta_ns_based_arithmetic(self):
  235. self.assert_ns_timedelta(self.timestamp + np.timedelta64(1234567898, 'ns'), 1234567898)
  236. def test_timedelta_us_arithmetic(self):
  237. self.assert_ns_timedelta(self.timestamp + np.timedelta64(-123, 'us'), -123000)
  238. def test_timedelta_ms_arithmetic(self):
  239. time = self.timestamp + np.timedelta64(-123, 'ms')
  240. self.assert_ns_timedelta(time, -123000000)
  241. def test_nanosecond_string_parsing(self):
  242. self.timestamp = Timestamp('2013-05-01 07:15:45.123456789')
  243. self.assertEqual(self.timestamp.value, 1367392545123456000)
  244. def test_nanosecond_timestamp(self):
  245. # GH 7610
  246. expected = 1293840000000000005
  247. t = Timestamp('2011-01-01') + offsets.Nano(5)
  248. self.assertEqual(repr(t), "Timestamp('2011-01-01 00:00:00.000000005')")
  249. self.assertEqual(t.value, expected)
  250. self.assertEqual(t.nanosecond, 5)
  251. t = Timestamp(t)
  252. self.assertEqual(repr(t), "Timestamp('2011-01-01 00:00:00.000000005')")
  253. self.assertEqual(t.value, expected)
  254. self.assertEqual(t.nanosecond, 5)
  255. t = Timestamp(np.datetime64('2011-01-01 00:00:00.000000005Z'))
  256. self.assertEqual(repr(t), "Timestamp('2011-01-01 00:00:00.000000005')")
  257. self.assertEqual(t.value, expected)
  258. self.assertEqual(t.nanosecond, 5)
  259. expected = 1293840000000000010
  260. t = t + offsets.Nano(5)
  261. self.assertEqual(repr(t), "Timestamp('2011-01-01 00:00:00.000000010')")
  262. self.assertEqual(t.value, expected)
  263. self.assertEqual(t.nanosecond, 10)
  264. t = Timestamp(t)
  265. self.assertEqual(repr(t), "Timestamp('2011-01-01 00:00:00.000000010')")
  266. self.assertEqual(t.value, expected)
  267. self.assertEqual(t.nanosecond, 10)
  268. t = Timestamp(np.datetime64('2011-01-01 00:00:00.000000010Z'))
  269. self.assertEqual(repr(t), "Timestamp('2011-01-01 00:00:00.000000010')")
  270. self.assertEqual(t.value, expected)
  271. self.assertEqual(t.nanosecond, 10)
  272. def test_nat_arithmetic(self):
  273. # GH 6873
  274. nat = tslib.NaT
  275. t = Timestamp('2014-01-01')
  276. dt = datetime.datetime(2014, 1, 1)
  277. delta = datetime.timedelta(3600)
  278. # Timestamp / datetime
  279. for (left, right) in [(nat, nat), (nat, t), (dt, nat)]:
  280. # NaT + Timestamp-like should raise TypeError
  281. with tm.assertRaises(TypeError):
  282. left + right
  283. with tm.assertRaises(TypeError):
  284. right + left
  285. # NaT - Timestamp-like (or inverse) returns NaT
  286. self.assertTrue((left - right) is tslib.NaT)
  287. self.assertTrue((right - left) is tslib.NaT)
  288. # timedelta-like
  289. # offsets are tested in test_offsets.py
  290. for (left, right) in [(nat, delta)]:
  291. # NaT + timedelta-like returns NaT
  292. self.assertTrue((left + right) is tslib.NaT)
  293. # timedelta-like + NaT should raise TypeError
  294. with tm.assertRaises(TypeError):
  295. right + left
  296. self.assertTrue((left - right) is tslib.NaT)
  297. with tm.assertRaises(TypeError):
  298. right - left
  299. if _np_version_under1p7:
  300. self.assertEqual(nat + np.timedelta64(1, 'h'), tslib.NaT)
  301. with tm.assertRaises(TypeError):
  302. np.timedelta64(1, 'h') + nat
  303. self.assertEqual(nat - np.timedelta64(1, 'h'), tslib.NaT)
  304. with tm.assertRaises(TypeError):
  305. np.timedelta64(1, 'h') - nat
  306. class TestTslib(tm.TestCase):
  307. def test_intraday_conversion_factors(self):
  308. self.assertEqual(period_asfreq(1, get_freq('D'), get_freq('H'), False), 24)
  309. self.assertEqual(period_asfreq(1, get_freq('D'), get_freq('T'), False), 1440)
  310. self.assertEqual(period_asfreq(1, get_freq('D'), get_freq('S'), False), 86400)
  311. self.assertEqual(period_asfreq(1, get_freq('D'), get_freq('L'), False), 86400000)
  312. self.assertEqual(period_asfreq(1, get_freq('D'), get_freq('U'), False), 86400000000)
  313. self.assertEqual(period_asfreq(1, get_freq('D'), get_freq('N'), False), 86400000000000)
  314. self.assertEqual(period_asfreq(1, get_freq('H'), get_freq('T'), False), 60)
  315. self.assertEqual(period_asfreq(1, get_freq('H'), get_freq('S'), False), 3600)
  316. self.assertEqual(period_asfreq(1, get_freq('H'), get_freq('L'), False), 3600000)
  317. self.assertEqual(period_asfreq(1, get_freq('H'), get_freq('U'), False), 3600000000)
  318. self.assertEqual(period_asfreq(1, get_freq('H'), get_freq('N'), False), 3600000000000)
  319. self.assertEqual(period_asfreq(1, get_freq('T'), get_freq('S'), False), 60)
  320. self.assertEqual(period_asfreq(1, get_freq('T'), get_freq('L'), False), 60000)
  321. self.assertEqual(period_asfreq(1, get_freq('T'), get_freq('U'), False), 60000000)
  322. self.assertEqual(period_asfreq(1, get_freq('T'), get_freq('N'), False), 60000000000)
  323. self.assertEqual(period_asfreq(1, get_freq('S'), get_freq('L'), False), 1000)
  324. self.assertEqual(period_asfreq(1, get_freq('S'), get_freq('U'), False), 1000000)
  325. self.assertEqual(period_asfreq(1, get_freq('S'), get_freq('N'), False), 1000000000)
  326. self.assertEqual(period_asfreq(1, get_freq('L'), get_freq('U'), False), 1000)
  327. self.assertEqual(period_asfreq(1, get_freq('L'), get_freq('N'), False), 1000000)
  328. self.assertEqual(period_asfreq(1, get_freq('U'), get_freq('N'), False), 1000)
  329. def test_period_ordinal_start_values(self):
  330. # information for 1.1.1970
  331. self.assertEqual(0, period_ordinal(1970, 1, 1, 0, 0, 0, 0, 0, get_freq('Y')))
  332. self.assertEqual(0, period_ordinal(1970, 1, 1, 0, 0, 0, 0, 0, get_freq('M')))
  333. self.assertEqual(1, period_ordinal(1970, 1, 1, 0, 0, 0, 0, 0, get_freq('W')))
  334. self.assertEqual(0, period_ordinal(1970, 1, 1, 0, 0, 0, 0, 0, get_freq('D')))
  335. self.assertEqual(0, period_ordinal(1970, 1, 1, 0, 0, 0, 0, 0, get_freq('B')))
  336. def test_period_ordinal_week(self):
  337. self.assertEqual(1, period_ordinal(1970, 1, 4, 0, 0, 0, 0, 0, get_freq('W')))
  338. self.assertEqual(2, period_ordinal(1970, 1, 5, 0, 0, 0, 0, 0, get_freq('W')))
  339. self.assertEqual(2284, period_ordinal(2013, 10, 6, 0, 0, 0, 0, 0, get_freq('W')))
  340. self.assertEqual(2285, period_ordinal(2013, 10, 7, 0, 0, 0, 0, 0, get_freq('W')))
  341. def test_period_ordinal_business_day(self):
  342. # Thursday
  343. self.assertEqual(11415, period_ordinal(2013, 10, 3, 0, 0, 0, 0, 0, get_freq('B')))
  344. # Friday
  345. self.assertEqual(11416, period_ordinal(2013, 10, 4, 0, 0, 0, 0, 0, get_freq('B')))
  346. # Saturday
  347. self.assertEqual(11417, period_ordinal(2013, 10, 5, 0, 0, 0, 0, 0, get_freq('B')))
  348. # Sunday
  349. self.assertEqual(11417, period_ordinal(2013, 10, 6, 0, 0, 0, 0, 0, get_freq('B')))
  350. # Monday
  351. self.assertEqual(11417, period_ordinal(2013, 10, 7, 0, 0, 0, 0, 0, get_freq('B')))
  352. # Tuesday
  353. self.assertEqual(11418, period_ordinal(2013, 10, 8, 0, 0, 0, 0, 0, get_freq('B')))
  354. class TestTimestampOps(tm.TestCase):
  355. def test_timestamp_and_datetime(self):
  356. self.assertEqual((Timestamp(datetime.datetime(2013, 10, 13)) - datetime.datetime(2013, 10, 12)).days, 1)
  357. self.assertEqual((datetime.datetime(2013, 10, 12) - Timestamp(datetime.datetime(2013, 10, 13))).days, -1)
  358. def test_timestamp_and_series(self):
  359. timestamp_series = Series(date_range('2014-03-17', periods=2, freq='D', tz='US/Eastern'))
  360. first_timestamp = timestamp_series[0]
  361. if not _np_version_under1p7:
  362. delta_series = Series([np.timedelta64(0, 'D'), np.timedelta64(1, 'D')])
  363. assert_series_equal(timestamp_series - first_timestamp, delta_series)
  364. assert_series_equal(first_timestamp - timestamp_series, -delta_series)
  365. def test_addition_subtraction_types(self):
  366. # Assert on the types resulting from Timestamp +/- various date/time objects
  367. datetime_instance = datetime.datetime(2014, 3, 4)
  368. timedelta_instance = datetime.timedelta(seconds=1)
  369. # build a timestamp with a frequency, since then it supports addition/subtraction of integers
  370. timestamp_instance = date_range(datetime_instance, periods=1, freq='D')[0]
  371. self.assertEqual(type(timestamp_instance + 1), Timestamp)
  372. self.assertEqual(type(timestamp_instance - 1), Timestamp)
  373. # Timestamp + datetime not supported, though subtraction is supported and yields timedelta
  374. self.assertEqual(type(timestamp_instance - datetime_instance), datetime.timedelta)
  375. self.assertEqual(type(timestamp_instance + timedelta_instance), Timestamp)
  376. self.assertEqual(type(timestamp_instance - timedelta_instance), Timestamp)
  377. if not _np_version_under1p7:
  378. # Timestamp +/- datetime64 not supported, so not tested (could possibly assert error raised?)
  379. timedelta64_instance = np.timedelta64(1, 'D')
  380. self.assertEqual(type(timestamp_instance + timedelta64_instance), Timestamp)
  381. self.assertEqual(type(timestamp_instance - timedelta64_instance), Timestamp)
  382. def test_addition_subtraction_preserve_frequency(self):
  383. timestamp_instance = date_range('2014-03-05', periods=1, freq='D')[0]
  384. timedelta_instance = datetime.timedelta(days=1)
  385. original_freq = timestamp_instance.freq
  386. self.assertEqual((timestamp_instance + 1).freq, original_freq)
  387. self.assertEqual((timestamp_instance - 1).freq, original_freq)
  388. self.assertEqual((timestamp_instance + timedelta_instance).freq, original_freq)
  389. self.assertEqual((timestamp_instance - timedelta_instance).freq, original_freq)
  390. if not _np_version_under1p7:
  391. timedelta64_instance = np.timedelta64(1, 'D')
  392. self.assertEqual((timestamp_instance + timedelta64_instance).freq, original_freq)
  393. self.assertEqual((timestamp_instance - timedelta64_instance).freq, original_freq)
  394. def test_resolution(self):
  395. for freq, expected in zip(['A', 'Q', 'M', 'D', 'H', 'T', 'S', 'L', 'U'],
  396. [tslib.D_RESO, tslib.D_RESO, tslib.D_RESO, tslib.D_RESO,
  397. tslib.H_RESO, tslib.T_RESO,tslib.S_RESO, tslib.MS_RESO, tslib.US_RESO]):
  398. for tz in [None, 'Asia/Tokyo', 'US/Eastern']:
  399. idx = date_range(start='2013-04-01', periods=30, freq=freq, tz=tz)
  400. result = tslib.resolution(idx.asi8, idx.tz)
  401. self.assertEqual(result, expected)
  402. if __name__ == '__main__':
  403. nose.runmodule(argv=[__file__, '-vvs', '-x', '--pdb', '--pdb-failure'],
  404. exit=False)