test_month.py 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666
  1. """
  2. Tests for the following offsets:
  3. - SemiMonthBegin
  4. - SemiMonthEnd
  5. - MonthBegin
  6. - MonthEnd
  7. """
  8. from __future__ import annotations
  9. from datetime import datetime
  10. import pytest
  11. from pandas._libs.tslibs import Timestamp
  12. from pandas._libs.tslibs.offsets import (
  13. MonthBegin,
  14. MonthEnd,
  15. SemiMonthBegin,
  16. SemiMonthEnd,
  17. )
  18. from pandas import (
  19. DatetimeIndex,
  20. Series,
  21. _testing as tm,
  22. )
  23. from pandas.tests.tseries.offsets.common import (
  24. assert_is_on_offset,
  25. assert_offset_equal,
  26. )
  27. class TestSemiMonthEnd:
  28. def test_offset_whole_year(self):
  29. dates = (
  30. datetime(2007, 12, 31),
  31. datetime(2008, 1, 15),
  32. datetime(2008, 1, 31),
  33. datetime(2008, 2, 15),
  34. datetime(2008, 2, 29),
  35. datetime(2008, 3, 15),
  36. datetime(2008, 3, 31),
  37. datetime(2008, 4, 15),
  38. datetime(2008, 4, 30),
  39. datetime(2008, 5, 15),
  40. datetime(2008, 5, 31),
  41. datetime(2008, 6, 15),
  42. datetime(2008, 6, 30),
  43. datetime(2008, 7, 15),
  44. datetime(2008, 7, 31),
  45. datetime(2008, 8, 15),
  46. datetime(2008, 8, 31),
  47. datetime(2008, 9, 15),
  48. datetime(2008, 9, 30),
  49. datetime(2008, 10, 15),
  50. datetime(2008, 10, 31),
  51. datetime(2008, 11, 15),
  52. datetime(2008, 11, 30),
  53. datetime(2008, 12, 15),
  54. datetime(2008, 12, 31),
  55. )
  56. for base, exp_date in zip(dates[:-1], dates[1:]):
  57. assert_offset_equal(SemiMonthEnd(), base, exp_date)
  58. # ensure .apply_index works as expected
  59. shift = DatetimeIndex(dates[:-1])
  60. with tm.assert_produces_warning(None):
  61. # GH#22535 check that we don't get a FutureWarning from adding
  62. # an integer array to PeriodIndex
  63. result = SemiMonthEnd() + shift
  64. exp = DatetimeIndex(dates[1:])
  65. tm.assert_index_equal(result, exp)
  66. offset_cases = []
  67. offset_cases.append(
  68. (
  69. SemiMonthEnd(),
  70. {
  71. datetime(2008, 1, 1): datetime(2008, 1, 15),
  72. datetime(2008, 1, 15): datetime(2008, 1, 31),
  73. datetime(2008, 1, 31): datetime(2008, 2, 15),
  74. datetime(2006, 12, 14): datetime(2006, 12, 15),
  75. datetime(2006, 12, 29): datetime(2006, 12, 31),
  76. datetime(2006, 12, 31): datetime(2007, 1, 15),
  77. datetime(2007, 1, 1): datetime(2007, 1, 15),
  78. datetime(2006, 12, 1): datetime(2006, 12, 15),
  79. datetime(2006, 12, 15): datetime(2006, 12, 31),
  80. },
  81. )
  82. )
  83. offset_cases.append(
  84. (
  85. SemiMonthEnd(day_of_month=20),
  86. {
  87. datetime(2008, 1, 1): datetime(2008, 1, 20),
  88. datetime(2008, 1, 15): datetime(2008, 1, 20),
  89. datetime(2008, 1, 21): datetime(2008, 1, 31),
  90. datetime(2008, 1, 31): datetime(2008, 2, 20),
  91. datetime(2006, 12, 14): datetime(2006, 12, 20),
  92. datetime(2006, 12, 29): datetime(2006, 12, 31),
  93. datetime(2006, 12, 31): datetime(2007, 1, 20),
  94. datetime(2007, 1, 1): datetime(2007, 1, 20),
  95. datetime(2006, 12, 1): datetime(2006, 12, 20),
  96. datetime(2006, 12, 15): datetime(2006, 12, 20),
  97. },
  98. )
  99. )
  100. offset_cases.append(
  101. (
  102. SemiMonthEnd(0),
  103. {
  104. datetime(2008, 1, 1): datetime(2008, 1, 15),
  105. datetime(2008, 1, 16): datetime(2008, 1, 31),
  106. datetime(2008, 1, 15): datetime(2008, 1, 15),
  107. datetime(2008, 1, 31): datetime(2008, 1, 31),
  108. datetime(2006, 12, 29): datetime(2006, 12, 31),
  109. datetime(2006, 12, 31): datetime(2006, 12, 31),
  110. datetime(2007, 1, 1): datetime(2007, 1, 15),
  111. },
  112. )
  113. )
  114. offset_cases.append(
  115. (
  116. SemiMonthEnd(0, day_of_month=16),
  117. {
  118. datetime(2008, 1, 1): datetime(2008, 1, 16),
  119. datetime(2008, 1, 16): datetime(2008, 1, 16),
  120. datetime(2008, 1, 15): datetime(2008, 1, 16),
  121. datetime(2008, 1, 31): datetime(2008, 1, 31),
  122. datetime(2006, 12, 29): datetime(2006, 12, 31),
  123. datetime(2006, 12, 31): datetime(2006, 12, 31),
  124. datetime(2007, 1, 1): datetime(2007, 1, 16),
  125. },
  126. )
  127. )
  128. offset_cases.append(
  129. (
  130. SemiMonthEnd(2),
  131. {
  132. datetime(2008, 1, 1): datetime(2008, 1, 31),
  133. datetime(2008, 1, 31): datetime(2008, 2, 29),
  134. datetime(2006, 12, 29): datetime(2007, 1, 15),
  135. datetime(2006, 12, 31): datetime(2007, 1, 31),
  136. datetime(2007, 1, 1): datetime(2007, 1, 31),
  137. datetime(2007, 1, 16): datetime(2007, 2, 15),
  138. datetime(2006, 11, 1): datetime(2006, 11, 30),
  139. },
  140. )
  141. )
  142. offset_cases.append(
  143. (
  144. SemiMonthEnd(-1),
  145. {
  146. datetime(2007, 1, 1): datetime(2006, 12, 31),
  147. datetime(2008, 6, 30): datetime(2008, 6, 15),
  148. datetime(2008, 12, 31): datetime(2008, 12, 15),
  149. datetime(2006, 12, 29): datetime(2006, 12, 15),
  150. datetime(2006, 12, 30): datetime(2006, 12, 15),
  151. datetime(2007, 1, 1): datetime(2006, 12, 31),
  152. },
  153. )
  154. )
  155. offset_cases.append(
  156. (
  157. SemiMonthEnd(-1, day_of_month=4),
  158. {
  159. datetime(2007, 1, 1): datetime(2006, 12, 31),
  160. datetime(2007, 1, 4): datetime(2006, 12, 31),
  161. datetime(2008, 6, 30): datetime(2008, 6, 4),
  162. datetime(2008, 12, 31): datetime(2008, 12, 4),
  163. datetime(2006, 12, 5): datetime(2006, 12, 4),
  164. datetime(2006, 12, 30): datetime(2006, 12, 4),
  165. datetime(2007, 1, 1): datetime(2006, 12, 31),
  166. },
  167. )
  168. )
  169. offset_cases.append(
  170. (
  171. SemiMonthEnd(-2),
  172. {
  173. datetime(2007, 1, 1): datetime(2006, 12, 15),
  174. datetime(2008, 6, 30): datetime(2008, 5, 31),
  175. datetime(2008, 3, 15): datetime(2008, 2, 15),
  176. datetime(2008, 12, 31): datetime(2008, 11, 30),
  177. datetime(2006, 12, 29): datetime(2006, 11, 30),
  178. datetime(2006, 12, 14): datetime(2006, 11, 15),
  179. datetime(2007, 1, 1): datetime(2006, 12, 15),
  180. },
  181. )
  182. )
  183. @pytest.mark.parametrize("case", offset_cases)
  184. def test_offset(self, case):
  185. offset, cases = case
  186. for base, expected in cases.items():
  187. assert_offset_equal(offset, base, expected)
  188. @pytest.mark.parametrize("case", offset_cases)
  189. def test_apply_index(self, case):
  190. # https://github.com/pandas-dev/pandas/issues/34580
  191. offset, cases = case
  192. shift = DatetimeIndex(cases.keys())
  193. exp = DatetimeIndex(cases.values())
  194. with tm.assert_produces_warning(None):
  195. # GH#22535 check that we don't get a FutureWarning from adding
  196. # an integer array to PeriodIndex
  197. result = offset + shift
  198. tm.assert_index_equal(result, exp)
  199. on_offset_cases = [
  200. (datetime(2007, 12, 31), True),
  201. (datetime(2007, 12, 15), True),
  202. (datetime(2007, 12, 14), False),
  203. (datetime(2007, 12, 1), False),
  204. (datetime(2008, 2, 29), True),
  205. ]
  206. @pytest.mark.parametrize("case", on_offset_cases)
  207. def test_is_on_offset(self, case):
  208. dt, expected = case
  209. assert_is_on_offset(SemiMonthEnd(), dt, expected)
  210. @pytest.mark.parametrize("klass", [Series, DatetimeIndex])
  211. def test_vectorized_offset_addition(self, klass):
  212. shift = klass(
  213. [
  214. Timestamp("2000-01-15 00:15:00", tz="US/Central"),
  215. Timestamp("2000-02-15", tz="US/Central"),
  216. ],
  217. name="a",
  218. )
  219. with tm.assert_produces_warning(None):
  220. # GH#22535 check that we don't get a FutureWarning from adding
  221. # an integer array to PeriodIndex
  222. result = shift + SemiMonthEnd()
  223. result2 = SemiMonthEnd() + shift
  224. exp = klass(
  225. [
  226. Timestamp("2000-01-31 00:15:00", tz="US/Central"),
  227. Timestamp("2000-02-29", tz="US/Central"),
  228. ],
  229. name="a",
  230. )
  231. tm.assert_equal(result, exp)
  232. tm.assert_equal(result2, exp)
  233. shift = klass(
  234. [
  235. Timestamp("2000-01-01 00:15:00", tz="US/Central"),
  236. Timestamp("2000-02-01", tz="US/Central"),
  237. ],
  238. name="a",
  239. )
  240. with tm.assert_produces_warning(None):
  241. # GH#22535 check that we don't get a FutureWarning from adding
  242. # an integer array to PeriodIndex
  243. result = shift + SemiMonthEnd()
  244. result2 = SemiMonthEnd() + shift
  245. exp = klass(
  246. [
  247. Timestamp("2000-01-15 00:15:00", tz="US/Central"),
  248. Timestamp("2000-02-15", tz="US/Central"),
  249. ],
  250. name="a",
  251. )
  252. tm.assert_equal(result, exp)
  253. tm.assert_equal(result2, exp)
  254. class TestSemiMonthBegin:
  255. def test_offset_whole_year(self):
  256. dates = (
  257. datetime(2007, 12, 15),
  258. datetime(2008, 1, 1),
  259. datetime(2008, 1, 15),
  260. datetime(2008, 2, 1),
  261. datetime(2008, 2, 15),
  262. datetime(2008, 3, 1),
  263. datetime(2008, 3, 15),
  264. datetime(2008, 4, 1),
  265. datetime(2008, 4, 15),
  266. datetime(2008, 5, 1),
  267. datetime(2008, 5, 15),
  268. datetime(2008, 6, 1),
  269. datetime(2008, 6, 15),
  270. datetime(2008, 7, 1),
  271. datetime(2008, 7, 15),
  272. datetime(2008, 8, 1),
  273. datetime(2008, 8, 15),
  274. datetime(2008, 9, 1),
  275. datetime(2008, 9, 15),
  276. datetime(2008, 10, 1),
  277. datetime(2008, 10, 15),
  278. datetime(2008, 11, 1),
  279. datetime(2008, 11, 15),
  280. datetime(2008, 12, 1),
  281. datetime(2008, 12, 15),
  282. )
  283. for base, exp_date in zip(dates[:-1], dates[1:]):
  284. assert_offset_equal(SemiMonthBegin(), base, exp_date)
  285. # ensure .apply_index works as expected
  286. shift = DatetimeIndex(dates[:-1])
  287. with tm.assert_produces_warning(None):
  288. # GH#22535 check that we don't get a FutureWarning from adding
  289. # an integer array to PeriodIndex
  290. result = SemiMonthBegin() + shift
  291. exp = DatetimeIndex(dates[1:])
  292. tm.assert_index_equal(result, exp)
  293. offset_cases = [
  294. (
  295. SemiMonthBegin(),
  296. {
  297. datetime(2008, 1, 1): datetime(2008, 1, 15),
  298. datetime(2008, 1, 15): datetime(2008, 2, 1),
  299. datetime(2008, 1, 31): datetime(2008, 2, 1),
  300. datetime(2006, 12, 14): datetime(2006, 12, 15),
  301. datetime(2006, 12, 29): datetime(2007, 1, 1),
  302. datetime(2006, 12, 31): datetime(2007, 1, 1),
  303. datetime(2007, 1, 1): datetime(2007, 1, 15),
  304. datetime(2006, 12, 1): datetime(2006, 12, 15),
  305. datetime(2006, 12, 15): datetime(2007, 1, 1),
  306. },
  307. ),
  308. (
  309. SemiMonthBegin(day_of_month=20),
  310. {
  311. datetime(2008, 1, 1): datetime(2008, 1, 20),
  312. datetime(2008, 1, 15): datetime(2008, 1, 20),
  313. datetime(2008, 1, 21): datetime(2008, 2, 1),
  314. datetime(2008, 1, 31): datetime(2008, 2, 1),
  315. datetime(2006, 12, 14): datetime(2006, 12, 20),
  316. datetime(2006, 12, 29): datetime(2007, 1, 1),
  317. datetime(2006, 12, 31): datetime(2007, 1, 1),
  318. datetime(2007, 1, 1): datetime(2007, 1, 20),
  319. datetime(2006, 12, 1): datetime(2006, 12, 20),
  320. datetime(2006, 12, 15): datetime(2006, 12, 20),
  321. },
  322. ),
  323. (
  324. SemiMonthBegin(0),
  325. {
  326. datetime(2008, 1, 1): datetime(2008, 1, 1),
  327. datetime(2008, 1, 16): datetime(2008, 2, 1),
  328. datetime(2008, 1, 15): datetime(2008, 1, 15),
  329. datetime(2008, 1, 31): datetime(2008, 2, 1),
  330. datetime(2006, 12, 29): datetime(2007, 1, 1),
  331. datetime(2006, 12, 2): datetime(2006, 12, 15),
  332. datetime(2007, 1, 1): datetime(2007, 1, 1),
  333. },
  334. ),
  335. (
  336. SemiMonthBegin(0, day_of_month=16),
  337. {
  338. datetime(2008, 1, 1): datetime(2008, 1, 1),
  339. datetime(2008, 1, 16): datetime(2008, 1, 16),
  340. datetime(2008, 1, 15): datetime(2008, 1, 16),
  341. datetime(2008, 1, 31): datetime(2008, 2, 1),
  342. datetime(2006, 12, 29): datetime(2007, 1, 1),
  343. datetime(2006, 12, 31): datetime(2007, 1, 1),
  344. datetime(2007, 1, 5): datetime(2007, 1, 16),
  345. datetime(2007, 1, 1): datetime(2007, 1, 1),
  346. },
  347. ),
  348. (
  349. SemiMonthBegin(2),
  350. {
  351. datetime(2008, 1, 1): datetime(2008, 2, 1),
  352. datetime(2008, 1, 31): datetime(2008, 2, 15),
  353. datetime(2006, 12, 1): datetime(2007, 1, 1),
  354. datetime(2006, 12, 29): datetime(2007, 1, 15),
  355. datetime(2006, 12, 15): datetime(2007, 1, 15),
  356. datetime(2007, 1, 1): datetime(2007, 2, 1),
  357. datetime(2007, 1, 16): datetime(2007, 2, 15),
  358. datetime(2006, 11, 1): datetime(2006, 12, 1),
  359. },
  360. ),
  361. (
  362. SemiMonthBegin(-1),
  363. {
  364. datetime(2007, 1, 1): datetime(2006, 12, 15),
  365. datetime(2008, 6, 30): datetime(2008, 6, 15),
  366. datetime(2008, 6, 14): datetime(2008, 6, 1),
  367. datetime(2008, 12, 31): datetime(2008, 12, 15),
  368. datetime(2006, 12, 29): datetime(2006, 12, 15),
  369. datetime(2006, 12, 15): datetime(2006, 12, 1),
  370. datetime(2007, 1, 1): datetime(2006, 12, 15),
  371. },
  372. ),
  373. (
  374. SemiMonthBegin(-1, day_of_month=4),
  375. {
  376. datetime(2007, 1, 1): datetime(2006, 12, 4),
  377. datetime(2007, 1, 4): datetime(2007, 1, 1),
  378. datetime(2008, 6, 30): datetime(2008, 6, 4),
  379. datetime(2008, 12, 31): datetime(2008, 12, 4),
  380. datetime(2006, 12, 5): datetime(2006, 12, 4),
  381. datetime(2006, 12, 30): datetime(2006, 12, 4),
  382. datetime(2006, 12, 2): datetime(2006, 12, 1),
  383. datetime(2007, 1, 1): datetime(2006, 12, 4),
  384. },
  385. ),
  386. (
  387. SemiMonthBegin(-2),
  388. {
  389. datetime(2007, 1, 1): datetime(2006, 12, 1),
  390. datetime(2008, 6, 30): datetime(2008, 6, 1),
  391. datetime(2008, 6, 14): datetime(2008, 5, 15),
  392. datetime(2008, 12, 31): datetime(2008, 12, 1),
  393. datetime(2006, 12, 29): datetime(2006, 12, 1),
  394. datetime(2006, 12, 15): datetime(2006, 11, 15),
  395. datetime(2007, 1, 1): datetime(2006, 12, 1),
  396. },
  397. ),
  398. ]
  399. @pytest.mark.parametrize("case", offset_cases)
  400. def test_offset(self, case):
  401. offset, cases = case
  402. for base, expected in cases.items():
  403. assert_offset_equal(offset, base, expected)
  404. @pytest.mark.parametrize("case", offset_cases)
  405. def test_apply_index(self, case):
  406. offset, cases = case
  407. shift = DatetimeIndex(cases.keys())
  408. with tm.assert_produces_warning(None):
  409. # GH#22535 check that we don't get a FutureWarning from adding
  410. # an integer array to PeriodIndex
  411. result = offset + shift
  412. exp = DatetimeIndex(cases.values())
  413. tm.assert_index_equal(result, exp)
  414. on_offset_cases = [
  415. (datetime(2007, 12, 1), True),
  416. (datetime(2007, 12, 15), True),
  417. (datetime(2007, 12, 14), False),
  418. (datetime(2007, 12, 31), False),
  419. (datetime(2008, 2, 15), True),
  420. ]
  421. @pytest.mark.parametrize("case", on_offset_cases)
  422. def test_is_on_offset(self, case):
  423. dt, expected = case
  424. assert_is_on_offset(SemiMonthBegin(), dt, expected)
  425. @pytest.mark.parametrize("klass", [Series, DatetimeIndex])
  426. def test_vectorized_offset_addition(self, klass):
  427. shift = klass(
  428. [
  429. Timestamp("2000-01-15 00:15:00", tz="US/Central"),
  430. Timestamp("2000-02-15", tz="US/Central"),
  431. ],
  432. name="a",
  433. )
  434. with tm.assert_produces_warning(None):
  435. # GH#22535 check that we don't get a FutureWarning from adding
  436. # an integer array to PeriodIndex
  437. result = shift + SemiMonthBegin()
  438. result2 = SemiMonthBegin() + shift
  439. exp = klass(
  440. [
  441. Timestamp("2000-02-01 00:15:00", tz="US/Central"),
  442. Timestamp("2000-03-01", tz="US/Central"),
  443. ],
  444. name="a",
  445. )
  446. tm.assert_equal(result, exp)
  447. tm.assert_equal(result2, exp)
  448. shift = klass(
  449. [
  450. Timestamp("2000-01-01 00:15:00", tz="US/Central"),
  451. Timestamp("2000-02-01", tz="US/Central"),
  452. ],
  453. name="a",
  454. )
  455. with tm.assert_produces_warning(None):
  456. # GH#22535 check that we don't get a FutureWarning from adding
  457. # an integer array to PeriodIndex
  458. result = shift + SemiMonthBegin()
  459. result2 = SemiMonthBegin() + shift
  460. exp = klass(
  461. [
  462. Timestamp("2000-01-15 00:15:00", tz="US/Central"),
  463. Timestamp("2000-02-15", tz="US/Central"),
  464. ],
  465. name="a",
  466. )
  467. tm.assert_equal(result, exp)
  468. tm.assert_equal(result2, exp)
  469. class TestMonthBegin:
  470. offset_cases = []
  471. # NOTE: I'm not entirely happy with the logic here for Begin -ss
  472. # see thread 'offset conventions' on the ML
  473. offset_cases.append(
  474. (
  475. MonthBegin(),
  476. {
  477. datetime(2008, 1, 31): datetime(2008, 2, 1),
  478. datetime(2008, 2, 1): datetime(2008, 3, 1),
  479. datetime(2006, 12, 31): datetime(2007, 1, 1),
  480. datetime(2006, 12, 1): datetime(2007, 1, 1),
  481. datetime(2007, 1, 31): datetime(2007, 2, 1),
  482. },
  483. )
  484. )
  485. offset_cases.append(
  486. (
  487. MonthBegin(0),
  488. {
  489. datetime(2008, 1, 31): datetime(2008, 2, 1),
  490. datetime(2008, 1, 1): datetime(2008, 1, 1),
  491. datetime(2006, 12, 3): datetime(2007, 1, 1),
  492. datetime(2007, 1, 31): datetime(2007, 2, 1),
  493. },
  494. )
  495. )
  496. offset_cases.append(
  497. (
  498. MonthBegin(2),
  499. {
  500. datetime(2008, 2, 29): datetime(2008, 4, 1),
  501. datetime(2008, 1, 31): datetime(2008, 3, 1),
  502. datetime(2006, 12, 31): datetime(2007, 2, 1),
  503. datetime(2007, 12, 28): datetime(2008, 2, 1),
  504. datetime(2007, 1, 1): datetime(2007, 3, 1),
  505. datetime(2006, 11, 1): datetime(2007, 1, 1),
  506. },
  507. )
  508. )
  509. offset_cases.append(
  510. (
  511. MonthBegin(-1),
  512. {
  513. datetime(2007, 1, 1): datetime(2006, 12, 1),
  514. datetime(2008, 5, 31): datetime(2008, 5, 1),
  515. datetime(2008, 12, 31): datetime(2008, 12, 1),
  516. datetime(2006, 12, 29): datetime(2006, 12, 1),
  517. datetime(2006, 1, 2): datetime(2006, 1, 1),
  518. },
  519. )
  520. )
  521. @pytest.mark.parametrize("case", offset_cases)
  522. def test_offset(self, case):
  523. offset, cases = case
  524. for base, expected in cases.items():
  525. assert_offset_equal(offset, base, expected)
  526. class TestMonthEnd:
  527. def test_day_of_month(self):
  528. dt = datetime(2007, 1, 1)
  529. offset = MonthEnd()
  530. result = dt + offset
  531. assert result == Timestamp(2007, 1, 31)
  532. result = result + offset
  533. assert result == Timestamp(2007, 2, 28)
  534. def test_normalize(self):
  535. dt = datetime(2007, 1, 1, 3)
  536. result = dt + MonthEnd(normalize=True)
  537. expected = dt.replace(hour=0) + MonthEnd()
  538. assert result == expected
  539. offset_cases = []
  540. offset_cases.append(
  541. (
  542. MonthEnd(),
  543. {
  544. datetime(2008, 1, 1): datetime(2008, 1, 31),
  545. datetime(2008, 1, 31): datetime(2008, 2, 29),
  546. datetime(2006, 12, 29): datetime(2006, 12, 31),
  547. datetime(2006, 12, 31): datetime(2007, 1, 31),
  548. datetime(2007, 1, 1): datetime(2007, 1, 31),
  549. datetime(2006, 12, 1): datetime(2006, 12, 31),
  550. },
  551. )
  552. )
  553. offset_cases.append(
  554. (
  555. MonthEnd(0),
  556. {
  557. datetime(2008, 1, 1): datetime(2008, 1, 31),
  558. datetime(2008, 1, 31): datetime(2008, 1, 31),
  559. datetime(2006, 12, 29): datetime(2006, 12, 31),
  560. datetime(2006, 12, 31): datetime(2006, 12, 31),
  561. datetime(2007, 1, 1): datetime(2007, 1, 31),
  562. },
  563. )
  564. )
  565. offset_cases.append(
  566. (
  567. MonthEnd(2),
  568. {
  569. datetime(2008, 1, 1): datetime(2008, 2, 29),
  570. datetime(2008, 1, 31): datetime(2008, 3, 31),
  571. datetime(2006, 12, 29): datetime(2007, 1, 31),
  572. datetime(2006, 12, 31): datetime(2007, 2, 28),
  573. datetime(2007, 1, 1): datetime(2007, 2, 28),
  574. datetime(2006, 11, 1): datetime(2006, 12, 31),
  575. },
  576. )
  577. )
  578. offset_cases.append(
  579. (
  580. MonthEnd(-1),
  581. {
  582. datetime(2007, 1, 1): datetime(2006, 12, 31),
  583. datetime(2008, 6, 30): datetime(2008, 5, 31),
  584. datetime(2008, 12, 31): datetime(2008, 11, 30),
  585. datetime(2006, 12, 29): datetime(2006, 11, 30),
  586. datetime(2006, 12, 30): datetime(2006, 11, 30),
  587. datetime(2007, 1, 1): datetime(2006, 12, 31),
  588. },
  589. )
  590. )
  591. @pytest.mark.parametrize("case", offset_cases)
  592. def test_offset(self, case):
  593. offset, cases = case
  594. for base, expected in cases.items():
  595. assert_offset_equal(offset, base, expected)
  596. on_offset_cases = [
  597. (MonthEnd(), datetime(2007, 12, 31), True),
  598. (MonthEnd(), datetime(2008, 1, 1), False),
  599. ]
  600. @pytest.mark.parametrize("case", on_offset_cases)
  601. def test_is_on_offset(self, case):
  602. offset, dt, expected = case
  603. assert_is_on_offset(offset, dt, expected)