test_liboffsets.py 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. """
  2. Tests for helper functions in the cython tslibs.offsets
  3. """
  4. from datetime import datetime
  5. import pytest
  6. from pandas._libs.tslibs.ccalendar import (
  7. get_firstbday,
  8. get_lastbday,
  9. )
  10. import pandas._libs.tslibs.offsets as liboffsets
  11. from pandas._libs.tslibs.offsets import roll_qtrday
  12. from pandas import Timestamp
  13. @pytest.fixture(params=["start", "end", "business_start", "business_end"])
  14. def day_opt(request):
  15. return request.param
  16. @pytest.mark.parametrize(
  17. "dt,exp_week_day,exp_last_day",
  18. [
  19. (datetime(2017, 11, 30), 3, 30), # Business day.
  20. (datetime(1993, 10, 31), 6, 29), # Non-business day.
  21. ],
  22. )
  23. def test_get_last_bday(dt, exp_week_day, exp_last_day):
  24. assert dt.weekday() == exp_week_day
  25. assert get_lastbday(dt.year, dt.month) == exp_last_day
  26. @pytest.mark.parametrize(
  27. "dt,exp_week_day,exp_first_day",
  28. [
  29. (datetime(2017, 4, 1), 5, 3), # Non-weekday.
  30. (datetime(1993, 10, 1), 4, 1), # Business day.
  31. ],
  32. )
  33. def test_get_first_bday(dt, exp_week_day, exp_first_day):
  34. assert dt.weekday() == exp_week_day
  35. assert get_firstbday(dt.year, dt.month) == exp_first_day
  36. @pytest.mark.parametrize(
  37. "months,day_opt,expected",
  38. [
  39. (0, 15, datetime(2017, 11, 15)),
  40. (0, None, datetime(2017, 11, 30)),
  41. (1, "start", datetime(2017, 12, 1)),
  42. (-145, "end", datetime(2005, 10, 31)),
  43. (0, "business_end", datetime(2017, 11, 30)),
  44. (0, "business_start", datetime(2017, 11, 1)),
  45. ],
  46. )
  47. def test_shift_month_dt(months, day_opt, expected):
  48. dt = datetime(2017, 11, 30)
  49. assert liboffsets.shift_month(dt, months, day_opt=day_opt) == expected
  50. @pytest.mark.parametrize(
  51. "months,day_opt,expected",
  52. [
  53. (1, "start", Timestamp("1929-06-01")),
  54. (-3, "end", Timestamp("1929-02-28")),
  55. (25, None, Timestamp("1931-06-5")),
  56. (-1, 31, Timestamp("1929-04-30")),
  57. ],
  58. )
  59. def test_shift_month_ts(months, day_opt, expected):
  60. ts = Timestamp("1929-05-05")
  61. assert liboffsets.shift_month(ts, months, day_opt=day_opt) == expected
  62. def test_shift_month_error():
  63. dt = datetime(2017, 11, 15)
  64. day_opt = "this should raise"
  65. with pytest.raises(ValueError, match=day_opt):
  66. liboffsets.shift_month(dt, 3, day_opt=day_opt)
  67. @pytest.mark.parametrize(
  68. "other,expected",
  69. [
  70. # Before March 1.
  71. (datetime(2017, 2, 10), {2: 1, -7: -7, 0: 0}),
  72. # After March 1.
  73. (Timestamp("2014-03-15", tz="US/Eastern"), {2: 2, -7: -6, 0: 1}),
  74. ],
  75. )
  76. @pytest.mark.parametrize("n", [2, -7, 0])
  77. def test_roll_qtrday_year(other, expected, n):
  78. month = 3
  79. day_opt = "start" # `other` will be compared to March 1.
  80. assert roll_qtrday(other, n, month, day_opt, modby=12) == expected[n]
  81. @pytest.mark.parametrize(
  82. "other,expected",
  83. [
  84. # Before June 30.
  85. (datetime(1999, 6, 29), {5: 4, -7: -7, 0: 0}),
  86. # After June 30.
  87. (Timestamp(2072, 8, 24, 6, 17, 18), {5: 5, -7: -6, 0: 1}),
  88. ],
  89. )
  90. @pytest.mark.parametrize("n", [5, -7, 0])
  91. def test_roll_qtrday_year2(other, expected, n):
  92. month = 6
  93. day_opt = "end" # `other` will be compared to June 30.
  94. assert roll_qtrday(other, n, month, day_opt, modby=12) == expected[n]
  95. def test_get_day_of_month_error():
  96. # get_day_of_month is not directly exposed.
  97. # We test it via roll_qtrday.
  98. dt = datetime(2017, 11, 15)
  99. day_opt = "foo"
  100. with pytest.raises(ValueError, match=day_opt):
  101. # To hit the raising case we need month == dt.month and n > 0.
  102. roll_qtrday(dt, n=3, month=11, day_opt=day_opt, modby=12)
  103. @pytest.mark.parametrize(
  104. "month",
  105. [3, 5], # (other.month % 3) < (month % 3) # (other.month % 3) > (month % 3)
  106. )
  107. @pytest.mark.parametrize("n", [4, -3])
  108. def test_roll_qtr_day_not_mod_unequal(day_opt, month, n):
  109. expected = {3: {-3: -2, 4: 4}, 5: {-3: -3, 4: 3}}
  110. other = Timestamp(2072, 10, 1, 6, 17, 18) # Saturday.
  111. assert roll_qtrday(other, n, month, day_opt, modby=3) == expected[month][n]
  112. @pytest.mark.parametrize(
  113. "other,month,exp_dict",
  114. [
  115. # Monday.
  116. (datetime(1999, 5, 31), 2, {-1: {"start": 0, "business_start": 0}}),
  117. # Saturday.
  118. (
  119. Timestamp(2072, 10, 1, 6, 17, 18),
  120. 4,
  121. {2: {"end": 1, "business_end": 1, "business_start": 1}},
  122. ),
  123. # First business day.
  124. (
  125. Timestamp(2072, 10, 3, 6, 17, 18),
  126. 4,
  127. {2: {"end": 1, "business_end": 1}, -1: {"start": 0}},
  128. ),
  129. ],
  130. )
  131. @pytest.mark.parametrize("n", [2, -1])
  132. def test_roll_qtr_day_mod_equal(other, month, exp_dict, n, day_opt):
  133. # All cases have (other.month % 3) == (month % 3).
  134. expected = exp_dict.get(n, {}).get(day_opt, n)
  135. assert roll_qtrday(other, n, month, day_opt, modby=3) == expected
  136. @pytest.mark.parametrize(
  137. "n,expected", [(42, {29: 42, 1: 42, 31: 41}), (-4, {29: -4, 1: -3, 31: -4})]
  138. )
  139. @pytest.mark.parametrize("compare", [29, 1, 31])
  140. def test_roll_convention(n, expected, compare):
  141. assert liboffsets.roll_convention(29, n, compare) == expected[compare]