test_interval.py 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. from __future__ import division
  2. import numpy as np
  3. import pytest
  4. from pandas import Interval, Timedelta, Timestamp
  5. import pandas.core.common as com
  6. @pytest.fixture
  7. def interval():
  8. return Interval(0, 1)
  9. class TestInterval(object):
  10. def test_properties(self, interval):
  11. assert interval.closed == 'right'
  12. assert interval.left == 0
  13. assert interval.right == 1
  14. assert interval.mid == 0.5
  15. def test_repr(self, interval):
  16. assert repr(interval) == "Interval(0, 1, closed='right')"
  17. assert str(interval) == "(0, 1]"
  18. interval_left = Interval(0, 1, closed='left')
  19. assert repr(interval_left) == "Interval(0, 1, closed='left')"
  20. assert str(interval_left) == "[0, 1)"
  21. def test_contains(self, interval):
  22. assert 0.5 in interval
  23. assert 1 in interval
  24. assert 0 not in interval
  25. msg = "__contains__ not defined for two intervals"
  26. with pytest.raises(TypeError, match=msg):
  27. interval in interval
  28. interval_both = Interval(0, 1, closed='both')
  29. assert 0 in interval_both
  30. assert 1 in interval_both
  31. interval_neither = Interval(0, 1, closed='neither')
  32. assert 0 not in interval_neither
  33. assert 0.5 in interval_neither
  34. assert 1 not in interval_neither
  35. def test_equal(self):
  36. assert Interval(0, 1) == Interval(0, 1, closed='right')
  37. assert Interval(0, 1) != Interval(0, 1, closed='left')
  38. assert Interval(0, 1) != 0
  39. def test_comparison(self):
  40. with pytest.raises(TypeError, match='unorderable types'):
  41. Interval(0, 1) < 2
  42. assert Interval(0, 1) < Interval(1, 2)
  43. assert Interval(0, 1) < Interval(0, 2)
  44. assert Interval(0, 1) < Interval(0.5, 1.5)
  45. assert Interval(0, 1) <= Interval(0, 1)
  46. assert Interval(0, 1) > Interval(-1, 2)
  47. assert Interval(0, 1) >= Interval(0, 1)
  48. def test_hash(self, interval):
  49. # should not raise
  50. hash(interval)
  51. @pytest.mark.parametrize('left, right, expected', [
  52. (0, 5, 5),
  53. (-2, 5.5, 7.5),
  54. (10, 10, 0),
  55. (10, np.inf, np.inf),
  56. (-np.inf, -5, np.inf),
  57. (-np.inf, np.inf, np.inf),
  58. (Timedelta('0 days'), Timedelta('5 days'), Timedelta('5 days')),
  59. (Timedelta('10 days'), Timedelta('10 days'), Timedelta('0 days')),
  60. (Timedelta('1H10M'), Timedelta('5H5M'), Timedelta('3H55M')),
  61. (Timedelta('5S'), Timedelta('1H'), Timedelta('59M55S'))])
  62. def test_length(self, left, right, expected):
  63. # GH 18789
  64. iv = Interval(left, right)
  65. result = iv.length
  66. assert result == expected
  67. @pytest.mark.parametrize('left, right, expected', [
  68. ('2017-01-01', '2017-01-06', '5 days'),
  69. ('2017-01-01', '2017-01-01 12:00:00', '12 hours'),
  70. ('2017-01-01 12:00', '2017-01-01 12:00:00', '0 days'),
  71. ('2017-01-01 12:01', '2017-01-05 17:31:00', '4 days 5 hours 30 min')])
  72. @pytest.mark.parametrize('tz', (None, 'UTC', 'CET', 'US/Eastern'))
  73. def test_length_timestamp(self, tz, left, right, expected):
  74. # GH 18789
  75. iv = Interval(Timestamp(left, tz=tz), Timestamp(right, tz=tz))
  76. result = iv.length
  77. expected = Timedelta(expected)
  78. assert result == expected
  79. @pytest.mark.parametrize('left, right', [
  80. ('a', 'z'),
  81. (('a', 'b'), ('c', 'd')),
  82. (list('AB'), list('ab')),
  83. (Interval(0, 1), Interval(1, 2))])
  84. def test_length_errors(self, left, right):
  85. # GH 18789
  86. iv = Interval(left, right)
  87. msg = 'cannot compute length between .* and .*'
  88. with pytest.raises(TypeError, match=msg):
  89. iv.length
  90. def test_math_add(self, closed):
  91. interval = Interval(0, 1, closed=closed)
  92. expected = Interval(1, 2, closed=closed)
  93. result = interval + 1
  94. assert result == expected
  95. result = 1 + interval
  96. assert result == expected
  97. result = interval
  98. result += 1
  99. assert result == expected
  100. msg = r"unsupported operand type\(s\) for \+"
  101. with pytest.raises(TypeError, match=msg):
  102. interval + interval
  103. with pytest.raises(TypeError, match=msg):
  104. interval + 'foo'
  105. def test_math_sub(self, closed):
  106. interval = Interval(0, 1, closed=closed)
  107. expected = Interval(-1, 0, closed=closed)
  108. result = interval - 1
  109. assert result == expected
  110. result = interval
  111. result -= 1
  112. assert result == expected
  113. msg = r"unsupported operand type\(s\) for -"
  114. with pytest.raises(TypeError, match=msg):
  115. interval - interval
  116. with pytest.raises(TypeError, match=msg):
  117. interval - 'foo'
  118. def test_math_mult(self, closed):
  119. interval = Interval(0, 1, closed=closed)
  120. expected = Interval(0, 2, closed=closed)
  121. result = interval * 2
  122. assert result == expected
  123. result = 2 * interval
  124. assert result == expected
  125. result = interval
  126. result *= 2
  127. assert result == expected
  128. msg = r"unsupported operand type\(s\) for \*"
  129. with pytest.raises(TypeError, match=msg):
  130. interval * interval
  131. msg = r"can\'t multiply sequence by non-int"
  132. with pytest.raises(TypeError, match=msg):
  133. interval * 'foo'
  134. def test_math_div(self, closed):
  135. interval = Interval(0, 1, closed=closed)
  136. expected = Interval(0, 0.5, closed=closed)
  137. result = interval / 2.0
  138. assert result == expected
  139. result = interval
  140. result /= 2.0
  141. assert result == expected
  142. msg = r"unsupported operand type\(s\) for /"
  143. with pytest.raises(TypeError, match=msg):
  144. interval / interval
  145. with pytest.raises(TypeError, match=msg):
  146. interval / 'foo'
  147. def test_math_floordiv(self, closed):
  148. interval = Interval(1, 2, closed=closed)
  149. expected = Interval(0, 1, closed=closed)
  150. result = interval // 2
  151. assert result == expected
  152. result = interval
  153. result //= 2
  154. assert result == expected
  155. msg = r"unsupported operand type\(s\) for //"
  156. with pytest.raises(TypeError, match=msg):
  157. interval // interval
  158. with pytest.raises(TypeError, match=msg):
  159. interval // 'foo'
  160. def test_constructor_errors(self):
  161. msg = "invalid option for 'closed': foo"
  162. with pytest.raises(ValueError, match=msg):
  163. Interval(0, 1, closed='foo')
  164. msg = 'left side of interval must be <= right side'
  165. with pytest.raises(ValueError, match=msg):
  166. Interval(1, 0)
  167. @pytest.mark.parametrize('tz_left, tz_right', [
  168. (None, 'UTC'), ('UTC', None), ('UTC', 'US/Eastern')])
  169. def test_constructor_errors_tz(self, tz_left, tz_right):
  170. # GH 18538
  171. left = Timestamp('2017-01-01', tz=tz_left)
  172. right = Timestamp('2017-01-02', tz=tz_right)
  173. error = TypeError if com._any_none(tz_left, tz_right) else ValueError
  174. with pytest.raises(error):
  175. Interval(left, right)