PageRenderTime 82ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 1ms

/pandas/tseries/tests/test_offsets.py

http://github.com/wesm/pandas
Python | 4923 lines | 3895 code | 871 blank | 157 comment | 231 complexity | 2ab5f86d3cceca3f0ae7857b00894086 MD5 | raw file
Possible License(s): BSD-3-Clause, Apache-2.0

Large files files are truncated, but you can click here to view the full file

  1. import os
  2. from datetime import date, datetime, timedelta
  3. from dateutil.relativedelta import relativedelta
  4. from pandas.compat import range, iteritems
  5. from pandas import compat
  6. import nose
  7. from nose.tools import assert_raises
  8. import numpy as np
  9. from pandas.compat.numpy import np_datetime64_compat
  10. from pandas.core.datetools import (bday, BDay, CDay, BQuarterEnd, BMonthEnd,
  11. BusinessHour, CustomBusinessHour,
  12. CBMonthEnd, CBMonthBegin, BYearEnd,
  13. MonthEnd, MonthBegin, SemiMonthBegin,
  14. SemiMonthEnd, BYearBegin, QuarterBegin,
  15. BQuarterBegin, BMonthBegin, DateOffset,
  16. Week, YearBegin, YearEnd, Hour, Minute,
  17. Second, Day, Micro, Milli, Nano, Easter,
  18. WeekOfMonth, format, ole2datetime,
  19. QuarterEnd, to_datetime, normalize_date,
  20. get_offset, get_standard_freq)
  21. from pandas.core.series import Series
  22. from pandas.tseries.frequencies import (_offset_map, get_freq_code,
  23. _get_freq_str, _INVALID_FREQ_ERROR)
  24. from pandas.tseries.index import _to_m8, DatetimeIndex, _daterange_cache
  25. from pandas.tseries.tools import parse_time_string, DateParseError
  26. import pandas.tseries.offsets as offsets
  27. from pandas.io.pickle import read_pickle
  28. from pandas.tslib import NaT, Timestamp, Timedelta
  29. import pandas.tslib as tslib
  30. from pandas.util.testing import assertRaisesRegexp
  31. import pandas.util.testing as tm
  32. from pandas.tseries.offsets import BusinessMonthEnd, CacheableOffset, \
  33. LastWeekOfMonth, FY5253, FY5253Quarter, WeekDay
  34. from pandas.tseries.holiday import USFederalHolidayCalendar
  35. _multiprocess_can_split_ = True
  36. def test_monthrange():
  37. import calendar
  38. for y in range(2000, 2013):
  39. for m in range(1, 13):
  40. assert tslib.monthrange(y, m) == calendar.monthrange(y, m)
  41. ####
  42. # Misc function tests
  43. ####
  44. def test_format():
  45. actual = format(datetime(2008, 1, 15))
  46. assert actual == '20080115'
  47. def test_ole2datetime():
  48. actual = ole2datetime(60000)
  49. assert actual == datetime(2064, 4, 8)
  50. assert_raises(ValueError, ole2datetime, 60)
  51. def test_to_datetime1():
  52. actual = to_datetime(datetime(2008, 1, 15))
  53. assert actual == datetime(2008, 1, 15)
  54. actual = to_datetime('20080115')
  55. assert actual == datetime(2008, 1, 15)
  56. # unparseable
  57. s = 'Month 1, 1999'
  58. assert to_datetime(s, errors='ignore') == s
  59. def test_normalize_date():
  60. actual = normalize_date(datetime(2007, 10, 1, 1, 12, 5, 10))
  61. assert actual == datetime(2007, 10, 1)
  62. def test_to_m8():
  63. valb = datetime(2007, 10, 1)
  64. valu = _to_m8(valb)
  65. tm.assertIsInstance(valu, np.datetime64)
  66. # assert valu == np.datetime64(datetime(2007,10,1))
  67. # def test_datetime64_box():
  68. # valu = np.datetime64(datetime(2007,10,1))
  69. # valb = _dt_box(valu)
  70. # assert type(valb) == datetime
  71. # assert valb == datetime(2007,10,1)
  72. #####
  73. # DateOffset Tests
  74. #####
  75. class Base(tm.TestCase):
  76. _offset = None
  77. _offset_types = [getattr(offsets, o) for o in offsets.__all__]
  78. timezones = [None, 'UTC', 'Asia/Tokyo', 'US/Eastern',
  79. 'dateutil/Asia/Tokyo', 'dateutil/US/Pacific']
  80. @property
  81. def offset_types(self):
  82. return self._offset_types
  83. def _get_offset(self, klass, value=1, normalize=False):
  84. # create instance from offset class
  85. if klass is FY5253 or klass is FY5253Quarter:
  86. klass = klass(n=value, startingMonth=1, weekday=1,
  87. qtr_with_extra_week=1, variation='last',
  88. normalize=normalize)
  89. elif klass is LastWeekOfMonth:
  90. klass = klass(n=value, weekday=5, normalize=normalize)
  91. elif klass is WeekOfMonth:
  92. klass = klass(n=value, week=1, weekday=5, normalize=normalize)
  93. elif klass is Week:
  94. klass = klass(n=value, weekday=5, normalize=normalize)
  95. elif klass is DateOffset:
  96. klass = klass(days=value, normalize=normalize)
  97. else:
  98. try:
  99. klass = klass(value, normalize=normalize)
  100. except:
  101. klass = klass(normalize=normalize)
  102. return klass
  103. def test_apply_out_of_range(self):
  104. if self._offset is None:
  105. return
  106. # try to create an out-of-bounds result timestamp; if we can't create
  107. # the offset skip
  108. try:
  109. if self._offset in (BusinessHour, CustomBusinessHour):
  110. # Using 10000 in BusinessHour fails in tz check because of DST
  111. # difference
  112. offset = self._get_offset(self._offset, value=100000)
  113. else:
  114. offset = self._get_offset(self._offset, value=10000)
  115. result = Timestamp('20080101') + offset
  116. self.assertIsInstance(result, datetime)
  117. self.assertIsNone(result.tzinfo)
  118. tm._skip_if_no_pytz()
  119. tm._skip_if_no_dateutil()
  120. # Check tz is preserved
  121. for tz in self.timezones:
  122. t = Timestamp('20080101', tz=tz)
  123. result = t + offset
  124. self.assertIsInstance(result, datetime)
  125. self.assertEqual(t.tzinfo, result.tzinfo)
  126. except (tslib.OutOfBoundsDatetime):
  127. raise
  128. except (ValueError, KeyError) as e:
  129. raise nose.SkipTest(
  130. "cannot create out_of_range offset: {0} {1}".format(
  131. str(self).split('.')[-1], e))
  132. class TestCommon(Base):
  133. def setUp(self):
  134. # exected value created by Base._get_offset
  135. # are applied to 2011/01/01 09:00 (Saturday)
  136. # used for .apply and .rollforward
  137. self.expecteds = {'Day': Timestamp('2011-01-02 09:00:00'),
  138. 'DateOffset': Timestamp('2011-01-02 09:00:00'),
  139. 'BusinessDay': Timestamp('2011-01-03 09:00:00'),
  140. 'CustomBusinessDay':
  141. Timestamp('2011-01-03 09:00:00'),
  142. 'CustomBusinessMonthEnd':
  143. Timestamp('2011-01-31 09:00:00'),
  144. 'CustomBusinessMonthBegin':
  145. Timestamp('2011-01-03 09:00:00'),
  146. 'MonthBegin': Timestamp('2011-02-01 09:00:00'),
  147. 'BusinessMonthBegin':
  148. Timestamp('2011-01-03 09:00:00'),
  149. 'MonthEnd': Timestamp('2011-01-31 09:00:00'),
  150. 'SemiMonthEnd': Timestamp('2011-01-15 09:00:00'),
  151. 'SemiMonthBegin': Timestamp('2011-01-15 09:00:00'),
  152. 'BusinessMonthEnd': Timestamp('2011-01-31 09:00:00'),
  153. 'YearBegin': Timestamp('2012-01-01 09:00:00'),
  154. 'BYearBegin': Timestamp('2011-01-03 09:00:00'),
  155. 'YearEnd': Timestamp('2011-12-31 09:00:00'),
  156. 'BYearEnd': Timestamp('2011-12-30 09:00:00'),
  157. 'QuarterBegin': Timestamp('2011-03-01 09:00:00'),
  158. 'BQuarterBegin': Timestamp('2011-03-01 09:00:00'),
  159. 'QuarterEnd': Timestamp('2011-03-31 09:00:00'),
  160. 'BQuarterEnd': Timestamp('2011-03-31 09:00:00'),
  161. 'BusinessHour': Timestamp('2011-01-03 10:00:00'),
  162. 'CustomBusinessHour':
  163. Timestamp('2011-01-03 10:00:00'),
  164. 'WeekOfMonth': Timestamp('2011-01-08 09:00:00'),
  165. 'LastWeekOfMonth': Timestamp('2011-01-29 09:00:00'),
  166. 'FY5253Quarter': Timestamp('2011-01-25 09:00:00'),
  167. 'FY5253': Timestamp('2011-01-25 09:00:00'),
  168. 'Week': Timestamp('2011-01-08 09:00:00'),
  169. 'Easter': Timestamp('2011-04-24 09:00:00'),
  170. 'Hour': Timestamp('2011-01-01 10:00:00'),
  171. 'Minute': Timestamp('2011-01-01 09:01:00'),
  172. 'Second': Timestamp('2011-01-01 09:00:01'),
  173. 'Milli': Timestamp('2011-01-01 09:00:00.001000'),
  174. 'Micro': Timestamp('2011-01-01 09:00:00.000001'),
  175. 'Nano': Timestamp(np_datetime64_compat(
  176. '2011-01-01T09:00:00.000000001Z'))}
  177. def test_return_type(self):
  178. for offset in self.offset_types:
  179. offset = self._get_offset(offset)
  180. # make sure that we are returning a Timestamp
  181. result = Timestamp('20080101') + offset
  182. self.assertIsInstance(result, Timestamp)
  183. # make sure that we are returning NaT
  184. self.assertTrue(NaT + offset is NaT)
  185. self.assertTrue(offset + NaT is NaT)
  186. self.assertTrue(NaT - offset is NaT)
  187. self.assertTrue((-offset).apply(NaT) is NaT)
  188. def test_offset_n(self):
  189. for offset_klass in self.offset_types:
  190. offset = self._get_offset(offset_klass)
  191. self.assertEqual(offset.n, 1)
  192. neg_offset = offset * -1
  193. self.assertEqual(neg_offset.n, -1)
  194. mul_offset = offset * 3
  195. self.assertEqual(mul_offset.n, 3)
  196. def test_offset_freqstr(self):
  197. for offset_klass in self.offset_types:
  198. offset = self._get_offset(offset_klass)
  199. freqstr = offset.freqstr
  200. if freqstr not in ('<Easter>',
  201. "<DateOffset: kwds={'days': 1}>",
  202. 'LWOM-SAT', ):
  203. code = get_offset(freqstr)
  204. self.assertEqual(offset.rule_code, code)
  205. def _check_offsetfunc_works(self, offset, funcname, dt, expected,
  206. normalize=False):
  207. offset_s = self._get_offset(offset, normalize=normalize)
  208. func = getattr(offset_s, funcname)
  209. result = func(dt)
  210. self.assertTrue(isinstance(result, Timestamp))
  211. self.assertEqual(result, expected)
  212. result = func(Timestamp(dt))
  213. self.assertTrue(isinstance(result, Timestamp))
  214. self.assertEqual(result, expected)
  215. # test nano second is preserved
  216. result = func(Timestamp(dt) + Nano(5))
  217. self.assertTrue(isinstance(result, Timestamp))
  218. if normalize is False:
  219. self.assertEqual(result, expected + Nano(5))
  220. else:
  221. self.assertEqual(result, expected)
  222. if isinstance(dt, np.datetime64):
  223. # test tz when input is datetime or Timestamp
  224. return
  225. tm._skip_if_no_pytz()
  226. tm._skip_if_no_dateutil()
  227. for tz in self.timezones:
  228. expected_localize = expected.tz_localize(tz)
  229. tz_obj = tslib.maybe_get_tz(tz)
  230. dt_tz = tslib._localize_pydatetime(dt, tz_obj)
  231. result = func(dt_tz)
  232. self.assertTrue(isinstance(result, Timestamp))
  233. self.assertEqual(result, expected_localize)
  234. result = func(Timestamp(dt, tz=tz))
  235. self.assertTrue(isinstance(result, Timestamp))
  236. self.assertEqual(result, expected_localize)
  237. # test nano second is preserved
  238. result = func(Timestamp(dt, tz=tz) + Nano(5))
  239. self.assertTrue(isinstance(result, Timestamp))
  240. if normalize is False:
  241. self.assertEqual(result, expected_localize + Nano(5))
  242. else:
  243. self.assertEqual(result, expected_localize)
  244. def test_apply(self):
  245. sdt = datetime(2011, 1, 1, 9, 0)
  246. ndt = np_datetime64_compat('2011-01-01 09:00Z')
  247. for offset in self.offset_types:
  248. for dt in [sdt, ndt]:
  249. expected = self.expecteds[offset.__name__]
  250. self._check_offsetfunc_works(offset, 'apply', dt, expected)
  251. expected = Timestamp(expected.date())
  252. self._check_offsetfunc_works(offset, 'apply', dt, expected,
  253. normalize=True)
  254. def test_rollforward(self):
  255. expecteds = self.expecteds.copy()
  256. # result will not be changed if the target is on the offset
  257. no_changes = ['Day', 'MonthBegin', 'SemiMonthBegin', 'YearBegin',
  258. 'Week', 'Hour', 'Minute', 'Second', 'Milli', 'Micro',
  259. 'Nano', 'DateOffset']
  260. for n in no_changes:
  261. expecteds[n] = Timestamp('2011/01/01 09:00')
  262. expecteds['BusinessHour'] = Timestamp('2011-01-03 09:00:00')
  263. expecteds['CustomBusinessHour'] = Timestamp('2011-01-03 09:00:00')
  264. # but be changed when normalize=True
  265. norm_expected = expecteds.copy()
  266. for k in norm_expected:
  267. norm_expected[k] = Timestamp(norm_expected[k].date())
  268. normalized = {'Day': Timestamp('2011-01-02 00:00:00'),
  269. 'DateOffset': Timestamp('2011-01-02 00:00:00'),
  270. 'MonthBegin': Timestamp('2011-02-01 00:00:00'),
  271. 'SemiMonthBegin': Timestamp('2011-01-15 00:00:00'),
  272. 'YearBegin': Timestamp('2012-01-01 00:00:00'),
  273. 'Week': Timestamp('2011-01-08 00:00:00'),
  274. 'Hour': Timestamp('2011-01-01 00:00:00'),
  275. 'Minute': Timestamp('2011-01-01 00:00:00'),
  276. 'Second': Timestamp('2011-01-01 00:00:00'),
  277. 'Milli': Timestamp('2011-01-01 00:00:00'),
  278. 'Micro': Timestamp('2011-01-01 00:00:00')}
  279. norm_expected.update(normalized)
  280. sdt = datetime(2011, 1, 1, 9, 0)
  281. ndt = np_datetime64_compat('2011-01-01 09:00Z')
  282. for offset in self.offset_types:
  283. for dt in [sdt, ndt]:
  284. expected = expecteds[offset.__name__]
  285. self._check_offsetfunc_works(offset, 'rollforward', dt,
  286. expected)
  287. expected = norm_expected[offset.__name__]
  288. self._check_offsetfunc_works(offset, 'rollforward', dt,
  289. expected, normalize=True)
  290. def test_rollback(self):
  291. expecteds = {'BusinessDay': Timestamp('2010-12-31 09:00:00'),
  292. 'CustomBusinessDay': Timestamp('2010-12-31 09:00:00'),
  293. 'CustomBusinessMonthEnd':
  294. Timestamp('2010-12-31 09:00:00'),
  295. 'CustomBusinessMonthBegin':
  296. Timestamp('2010-12-01 09:00:00'),
  297. 'BusinessMonthBegin': Timestamp('2010-12-01 09:00:00'),
  298. 'MonthEnd': Timestamp('2010-12-31 09:00:00'),
  299. 'SemiMonthEnd': Timestamp('2010-12-31 09:00:00'),
  300. 'BusinessMonthEnd': Timestamp('2010-12-31 09:00:00'),
  301. 'BYearBegin': Timestamp('2010-01-01 09:00:00'),
  302. 'YearEnd': Timestamp('2010-12-31 09:00:00'),
  303. 'BYearEnd': Timestamp('2010-12-31 09:00:00'),
  304. 'QuarterBegin': Timestamp('2010-12-01 09:00:00'),
  305. 'BQuarterBegin': Timestamp('2010-12-01 09:00:00'),
  306. 'QuarterEnd': Timestamp('2010-12-31 09:00:00'),
  307. 'BQuarterEnd': Timestamp('2010-12-31 09:00:00'),
  308. 'BusinessHour': Timestamp('2010-12-31 17:00:00'),
  309. 'CustomBusinessHour': Timestamp('2010-12-31 17:00:00'),
  310. 'WeekOfMonth': Timestamp('2010-12-11 09:00:00'),
  311. 'LastWeekOfMonth': Timestamp('2010-12-25 09:00:00'),
  312. 'FY5253Quarter': Timestamp('2010-10-26 09:00:00'),
  313. 'FY5253': Timestamp('2010-01-26 09:00:00'),
  314. 'Easter': Timestamp('2010-04-04 09:00:00')}
  315. # result will not be changed if the target is on the offset
  316. for n in ['Day', 'MonthBegin', 'SemiMonthBegin', 'YearBegin', 'Week',
  317. 'Hour', 'Minute', 'Second', 'Milli', 'Micro', 'Nano',
  318. 'DateOffset']:
  319. expecteds[n] = Timestamp('2011/01/01 09:00')
  320. # but be changed when normalize=True
  321. norm_expected = expecteds.copy()
  322. for k in norm_expected:
  323. norm_expected[k] = Timestamp(norm_expected[k].date())
  324. normalized = {'Day': Timestamp('2010-12-31 00:00:00'),
  325. 'DateOffset': Timestamp('2010-12-31 00:00:00'),
  326. 'MonthBegin': Timestamp('2010-12-01 00:00:00'),
  327. 'SemiMonthBegin': Timestamp('2010-12-15 00:00:00'),
  328. 'YearBegin': Timestamp('2010-01-01 00:00:00'),
  329. 'Week': Timestamp('2010-12-25 00:00:00'),
  330. 'Hour': Timestamp('2011-01-01 00:00:00'),
  331. 'Minute': Timestamp('2011-01-01 00:00:00'),
  332. 'Second': Timestamp('2011-01-01 00:00:00'),
  333. 'Milli': Timestamp('2011-01-01 00:00:00'),
  334. 'Micro': Timestamp('2011-01-01 00:00:00')}
  335. norm_expected.update(normalized)
  336. sdt = datetime(2011, 1, 1, 9, 0)
  337. ndt = np_datetime64_compat('2011-01-01 09:00Z')
  338. for offset in self.offset_types:
  339. for dt in [sdt, ndt]:
  340. expected = expecteds[offset.__name__]
  341. self._check_offsetfunc_works(offset, 'rollback', dt, expected)
  342. expected = norm_expected[offset.__name__]
  343. self._check_offsetfunc_works(offset, 'rollback', dt, expected,
  344. normalize=True)
  345. def test_onOffset(self):
  346. for offset in self.offset_types:
  347. dt = self.expecteds[offset.__name__]
  348. offset_s = self._get_offset(offset)
  349. self.assertTrue(offset_s.onOffset(dt))
  350. # when normalize=True, onOffset checks time is 00:00:00
  351. offset_n = self._get_offset(offset, normalize=True)
  352. self.assertFalse(offset_n.onOffset(dt))
  353. if offset in (BusinessHour, CustomBusinessHour):
  354. # In default BusinessHour (9:00-17:00), normalized time
  355. # cannot be in business hour range
  356. continue
  357. date = datetime(dt.year, dt.month, dt.day)
  358. self.assertTrue(offset_n.onOffset(date))
  359. def test_add(self):
  360. dt = datetime(2011, 1, 1, 9, 0)
  361. for offset in self.offset_types:
  362. offset_s = self._get_offset(offset)
  363. expected = self.expecteds[offset.__name__]
  364. result_dt = dt + offset_s
  365. result_ts = Timestamp(dt) + offset_s
  366. for result in [result_dt, result_ts]:
  367. self.assertTrue(isinstance(result, Timestamp))
  368. self.assertEqual(result, expected)
  369. tm._skip_if_no_pytz()
  370. for tz in self.timezones:
  371. expected_localize = expected.tz_localize(tz)
  372. result = Timestamp(dt, tz=tz) + offset_s
  373. self.assertTrue(isinstance(result, Timestamp))
  374. self.assertEqual(result, expected_localize)
  375. # normalize=True
  376. offset_s = self._get_offset(offset, normalize=True)
  377. expected = Timestamp(expected.date())
  378. result_dt = dt + offset_s
  379. result_ts = Timestamp(dt) + offset_s
  380. for result in [result_dt, result_ts]:
  381. self.assertTrue(isinstance(result, Timestamp))
  382. self.assertEqual(result, expected)
  383. for tz in self.timezones:
  384. expected_localize = expected.tz_localize(tz)
  385. result = Timestamp(dt, tz=tz) + offset_s
  386. self.assertTrue(isinstance(result, Timestamp))
  387. self.assertEqual(result, expected_localize)
  388. def test_pickle_v0_15_2(self):
  389. offsets = {'DateOffset': DateOffset(years=1),
  390. 'MonthBegin': MonthBegin(1),
  391. 'Day': Day(1),
  392. 'YearBegin': YearBegin(1),
  393. 'Week': Week(1)}
  394. pickle_path = os.path.join(tm.get_data_path(),
  395. 'dateoffset_0_15_2.pickle')
  396. # This code was executed once on v0.15.2 to generate the pickle:
  397. # with open(pickle_path, 'wb') as f: pickle.dump(offsets, f)
  398. #
  399. tm.assert_dict_equal(offsets, read_pickle(pickle_path))
  400. class TestDateOffset(Base):
  401. _multiprocess_can_split_ = True
  402. def setUp(self):
  403. self.d = Timestamp(datetime(2008, 1, 2))
  404. _offset_map.clear()
  405. def test_repr(self):
  406. repr(DateOffset())
  407. repr(DateOffset(2))
  408. repr(2 * DateOffset())
  409. repr(2 * DateOffset(months=2))
  410. def test_mul(self):
  411. assert DateOffset(2) == 2 * DateOffset(1)
  412. assert DateOffset(2) == DateOffset(1) * 2
  413. def test_constructor(self):
  414. assert ((self.d + DateOffset(months=2)) == datetime(2008, 3, 2))
  415. assert ((self.d - DateOffset(months=2)) == datetime(2007, 11, 2))
  416. assert ((self.d + DateOffset(2)) == datetime(2008, 1, 4))
  417. assert not DateOffset(2).isAnchored()
  418. assert DateOffset(1).isAnchored()
  419. d = datetime(2008, 1, 31)
  420. assert ((d + DateOffset(months=1)) == datetime(2008, 2, 29))
  421. def test_copy(self):
  422. assert (DateOffset(months=2).copy() == DateOffset(months=2))
  423. def test_eq(self):
  424. offset1 = DateOffset(days=1)
  425. offset2 = DateOffset(days=365)
  426. self.assertNotEqual(offset1, offset2)
  427. class TestBusinessDay(Base):
  428. _multiprocess_can_split_ = True
  429. _offset = BDay
  430. def setUp(self):
  431. self.d = datetime(2008, 1, 1)
  432. self.offset = BDay()
  433. self.offset2 = BDay(2)
  434. def test_different_normalize_equals(self):
  435. # equivalent in this special case
  436. offset = BDay()
  437. offset2 = BDay()
  438. offset2.normalize = True
  439. self.assertEqual(offset, offset2)
  440. def test_repr(self):
  441. self.assertEqual(repr(self.offset), '<BusinessDay>')
  442. assert repr(self.offset2) == '<2 * BusinessDays>'
  443. expected = '<BusinessDay: offset=datetime.timedelta(1)>'
  444. assert repr(self.offset + timedelta(1)) == expected
  445. def test_with_offset(self):
  446. offset = self.offset + timedelta(hours=2)
  447. assert (self.d + offset) == datetime(2008, 1, 2, 2)
  448. def testEQ(self):
  449. self.assertEqual(self.offset2, self.offset2)
  450. def test_mul(self):
  451. pass
  452. def test_hash(self):
  453. self.assertEqual(hash(self.offset2), hash(self.offset2))
  454. def testCall(self):
  455. self.assertEqual(self.offset2(self.d), datetime(2008, 1, 3))
  456. def testRAdd(self):
  457. self.assertEqual(self.d + self.offset2, self.offset2 + self.d)
  458. def testSub(self):
  459. off = self.offset2
  460. self.assertRaises(Exception, off.__sub__, self.d)
  461. self.assertEqual(2 * off - off, off)
  462. self.assertEqual(self.d - self.offset2, self.d + BDay(-2))
  463. def testRSub(self):
  464. self.assertEqual(self.d - self.offset2, (-self.offset2).apply(self.d))
  465. def testMult1(self):
  466. self.assertEqual(self.d + 10 * self.offset, self.d + BDay(10))
  467. def testMult2(self):
  468. self.assertEqual(self.d + (-5 * BDay(-10)), self.d + BDay(50))
  469. def testRollback1(self):
  470. self.assertEqual(BDay(10).rollback(self.d), self.d)
  471. def testRollback2(self):
  472. self.assertEqual(
  473. BDay(10).rollback(datetime(2008, 1, 5)), datetime(2008, 1, 4))
  474. def testRollforward1(self):
  475. self.assertEqual(BDay(10).rollforward(self.d), self.d)
  476. def testRollforward2(self):
  477. self.assertEqual(
  478. BDay(10).rollforward(datetime(2008, 1, 5)), datetime(2008, 1, 7))
  479. def test_roll_date_object(self):
  480. offset = BDay()
  481. dt = date(2012, 9, 15)
  482. result = offset.rollback(dt)
  483. self.assertEqual(result, datetime(2012, 9, 14))
  484. result = offset.rollforward(dt)
  485. self.assertEqual(result, datetime(2012, 9, 17))
  486. offset = offsets.Day()
  487. result = offset.rollback(dt)
  488. self.assertEqual(result, datetime(2012, 9, 15))
  489. result = offset.rollforward(dt)
  490. self.assertEqual(result, datetime(2012, 9, 15))
  491. def test_onOffset(self):
  492. tests = [(BDay(), datetime(2008, 1, 1), True),
  493. (BDay(), datetime(2008, 1, 5), False)]
  494. for offset, d, expected in tests:
  495. assertOnOffset(offset, d, expected)
  496. def test_apply(self):
  497. tests = []
  498. tests.append((bday, {datetime(2008, 1, 1): datetime(2008, 1, 2),
  499. datetime(2008, 1, 4): datetime(2008, 1, 7),
  500. datetime(2008, 1, 5): datetime(2008, 1, 7),
  501. datetime(2008, 1, 6): datetime(2008, 1, 7),
  502. datetime(2008, 1, 7): datetime(2008, 1, 8)}))
  503. tests.append((2 * bday, {datetime(2008, 1, 1): datetime(2008, 1, 3),
  504. datetime(2008, 1, 4): datetime(2008, 1, 8),
  505. datetime(2008, 1, 5): datetime(2008, 1, 8),
  506. datetime(2008, 1, 6): datetime(2008, 1, 8),
  507. datetime(2008, 1, 7): datetime(2008, 1, 9)}))
  508. tests.append((-bday, {datetime(2008, 1, 1): datetime(2007, 12, 31),
  509. datetime(2008, 1, 4): datetime(2008, 1, 3),
  510. datetime(2008, 1, 5): datetime(2008, 1, 4),
  511. datetime(2008, 1, 6): datetime(2008, 1, 4),
  512. datetime(2008, 1, 7): datetime(2008, 1, 4),
  513. datetime(2008, 1, 8): datetime(2008, 1, 7)}))
  514. tests.append((-2 * bday, {datetime(2008, 1, 1): datetime(2007, 12, 28),
  515. datetime(2008, 1, 4): datetime(2008, 1, 2),
  516. datetime(2008, 1, 5): datetime(2008, 1, 3),
  517. datetime(2008, 1, 6): datetime(2008, 1, 3),
  518. datetime(2008, 1, 7): datetime(2008, 1, 3),
  519. datetime(2008, 1, 8): datetime(2008, 1, 4),
  520. datetime(2008, 1, 9): datetime(2008, 1, 7)}))
  521. tests.append((BDay(0), {datetime(2008, 1, 1): datetime(2008, 1, 1),
  522. datetime(2008, 1, 4): datetime(2008, 1, 4),
  523. datetime(2008, 1, 5): datetime(2008, 1, 7),
  524. datetime(2008, 1, 6): datetime(2008, 1, 7),
  525. datetime(2008, 1, 7): datetime(2008, 1, 7)}))
  526. for offset, cases in tests:
  527. for base, expected in compat.iteritems(cases):
  528. assertEq(offset, base, expected)
  529. def test_apply_large_n(self):
  530. dt = datetime(2012, 10, 23)
  531. result = dt + BDay(10)
  532. self.assertEqual(result, datetime(2012, 11, 6))
  533. result = dt + BDay(100) - BDay(100)
  534. self.assertEqual(result, dt)
  535. off = BDay() * 6
  536. rs = datetime(2012, 1, 1) - off
  537. xp = datetime(2011, 12, 23)
  538. self.assertEqual(rs, xp)
  539. st = datetime(2011, 12, 18)
  540. rs = st + off
  541. xp = datetime(2011, 12, 26)
  542. self.assertEqual(rs, xp)
  543. off = BDay() * 10
  544. rs = datetime(2014, 1, 5) + off # see #5890
  545. xp = datetime(2014, 1, 17)
  546. self.assertEqual(rs, xp)
  547. def test_apply_corner(self):
  548. self.assertRaises(TypeError, BDay().apply, BMonthEnd())
  549. def test_offsets_compare_equal(self):
  550. # root cause of #456
  551. offset1 = BDay()
  552. offset2 = BDay()
  553. self.assertFalse(offset1 != offset2)
  554. class TestBusinessHour(Base):
  555. _multiprocess_can_split_ = True
  556. _offset = BusinessHour
  557. def setUp(self):
  558. self.d = datetime(2014, 7, 1, 10, 00)
  559. self.offset1 = BusinessHour()
  560. self.offset2 = BusinessHour(n=3)
  561. self.offset3 = BusinessHour(n=-1)
  562. self.offset4 = BusinessHour(n=-4)
  563. from datetime import time as dt_time
  564. self.offset5 = BusinessHour(start=dt_time(11, 0), end=dt_time(14, 30))
  565. self.offset6 = BusinessHour(start='20:00', end='05:00')
  566. self.offset7 = BusinessHour(n=-2, start=dt_time(21, 30),
  567. end=dt_time(6, 30))
  568. def test_constructor_errors(self):
  569. from datetime import time as dt_time
  570. with tm.assertRaises(ValueError):
  571. BusinessHour(start=dt_time(11, 0, 5))
  572. with tm.assertRaises(ValueError):
  573. BusinessHour(start='AAA')
  574. with tm.assertRaises(ValueError):
  575. BusinessHour(start='14:00:05')
  576. def test_different_normalize_equals(self):
  577. # equivalent in this special case
  578. offset = self._offset()
  579. offset2 = self._offset()
  580. offset2.normalize = True
  581. self.assertEqual(offset, offset2)
  582. def test_repr(self):
  583. self.assertEqual(repr(self.offset1), '<BusinessHour: BH=09:00-17:00>')
  584. self.assertEqual(repr(self.offset2),
  585. '<3 * BusinessHours: BH=09:00-17:00>')
  586. self.assertEqual(repr(self.offset3),
  587. '<-1 * BusinessHour: BH=09:00-17:00>')
  588. self.assertEqual(repr(self.offset4),
  589. '<-4 * BusinessHours: BH=09:00-17:00>')
  590. self.assertEqual(repr(self.offset5), '<BusinessHour: BH=11:00-14:30>')
  591. self.assertEqual(repr(self.offset6), '<BusinessHour: BH=20:00-05:00>')
  592. self.assertEqual(repr(self.offset7),
  593. '<-2 * BusinessHours: BH=21:30-06:30>')
  594. def test_with_offset(self):
  595. expected = Timestamp('2014-07-01 13:00')
  596. self.assertEqual(self.d + BusinessHour() * 3, expected)
  597. self.assertEqual(self.d + BusinessHour(n=3), expected)
  598. def testEQ(self):
  599. for offset in [self.offset1, self.offset2, self.offset3, self.offset4]:
  600. self.assertEqual(offset, offset)
  601. self.assertNotEqual(BusinessHour(), BusinessHour(-1))
  602. self.assertEqual(BusinessHour(start='09:00'), BusinessHour())
  603. self.assertNotEqual(BusinessHour(start='09:00'),
  604. BusinessHour(start='09:01'))
  605. self.assertNotEqual(BusinessHour(start='09:00', end='17:00'),
  606. BusinessHour(start='17:00', end='09:01'))
  607. def test_hash(self):
  608. for offset in [self.offset1, self.offset2, self.offset3, self.offset4]:
  609. self.assertEqual(hash(offset), hash(offset))
  610. def testCall(self):
  611. self.assertEqual(self.offset1(self.d), datetime(2014, 7, 1, 11))
  612. self.assertEqual(self.offset2(self.d), datetime(2014, 7, 1, 13))
  613. self.assertEqual(self.offset3(self.d), datetime(2014, 6, 30, 17))
  614. self.assertEqual(self.offset4(self.d), datetime(2014, 6, 30, 14))
  615. def testRAdd(self):
  616. self.assertEqual(self.d + self.offset2, self.offset2 + self.d)
  617. def testSub(self):
  618. off = self.offset2
  619. self.assertRaises(Exception, off.__sub__, self.d)
  620. self.assertEqual(2 * off - off, off)
  621. self.assertEqual(self.d - self.offset2, self.d + self._offset(-3))
  622. def testRSub(self):
  623. self.assertEqual(self.d - self.offset2, (-self.offset2).apply(self.d))
  624. def testMult1(self):
  625. self.assertEqual(self.d + 5 * self.offset1, self.d + self._offset(5))
  626. def testMult2(self):
  627. self.assertEqual(self.d + (-3 * self._offset(-2)),
  628. self.d + self._offset(6))
  629. def testRollback1(self):
  630. self.assertEqual(self.offset1.rollback(self.d), self.d)
  631. self.assertEqual(self.offset2.rollback(self.d), self.d)
  632. self.assertEqual(self.offset3.rollback(self.d), self.d)
  633. self.assertEqual(self.offset4.rollback(self.d), self.d)
  634. self.assertEqual(self.offset5.rollback(self.d),
  635. datetime(2014, 6, 30, 14, 30))
  636. self.assertEqual(self.offset6.rollback(
  637. self.d), datetime(2014, 7, 1, 5, 0))
  638. self.assertEqual(self.offset7.rollback(
  639. self.d), datetime(2014, 7, 1, 6, 30))
  640. d = datetime(2014, 7, 1, 0)
  641. self.assertEqual(self.offset1.rollback(d), datetime(2014, 6, 30, 17))
  642. self.assertEqual(self.offset2.rollback(d), datetime(2014, 6, 30, 17))
  643. self.assertEqual(self.offset3.rollback(d), datetime(2014, 6, 30, 17))
  644. self.assertEqual(self.offset4.rollback(d), datetime(2014, 6, 30, 17))
  645. self.assertEqual(self.offset5.rollback(
  646. d), datetime(2014, 6, 30, 14, 30))
  647. self.assertEqual(self.offset6.rollback(d), d)
  648. self.assertEqual(self.offset7.rollback(d), d)
  649. self.assertEqual(self._offset(5).rollback(self.d), self.d)
  650. def testRollback2(self):
  651. self.assertEqual(self._offset(-3)
  652. .rollback(datetime(2014, 7, 5, 15, 0)),
  653. datetime(2014, 7, 4, 17, 0))
  654. def testRollforward1(self):
  655. self.assertEqual(self.offset1.rollforward(self.d), self.d)
  656. self.assertEqual(self.offset2.rollforward(self.d), self.d)
  657. self.assertEqual(self.offset3.rollforward(self.d), self.d)
  658. self.assertEqual(self.offset4.rollforward(self.d), self.d)
  659. self.assertEqual(self.offset5.rollforward(
  660. self.d), datetime(2014, 7, 1, 11, 0))
  661. self.assertEqual(self.offset6.rollforward(
  662. self.d), datetime(2014, 7, 1, 20, 0))
  663. self.assertEqual(self.offset7.rollforward(
  664. self.d), datetime(2014, 7, 1, 21, 30))
  665. d = datetime(2014, 7, 1, 0)
  666. self.assertEqual(self.offset1.rollforward(d), datetime(2014, 7, 1, 9))
  667. self.assertEqual(self.offset2.rollforward(d), datetime(2014, 7, 1, 9))
  668. self.assertEqual(self.offset3.rollforward(d), datetime(2014, 7, 1, 9))
  669. self.assertEqual(self.offset4.rollforward(d), datetime(2014, 7, 1, 9))
  670. self.assertEqual(self.offset5.rollforward(d), datetime(2014, 7, 1, 11))
  671. self.assertEqual(self.offset6.rollforward(d), d)
  672. self.assertEqual(self.offset7.rollforward(d), d)
  673. self.assertEqual(self._offset(5).rollforward(self.d), self.d)
  674. def testRollforward2(self):
  675. self.assertEqual(self._offset(-3)
  676. .rollforward(datetime(2014, 7, 5, 16, 0)),
  677. datetime(2014, 7, 7, 9))
  678. def test_roll_date_object(self):
  679. offset = BusinessHour()
  680. dt = datetime(2014, 7, 6, 15, 0)
  681. result = offset.rollback(dt)
  682. self.assertEqual(result, datetime(2014, 7, 4, 17))
  683. result = offset.rollforward(dt)
  684. self.assertEqual(result, datetime(2014, 7, 7, 9))
  685. def test_normalize(self):
  686. tests = []
  687. tests.append((BusinessHour(normalize=True),
  688. {datetime(2014, 7, 1, 8): datetime(2014, 7, 1),
  689. datetime(2014, 7, 1, 17): datetime(2014, 7, 2),
  690. datetime(2014, 7, 1, 16): datetime(2014, 7, 2),
  691. datetime(2014, 7, 1, 23): datetime(2014, 7, 2),
  692. datetime(2014, 7, 1, 0): datetime(2014, 7, 1),
  693. datetime(2014, 7, 4, 15): datetime(2014, 7, 4),
  694. datetime(2014, 7, 4, 15, 59): datetime(2014, 7, 4),
  695. datetime(2014, 7, 4, 16, 30): datetime(2014, 7, 7),
  696. datetime(2014, 7, 5, 23): datetime(2014, 7, 7),
  697. datetime(2014, 7, 6, 10): datetime(2014, 7, 7)}))
  698. tests.append((BusinessHour(-1, normalize=True),
  699. {datetime(2014, 7, 1, 8): datetime(2014, 6, 30),
  700. datetime(2014, 7, 1, 17): datetime(2014, 7, 1),
  701. datetime(2014, 7, 1, 16): datetime(2014, 7, 1),
  702. datetime(2014, 7, 1, 10): datetime(2014, 6, 30),
  703. datetime(2014, 7, 1, 0): datetime(2014, 6, 30),
  704. datetime(2014, 7, 7, 10): datetime(2014, 7, 4),
  705. datetime(2014, 7, 7, 10, 1): datetime(2014, 7, 7),
  706. datetime(2014, 7, 5, 23): datetime(2014, 7, 4),
  707. datetime(2014, 7, 6, 10): datetime(2014, 7, 4)}))
  708. tests.append((BusinessHour(1, normalize=True, start='17:00',
  709. end='04:00'),
  710. {datetime(2014, 7, 1, 8): datetime(2014, 7, 1),
  711. datetime(2014, 7, 1, 17): datetime(2014, 7, 1),
  712. datetime(2014, 7, 1, 23): datetime(2014, 7, 2),
  713. datetime(2014, 7, 2, 2): datetime(2014, 7, 2),
  714. datetime(2014, 7, 2, 3): datetime(2014, 7, 2),
  715. datetime(2014, 7, 4, 23): datetime(2014, 7, 5),
  716. datetime(2014, 7, 5, 2): datetime(2014, 7, 5),
  717. datetime(2014, 7, 7, 2): datetime(2014, 7, 7),
  718. datetime(2014, 7, 7, 17): datetime(2014, 7, 7)}))
  719. for offset, cases in tests:
  720. for dt, expected in compat.iteritems(cases):
  721. self.assertEqual(offset.apply(dt), expected)
  722. def test_onOffset(self):
  723. tests = []
  724. tests.append((BusinessHour(), {datetime(2014, 7, 1, 9): True,
  725. datetime(2014, 7, 1, 8, 59): False,
  726. datetime(2014, 7, 1, 8): False,
  727. datetime(2014, 7, 1, 17): True,
  728. datetime(2014, 7, 1, 17, 1): False,
  729. datetime(2014, 7, 1, 18): False,
  730. datetime(2014, 7, 5, 9): False,
  731. datetime(2014, 7, 6, 12): False}))
  732. tests.append((BusinessHour(start='10:00', end='15:00'),
  733. {datetime(2014, 7, 1, 9): False,
  734. datetime(2014, 7, 1, 10): True,
  735. datetime(2014, 7, 1, 15): True,
  736. datetime(2014, 7, 1, 15, 1): False,
  737. datetime(2014, 7, 5, 12): False,
  738. datetime(2014, 7, 6, 12): False}))
  739. tests.append((BusinessHour(start='19:00', end='05:00'),
  740. {datetime(2014, 7, 1, 9, 0): False,
  741. datetime(2014, 7, 1, 10, 0): False,
  742. datetime(2014, 7, 1, 15): False,
  743. datetime(2014, 7, 1, 15, 1): False,
  744. datetime(2014, 7, 5, 12, 0): False,
  745. datetime(2014, 7, 6, 12, 0): False,
  746. datetime(2014, 7, 1, 19, 0): True,
  747. datetime(2014, 7, 2, 0, 0): True,
  748. datetime(2014, 7, 4, 23): True,
  749. datetime(2014, 7, 5, 1): True,
  750. datetime(2014, 7, 5, 5, 0): True,
  751. datetime(2014, 7, 6, 23, 0): False,
  752. datetime(2014, 7, 7, 3, 0): False}))
  753. for offset, cases in tests:
  754. for dt, expected in compat.iteritems(cases):
  755. self.assertEqual(offset.onOffset(dt), expected)
  756. def test_opening_time(self):
  757. tests = []
  758. # opening time should be affected by sign of n, not by n's value and
  759. # end
  760. tests.append((
  761. [BusinessHour(), BusinessHour(n=2), BusinessHour(
  762. n=4), BusinessHour(end='10:00'), BusinessHour(n=2, end='4:00'),
  763. BusinessHour(n=4, end='15:00')],
  764. {datetime(2014, 7, 1, 11): (datetime(2014, 7, 2, 9), datetime(
  765. 2014, 7, 1, 9)),
  766. datetime(2014, 7, 1, 18): (datetime(2014, 7, 2, 9), datetime(
  767. 2014, 7, 1, 9)),
  768. datetime(2014, 7, 1, 23): (datetime(2014, 7, 2, 9), datetime(
  769. 2014, 7, 1, 9)),
  770. datetime(2014, 7, 2, 8): (datetime(2014, 7, 2, 9), datetime(
  771. 2014, 7, 1, 9)),
  772. # if timestamp is on opening time, next opening time is
  773. # as it is
  774. datetime(2014, 7, 2, 9): (datetime(2014, 7, 2, 9), datetime(
  775. 2014, 7, 2, 9)),
  776. datetime(2014, 7, 2, 10): (datetime(2014, 7, 3, 9), datetime(
  777. 2014, 7, 2, 9)),
  778. # 2014-07-05 is saturday
  779. datetime(2014, 7, 5, 10): (datetime(2014, 7, 7, 9), datetime(
  780. 2014, 7, 4, 9)),
  781. datetime(2014, 7, 4, 10): (datetime(2014, 7, 7, 9), datetime(
  782. 2014, 7, 4, 9)),
  783. datetime(2014, 7, 4, 23): (datetime(2014, 7, 7, 9), datetime(
  784. 2014, 7, 4, 9)),
  785. datetime(2014, 7, 6, 10): (datetime(2014, 7, 7, 9), datetime(
  786. 2014, 7, 4, 9)),
  787. datetime(2014, 7, 7, 5): (datetime(2014, 7, 7, 9), datetime(
  788. 2014, 7, 4, 9)),
  789. datetime(2014, 7, 7, 9, 1): (datetime(2014, 7, 8, 9), datetime(
  790. 2014, 7, 7, 9))}))
  791. tests.append(([BusinessHour(start='11:15'),
  792. BusinessHour(n=2, start='11:15'),
  793. BusinessHour(n=3, start='11:15'),
  794. BusinessHour(start='11:15', end='10:00'),
  795. BusinessHour(n=2, start='11:15', end='4:00'),
  796. BusinessHour(n=3, start='11:15', end='15:00')],
  797. {datetime(2014, 7, 1, 11): (datetime(
  798. 2014, 7, 1, 11, 15), datetime(2014, 6, 30, 11, 15)),
  799. datetime(2014, 7, 1, 18): (datetime(
  800. 2014, 7, 2, 11, 15), datetime(2014, 7, 1, 11, 15)),
  801. datetime(2014, 7, 1, 23): (datetime(
  802. 2014, 7, 2, 11, 15), datetime(2014, 7, 1, 11, 15)),
  803. datetime(2014, 7, 2, 8): (datetime(2014, 7, 2, 11, 15),
  804. datetime(2014, 7, 1, 11, 15)),
  805. datetime(2014, 7, 2, 9): (datetime(2014, 7, 2, 11, 15),
  806. datetime(2014, 7, 1, 11, 15)),
  807. datetime(2014, 7, 2, 10): (datetime(
  808. 2014, 7, 2, 11, 15), datetime(2014, 7, 1, 11, 15)),
  809. datetime(2014, 7, 2, 11, 15): (datetime(
  810. 2014, 7, 2, 11, 15), datetime(2014, 7, 2, 11, 15)),
  811. datetime(2014, 7, 2, 11, 15, 1): (datetime(
  812. 2014, 7, 3, 11, 15), datetime(2014, 7, 2, 11, 15)),
  813. datetime(2014, 7, 5, 10): (datetime(
  814. 2014, 7, 7, 11, 15), datetime(2014, 7, 4, 11, 15)),
  815. datetime(2014, 7, 4, 10): (datetime(
  816. 2014, 7, 4, 11, 15), datetime(2014, 7, 3, 11, 15)),
  817. datetime(2014, 7, 4, 23): (datetime(
  818. 2014, 7, 7, 11, 15), datetime(2014, 7, 4, 11, 15)),
  819. datetime(2014, 7, 6, 10): (datetime(
  820. 2014, 7, 7, 11, 15), datetime(2014, 7, 4, 11, 15)),
  821. datetime(2014, 7, 7, 5): (datetime(2014, 7, 7, 11, 15),
  822. datetime(2014, 7, 4, 11, 15)),
  823. datetime(2014, 7, 7, 9, 1): (
  824. datetime(2014, 7, 7, 11, 15),
  825. datetime(2014, 7, 4, 11, 15))}))
  826. tests.append(([BusinessHour(-1), BusinessHour(n=-2),
  827. BusinessHour(n=-4),
  828. BusinessHour(n=-1, end='10:00'),
  829. BusinessHour(n=-2, end='4:00'),
  830. BusinessHour(n=-4, end='15:00')],
  831. {datetime(2014, 7, 1, 11): (datetime(2014, 7, 1, 9),
  832. datetime(2014, 7, 2, 9)),
  833. datetime(2014, 7, 1, 18): (datetime(2014, 7, 1, 9),
  834. datetime(2014, 7, 2, 9)),
  835. datetime(2014, 7, 1, 23): (datetime(2014, 7, 1, 9),
  836. datetime(2014, 7, 2, 9)),
  837. datetime(2014, 7, 2, 8): (datetime(2014, 7, 1, 9),
  838. datetime(2014, 7, 2, 9)),
  839. datetime(2014, 7, 2, 9): (datetime(2014, 7, 2, 9),
  840. datetime(2014, 7, 2, 9)),
  841. datetime(2014, 7, 2, 10): (datetime(2014, 7, 2, 9),
  842. datetime(2014, 7, 3, 9)),
  843. datetime(2014, 7, 5, 10): (datetime(2014, 7, 4, 9),
  844. datetime(2014, 7, 7, 9)),
  845. datetime(2014, 7, 4, 10): (datetime(2014, 7, 4, 9),
  846. datetime(2014, 7, 7, 9)),
  847. datetime(2014, 7, 4, 23): (datetime(2014, 7, 4, 9),
  848. datetime(2014, 7, 7, 9)),
  849. datetime(2014, 7, 6, 10): (datetime(2014, 7, 4, 9),
  850. datetime(2014, 7, 7, 9)),
  851. datetime(2014, 7, 7, 5): (datetime(2014, 7, 4, 9),
  852. datetime(2014, 7, 7, 9)),
  853. datetime(2014, 7, 7, 9): (datetime(2014, 7, 7, 9),
  854. datetime(2014, 7, 7, 9)),
  855. datetime(2014, 7, 7, 9, 1): (datetime(2014, 7, 7, 9),
  856. datetime(2014, 7, 8, 9))}))
  857. tests.append(([BusinessHour(start='17:00', end='05:00'),
  858. BusinessHour(n=3, start='17:00', end='03:00')],
  859. {datetime(2014, 7, 1, 11): (datetime(2014, 7, 1, 17),
  860. datetime(2014, 6, 30, 17)),
  861. datetime(2014, 7, 1, 18): (datetime(2014, 7, 2, 17),
  862. datetime(2014, 7, 1, 17)),
  863. datetime(2014, 7, 1, 23): (datetime(2014, 7, 2, 17),
  864. datetime(2014, 7, 1, 17)),
  865. datetime(2014, 7, 2, 8): (datetime(2014, 7, 2, 17),
  866. datetime(2014, 7, 1, 17)),
  867. datetime(2014, 7, 2, 9): (datetime(2014, 7, 2, 17),
  868. datetime(2014, 7, 1, 17)),
  869. datetime(2014, 7, 4, 17): (datetime(2014, 7, 4, 17),
  870. datetime(2014, 7, 4, 17)),
  871. datetime(2014, 7, 5, 10): (datetime(2014, 7, 7, 17),
  872. datetime(2014, 7, 4, 17)),
  873. datetime(2014, 7, 4, 10): (datetime(2014, 7, 4, 17),
  874. datetime(2014, 7, 3, 17)),
  875. datetime(2014, 7, 4, 23): (datetime(2014, 7, 7, 17),
  876. datetime(2014, 7, 4, 17)),
  877. datetime(2014, 7, 6, 10): (datetime(2014, 7, 7, 17),
  878. datetime(2014, 7, 4, 17)),
  879. datetime(2014, 7, 7, 5): (datetime(2014, 7, 7, 17),
  880. datetime(2014, 7, 4, 17)),
  881. datetime(2014, 7, 7, 17, 1): (datetime(
  882. 2014, 7, 8, 17), datetime(2014, 7, 7, 17)), }))
  883. tests.append(([BusinessHour(-1, start='17:00', end='05:00'),
  884. BusinessHour(n=-2, start='17:00', end='03:00')],
  885. {datetime(2014, 7, 1, 11): (datetime(2014, 6, 30, 17),
  886. datetime(2014, 7, 1, 17)),
  887. datetime(2014, 7, 1, 18): (datetime(2014, 7, 1, 17),
  888. datetime(2014, 7, 2, 17)),
  889. datetime(2014, 7, 1, 23): (datetime(2014, 7, 1, 17),
  890. datetime(2014, 7, 2, 17)),
  891. datetime(2014, 7, 2, 8): (datetime(2014, 7, 1, 17),
  892. datetime(2014, 7, 2, 17)),
  893. datetime(2014, 7, 2, 9): (datetime(2014, 7, 1, 17),
  894. datetime(2014, 7, 2, 17)),
  895. datetime(2014, 7, 2, 16, 59): (datetime(
  896. 2014, 7, 1, 17), datetime(2014, 7, 2, 17)),
  897. datetime(2014, 7, 5, 10): (datetime(2014, 7, 4, 17),
  898. datetime(2014, 7, 7, 17)),
  899. datetime(2014, 7, 4, 10): (datetime(2014, 7, 3, 17),
  900. datetime(2014, 7, 4, 17)),
  901. datetime(2014, 7, 4, 23): (datetime(2014, 7, 4, 17),
  902. datetime(2014, 7, 7, 17)),
  903. datetime(2014, 7, 6, 10): (datetime(2014, 7, 4, 17),
  904. datetime(2014, 7, 7, 17)),
  905. datetime(2014, 7, 7, 5): (datetime(2014, 7, 4, 17),
  906. datetime(2014, 7, 7, 17)),
  907. datetime(2014, 7, 7, 18): (datetime(2014, 7, 7, 17),
  908. datetime(2014, 7, 8, 17))}))
  909. for _offsets, cases in tests:
  910. for offset in _offsets:
  911. for dt, (exp_next, exp_prev) in compat.iteritems(cases):
  912. self.assertEqual(offset._next_opening_time(dt), exp_next)
  913. self.assertEqual(offset._prev_opening_time(dt), exp_prev)
  914. def test_apply(self):
  915. tests = []

Large files files are truncated, but you can click here to view the full file