Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BUG: Raise TypeError when subracting DateTimeArray and other date types #59901

Open
wants to merge 18 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
99b1c3d
sync to master
KevsterAmp Sep 7, 2024
55e6e47
Merge remote-tracking branch 'upstream/main'
KevsterAmp Sep 7, 2024
e5b75f0
Merge remote-tracking branch 'upstream/main' into better-msg-delta-se…
KevsterAmp Sep 25, 2024
2e041b9
raise TypeError when "-" is used between DateTimeArray
KevsterAmp Sep 26, 2024
11dd714
Merge remote-tracking branch 'upstream/main' into better-msg-delta-se…
KevsterAmp Sep 26, 2024
b9f41fb
Merge remote-tracking branch 'upstream/main' into better-msg-delta-se…
KevsterAmp Oct 3, 2024
9f14a2a
remove pandas library and improve formatting
KevsterAmp Oct 3, 2024
1df1edc
modify tests revolving this issue
KevsterAmp Oct 3, 2024
ca071a5
Merge remote-tracking branch 'upstream/main' into better-msg-delta-se…
KevsterAmp Nov 12, 2024
5feb3a6
import outside top-level to handle DatetimeArray initialization
KevsterAmp Nov 12, 2024
8f7430f
replace prev error msg to new implemented error msg
KevsterAmp Nov 12, 2024
71a0c0f
replace prev error msg on test_timedelta64 with new error msg
KevsterAmp Nov 12, 2024
1aba9a2
specify dtype since test func doesn't contain multiple params/loops
KevsterAmp Nov 12, 2024
5b20b59
catch TypeError on DateTimeArrays specifically; Improve error message
KevsterAmp Nov 16, 2024
17ace06
fix tests due to changed error message
KevsterAmp Nov 16, 2024
25286eb
Merge remote-tracking branch 'upstream/main' into better-msg-delta-se…
KevsterAmp Nov 16, 2024
23eb6c2
remove if statement to always raise the exception on TypeERror
KevsterAmp Dec 5, 2024
341d085
Merge remote-tracking branch 'upstream/main' into better-msg-delta-se…
KevsterAmp Dec 5, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion pandas/core/arrays/datetimelike.py
Original file line number Diff line number Diff line change
Expand Up @@ -1495,7 +1495,15 @@ def __rsub__(self, other):
return (-self) + other

# We get here with e.g. datetime objects
return -(self - other)
from pandas.core.arrays import DatetimeArray

datetime_result = self - other
if isinstance(datetime_result, DatetimeArray):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a little nervous enforcing a particular type out of a rsub operation.

Could we just catch the TypeError and reraise it with a better message?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gotcha, I agree that it would be a better implementation

raise TypeError(
"TypeError: unsupported operand type(s) for -: "
f"'{type(self).__name__}' and '{type(other).__name__}'"
)
return -(datetime_result)

def __iadd__(self, other) -> Self:
result = self + other
Expand Down
27 changes: 20 additions & 7 deletions pandas/tests/arithmetic/test_datetime64.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
starmap,
)
import operator
import re

import numpy as np
import pytest
Expand Down Expand Up @@ -1273,8 +1274,10 @@ def test_dt64arr_series_sub_tick_DateOffset(self, box_with_array):

result2 = -pd.offsets.Second(5) + ser
tm.assert_equal(result2, expected)
msg = "(bad|unsupported) operand type for unary"
with pytest.raises(TypeError, match=msg):
msg = (
"TypeError: unsupported operand type(s) for -: 'DatetimeArray' and 'Second'"
)
with pytest.raises(TypeError, match=re.escape(msg)):
pd.offsets.Second(5) - ser

@pytest.mark.parametrize(
Expand Down Expand Up @@ -1318,8 +1321,10 @@ def test_dti_add_tick_tzaware(self, tz_aware_fixture, box_with_array):
roundtrip = offset - scalar
tm.assert_equal(roundtrip, dates)

msg = "|".join(
["bad operand type for unary -", "cannot subtract DatetimeArray"]
msg = (
r"TypeError: unsupported operand type\(s\) "
"for -: 'DatetimeArray' and '.*'|"
r"cannot subtract DatetimeArray from .*"
)
with pytest.raises(TypeError, match=msg):
scalar - dates
Expand Down Expand Up @@ -1379,7 +1384,10 @@ def test_dt64arr_add_sub_relativedelta_offsets(self, box_with_array, unit):
expected = DatetimeIndex([x - off for x in vec_items]).as_unit(exp_unit)
expected = tm.box_expected(expected, box_with_array)
tm.assert_equal(expected, vec - off)
msg = "(bad|unsupported) operand type for unary"
msg = (
r"TypeError: unsupported operand type\(s\) "
"for -: 'DatetimeArray' and '.*'"
)
with pytest.raises(TypeError, match=msg):
off - vec

Expand Down Expand Up @@ -1495,7 +1503,9 @@ def test_dt64arr_add_sub_DateOffsets(
expected = DatetimeIndex([offset + x for x in vec_items]).as_unit(unit)
expected = tm.box_expected(expected, box_with_array)
tm.assert_equal(expected, offset + vec)
msg = "(bad|unsupported) operand type for unary"
msg = (
r"TypeError: unsupported operand type\(s\) for -: 'DatetimeArray' and '.*'"
)
with pytest.raises(TypeError, match=msg):
offset - vec

Expand Down Expand Up @@ -1984,7 +1994,10 @@ def test_operators_datetimelike_with_timezones(self):
result = dt1 - td1[0]
exp = (dt1.dt.tz_localize(None) - td1[0]).dt.tz_localize(tz)
tm.assert_series_equal(result, exp)
msg = "(bad|unsupported) operand type for unary"
msg = (
r"TypeError: unsupported operand type\(s\) "
"for -: 'DatetimeArray' and 'Timedelta'"
)
with pytest.raises(TypeError, match=msg):
td1[0] - dt1

Expand Down
5 changes: 4 additions & 1 deletion pandas/tests/arithmetic/test_timedelta64.py
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,10 @@ def test_subtraction_ops(self):
with pytest.raises(TypeError, match=msg):
td - dt

msg = "(bad|unsupported) operand type for unary"
msg = (
r"TypeError: unsupported operand type\(s\) "
"for -: 'DatetimeArray' and 'Timedelta'"
)
with pytest.raises(TypeError, match=msg):
td - dti

Expand Down