Skip to content

Commit 6236c98

Browse files
authored
REF: misplaced Timedelta tests (#32871)
1 parent c3d7d25 commit 6236c98

File tree

5 files changed

+288
-309
lines changed

5 files changed

+288
-309
lines changed

pandas/tests/indexes/timedeltas/test_scalar_compat.py

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,3 +69,67 @@ def test_tdi_round(self):
6969
td.round(freq="M")
7070
with pytest.raises(ValueError, match=msg):
7171
elt.round(freq="M")
72+
73+
@pytest.mark.parametrize(
74+
"freq,msg",
75+
[
76+
("Y", "<YearEnd: month=12> is a non-fixed frequency"),
77+
("M", "<MonthEnd> is a non-fixed frequency"),
78+
("foobar", "Invalid frequency: foobar"),
79+
],
80+
)
81+
def test_tdi_round_invalid(self, freq, msg):
82+
t1 = timedelta_range("1 days", periods=3, freq="1 min 2 s 3 us")
83+
84+
with pytest.raises(ValueError, match=msg):
85+
t1.round(freq)
86+
with pytest.raises(ValueError, match=msg):
87+
# Same test for TimedeltaArray
88+
t1._data.round(freq)
89+
90+
# TODO: de-duplicate with test_tdi_round
91+
def test_round(self):
92+
t1 = timedelta_range("1 days", periods=3, freq="1 min 2 s 3 us")
93+
t2 = -1 * t1
94+
t1a = timedelta_range("1 days", periods=3, freq="1 min 2 s")
95+
t1c = TimedeltaIndex([1, 1, 1], unit="D")
96+
97+
# note that negative times round DOWN! so don't give whole numbers
98+
for (freq, s1, s2) in [
99+
("N", t1, t2),
100+
("U", t1, t2),
101+
(
102+
"L",
103+
t1a,
104+
TimedeltaIndex(
105+
["-1 days +00:00:00", "-2 days +23:58:58", "-2 days +23:57:56"],
106+
),
107+
),
108+
(
109+
"S",
110+
t1a,
111+
TimedeltaIndex(
112+
["-1 days +00:00:00", "-2 days +23:58:58", "-2 days +23:57:56"],
113+
),
114+
),
115+
("12T", t1c, TimedeltaIndex(["-1 days", "-1 days", "-1 days"],),),
116+
("H", t1c, TimedeltaIndex(["-1 days", "-1 days", "-1 days"],),),
117+
("d", t1c, TimedeltaIndex([-1, -1, -1], unit="D")),
118+
]:
119+
120+
r1 = t1.round(freq)
121+
tm.assert_index_equal(r1, s1)
122+
r2 = t2.round(freq)
123+
tm.assert_index_equal(r2, s2)
124+
125+
def test_components(self):
126+
rng = timedelta_range("1 days, 10:11:12", periods=2, freq="s")
127+
rng.components
128+
129+
# with nat
130+
s = Series(rng)
131+
s[1] = np.nan
132+
133+
result = s.dt.components
134+
assert not result.iloc[0].isna().all()
135+
assert result.iloc[1].isna().all()

pandas/tests/scalar/timedelta/test_arithmetic.py

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,13 @@ def test_td_add_datetimelike_scalar(self, op):
8888
result = op(td, NaT)
8989
assert result is NaT
9090

91+
def test_td_add_timestamp_overflow(self):
92+
with pytest.raises(OverflowError):
93+
Timestamp("1700-01-01") + Timedelta(13 * 19999, unit="D")
94+
95+
with pytest.raises(OverflowError):
96+
Timestamp("1700-01-01") + timedelta(days=13 * 19999)
97+
9198
@pytest.mark.parametrize("op", [operator.add, ops.radd])
9299
def test_td_add_td(self, op):
93100
td = Timedelta(10, unit="d")
@@ -365,6 +372,26 @@ def test_td_div_timedeltalike_scalar(self):
365372

366373
assert np.isnan(td / NaT)
367374

375+
def test_td_div_td64_non_nano(self):
376+
377+
# truediv
378+
td = Timedelta("1 days 2 hours 3 ns")
379+
result = td / np.timedelta64(1, "D")
380+
assert result == td.value / float(86400 * 1e9)
381+
result = td / np.timedelta64(1, "s")
382+
assert result == td.value / float(1e9)
383+
result = td / np.timedelta64(1, "ns")
384+
assert result == td.value
385+
386+
# floordiv
387+
td = Timedelta("1 days 2 hours 3 ns")
388+
result = td // np.timedelta64(1, "D")
389+
assert result == 1
390+
result = td // np.timedelta64(1, "s")
391+
assert result == 93600
392+
result = td // np.timedelta64(1, "ns")
393+
assert result == td.value
394+
368395
def test_td_div_numeric_scalar(self):
369396
# GH#19738
370397
td = Timedelta(10, unit="d")
@@ -589,6 +616,13 @@ def test_td_rfloordiv_timedeltalike_array(self):
589616
expected = np.array([10, np.nan])
590617
tm.assert_numpy_array_equal(res, expected)
591618

619+
def test_td_rfloordiv_intarray(self):
620+
# deprecated GH#19761, enforced GH#29797
621+
ints = np.array([1349654400, 1349740800, 1349827200, 1349913600]) * 10 ** 9
622+
623+
with pytest.raises(TypeError, match="Invalid dtype"):
624+
ints // Timedelta(1, unit="s")
625+
592626
def test_td_rfloordiv_numeric_series(self):
593627
# GH#18846
594628
td = Timedelta(hours=3, minutes=3)
@@ -796,3 +830,129 @@ def test_rdivmod_invalid(self):
796830
def test_td_op_timedelta_timedeltalike_array(self, op, arr):
797831
with pytest.raises(TypeError):
798832
op(arr, Timedelta("1D"))
833+
834+
835+
class TestTimedeltaComparison:
836+
def test_compare_tick(self, tick_classes):
837+
cls = tick_classes
838+
839+
off = cls(4)
840+
td = off.delta
841+
assert isinstance(td, Timedelta)
842+
843+
assert td == off
844+
assert not td != off
845+
assert td <= off
846+
assert td >= off
847+
assert not td < off
848+
assert not td > off
849+
850+
assert not td == 2 * off
851+
assert td != 2 * off
852+
assert td <= 2 * off
853+
assert td < 2 * off
854+
assert not td >= 2 * off
855+
assert not td > 2 * off
856+
857+
def test_comparison_object_array(self):
858+
# analogous to GH#15183
859+
td = Timedelta("2 days")
860+
other = Timedelta("3 hours")
861+
862+
arr = np.array([other, td], dtype=object)
863+
res = arr == td
864+
expected = np.array([False, True], dtype=bool)
865+
assert (res == expected).all()
866+
867+
# 2D case
868+
arr = np.array([[other, td], [td, other]], dtype=object)
869+
res = arr != td
870+
expected = np.array([[True, False], [False, True]], dtype=bool)
871+
assert res.shape == expected.shape
872+
assert (res == expected).all()
873+
874+
def test_compare_timedelta_ndarray(self):
875+
# GH#11835
876+
periods = [Timedelta("0 days 01:00:00"), Timedelta("0 days 01:00:00")]
877+
arr = np.array(periods)
878+
result = arr[0] > arr
879+
expected = np.array([False, False])
880+
tm.assert_numpy_array_equal(result, expected)
881+
882+
@pytest.mark.skip(reason="GH#20829 is reverted until after 0.24.0")
883+
def test_compare_custom_object(self):
884+
"""
885+
Make sure non supported operations on Timedelta returns NonImplemented
886+
and yields to other operand (GH#20829).
887+
"""
888+
889+
class CustomClass:
890+
def __init__(self, cmp_result=None):
891+
self.cmp_result = cmp_result
892+
893+
def generic_result(self):
894+
if self.cmp_result is None:
895+
return NotImplemented
896+
else:
897+
return self.cmp_result
898+
899+
def __eq__(self, other):
900+
return self.generic_result()
901+
902+
def __gt__(self, other):
903+
return self.generic_result()
904+
905+
t = Timedelta("1s")
906+
907+
assert not (t == "string")
908+
assert not (t == 1)
909+
assert not (t == CustomClass())
910+
assert not (t == CustomClass(cmp_result=False))
911+
912+
assert t < CustomClass(cmp_result=True)
913+
assert not (t < CustomClass(cmp_result=False))
914+
915+
assert t == CustomClass(cmp_result=True)
916+
917+
@pytest.mark.parametrize("val", ["string", 1])
918+
def test_compare_unknown_type(self, val):
919+
# GH#20829
920+
t = Timedelta("1s")
921+
with pytest.raises(TypeError):
922+
t >= val
923+
with pytest.raises(TypeError):
924+
t > val
925+
with pytest.raises(TypeError):
926+
t <= val
927+
with pytest.raises(TypeError):
928+
t < val
929+
930+
931+
def test_ops_notimplemented():
932+
class Other:
933+
pass
934+
935+
other = Other()
936+
937+
td = Timedelta("1 day")
938+
assert td.__add__(other) is NotImplemented
939+
assert td.__sub__(other) is NotImplemented
940+
assert td.__truediv__(other) is NotImplemented
941+
assert td.__mul__(other) is NotImplemented
942+
assert td.__floordiv__(other) is NotImplemented
943+
944+
945+
def test_ops_error_str():
946+
# GH#13624
947+
td = Timedelta("1 day")
948+
949+
for left, right in [(td, "a"), ("a", td)]:
950+
951+
with pytest.raises(TypeError):
952+
left + right
953+
954+
with pytest.raises(TypeError):
955+
left > right
956+
957+
assert not left == right
958+
assert left != right

0 commit comments

Comments
 (0)