test_to_offset.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. import re
  2. import pytest
  3. from pandas._libs.tslibs import (
  4. Timedelta,
  5. offsets,
  6. to_offset,
  7. )
  8. @pytest.mark.parametrize(
  9. "freq_input,expected",
  10. [
  11. (to_offset("10us"), offsets.Micro(10)),
  12. (offsets.Hour(), offsets.Hour()),
  13. ("2h30min", offsets.Minute(150)),
  14. ("2h 30min", offsets.Minute(150)),
  15. ("2h30min15s", offsets.Second(150 * 60 + 15)),
  16. ("2h 60min", offsets.Hour(3)),
  17. ("2h 20.5min", offsets.Second(8430)),
  18. ("1.5min", offsets.Second(90)),
  19. ("0.5s", offsets.Milli(500)),
  20. ("15ms500us", offsets.Micro(15500)),
  21. ("10s75ms", offsets.Milli(10075)),
  22. ("1s0.25ms", offsets.Micro(1000250)),
  23. ("1s0.25ms", offsets.Micro(1000250)),
  24. ("2800ns", offsets.Nano(2800)),
  25. ("2SME", offsets.SemiMonthEnd(2)),
  26. ("2SME-16", offsets.SemiMonthEnd(2, day_of_month=16)),
  27. ("2SMS-14", offsets.SemiMonthBegin(2, day_of_month=14)),
  28. ("2SMS-15", offsets.SemiMonthBegin(2)),
  29. ],
  30. )
  31. def test_to_offset(freq_input, expected):
  32. result = to_offset(freq_input)
  33. assert result == expected
  34. @pytest.mark.parametrize(
  35. "freqstr,expected", [("-1s", -1), ("-2SME", -2), ("-1SMS", -1), ("-5min10s", -310)]
  36. )
  37. def test_to_offset_negative(freqstr, expected):
  38. result = to_offset(freqstr)
  39. assert result.n == expected
  40. @pytest.mark.filterwarnings("ignore:.*'m' is deprecated.*:FutureWarning")
  41. @pytest.mark.parametrize(
  42. "freqstr",
  43. [
  44. "2h20m",
  45. "us1",
  46. "-us",
  47. "3us1",
  48. "-2-3us",
  49. "-2D:3h",
  50. "1.5.0s",
  51. "2SMS-15-15",
  52. "2SMS-15D",
  53. "100foo",
  54. # Invalid leading +/- signs.
  55. "+-1d",
  56. "-+1h",
  57. "+1",
  58. "-7",
  59. "+d",
  60. "-m",
  61. # Invalid shortcut anchors.
  62. "SME-0",
  63. "SME-28",
  64. "SME-29",
  65. "SME-FOO",
  66. "BSM",
  67. "SME--1",
  68. "SMS-1",
  69. "SMS-28",
  70. "SMS-30",
  71. "SMS-BAR",
  72. "SMS-BYR",
  73. "BSMS",
  74. "SMS--2",
  75. ],
  76. )
  77. def test_to_offset_invalid(freqstr):
  78. # see gh-13930
  79. # We escape string because some of our
  80. # inputs contain regex special characters.
  81. msg = re.escape(f"Invalid frequency: {freqstr}")
  82. with pytest.raises(ValueError, match=msg):
  83. to_offset(freqstr)
  84. def test_to_offset_no_evaluate():
  85. msg = str(("", ""))
  86. with pytest.raises(TypeError, match=msg):
  87. to_offset(("", ""))
  88. def test_to_offset_tuple_unsupported():
  89. with pytest.raises(TypeError, match="pass as a string instead"):
  90. to_offset((5, "T"))
  91. @pytest.mark.parametrize(
  92. "freqstr,expected",
  93. [
  94. ("2D 3h", offsets.Hour(51)),
  95. ("2 D3 h", offsets.Hour(51)),
  96. ("2 D 3 h", offsets.Hour(51)),
  97. (" 2 D 3 h ", offsets.Hour(51)),
  98. (" h ", offsets.Hour()),
  99. (" 3 h ", offsets.Hour(3)),
  100. ],
  101. )
  102. def test_to_offset_whitespace(freqstr, expected):
  103. result = to_offset(freqstr)
  104. assert result == expected
  105. @pytest.mark.parametrize(
  106. "freqstr,expected", [("00h 00min 01s", 1), ("-00h 03min 14s", -194)]
  107. )
  108. def test_to_offset_leading_zero(freqstr, expected):
  109. result = to_offset(freqstr)
  110. assert result.n == expected
  111. @pytest.mark.parametrize("freqstr,expected", [("+1d", 1), ("+2h30min", 150)])
  112. def test_to_offset_leading_plus(freqstr, expected):
  113. result = to_offset(freqstr)
  114. assert result.n == expected
  115. @pytest.mark.parametrize(
  116. "kwargs,expected",
  117. [
  118. ({"days": 1, "seconds": 1}, offsets.Second(86401)),
  119. ({"days": -1, "seconds": 1}, offsets.Second(-86399)),
  120. ({"hours": 1, "minutes": 10}, offsets.Minute(70)),
  121. ({"hours": 1, "minutes": -10}, offsets.Minute(50)),
  122. ({"weeks": 1}, offsets.Day(7)),
  123. ({"hours": 1}, offsets.Hour(1)),
  124. ({"hours": 1}, to_offset("60min")),
  125. ({"microseconds": 1}, offsets.Micro(1)),
  126. ({"microseconds": 0}, offsets.Nano(0)),
  127. ],
  128. )
  129. def test_to_offset_pd_timedelta(kwargs, expected):
  130. # see gh-9064
  131. td = Timedelta(**kwargs)
  132. result = to_offset(td)
  133. assert result == expected
  134. @pytest.mark.parametrize(
  135. "shortcut,expected",
  136. [
  137. ("W", offsets.Week(weekday=6)),
  138. ("W-SUN", offsets.Week(weekday=6)),
  139. ("QE", offsets.QuarterEnd(startingMonth=12)),
  140. ("QE-DEC", offsets.QuarterEnd(startingMonth=12)),
  141. ("QE-MAY", offsets.QuarterEnd(startingMonth=5)),
  142. ("SME", offsets.SemiMonthEnd(day_of_month=15)),
  143. ("SME-15", offsets.SemiMonthEnd(day_of_month=15)),
  144. ("SME-1", offsets.SemiMonthEnd(day_of_month=1)),
  145. ("SME-27", offsets.SemiMonthEnd(day_of_month=27)),
  146. ("SMS-2", offsets.SemiMonthBegin(day_of_month=2)),
  147. ("SMS-27", offsets.SemiMonthBegin(day_of_month=27)),
  148. ],
  149. )
  150. def test_anchored_shortcuts(shortcut, expected):
  151. result = to_offset(shortcut)
  152. assert result == expected
  153. @pytest.mark.parametrize(
  154. "freq_depr",
  155. [
  156. "2ye-mar",
  157. "2ys",
  158. "2qe",
  159. "2qs-feb",
  160. "2bqs",
  161. "2sms",
  162. "2bms",
  163. "2cbme",
  164. "2me",
  165. "2w",
  166. ],
  167. )
  168. def test_to_offset_lowercase_frequency_deprecated(freq_depr):
  169. # GH#54939
  170. depr_msg = f"'{freq_depr[1:]}' is deprecated and will be removed in a "
  171. f"future version, please use '{freq_depr.upper()[1:]}' instead."
  172. with pytest.raises(FutureWarning, match=depr_msg):
  173. to_offset(freq_depr)
  174. @pytest.mark.parametrize(
  175. "freq_depr",
  176. [
  177. "2H",
  178. "2BH",
  179. "2MIN",
  180. "2S",
  181. "2Us",
  182. "2NS",
  183. ],
  184. )
  185. def test_to_offset_uppercase_frequency_deprecated(freq_depr):
  186. # GH#54939
  187. depr_msg = f"'{freq_depr[1:]}' is deprecated and will be removed in a "
  188. f"future version, please use '{freq_depr.lower()[1:]}' instead."
  189. with pytest.raises(FutureWarning, match=depr_msg):
  190. to_offset(freq_depr)