Skip to content

Commit ecc7d80

Browse files
committed
better exception message
1 parent b0316a6 commit ecc7d80

File tree

2 files changed

+24
-7
lines changed

2 files changed

+24
-7
lines changed

pandas/_libs/tslibs/timestamps.pyx

+11-4
Original file line numberDiff line numberDiff line change
@@ -479,10 +479,17 @@ cdef class _Timestamp(ABCTimestamp):
479479

480480
# We allow silent casting to the lower resolution if and only
481481
# if it is lossless.
482-
if self._reso < other._reso:
483-
other = (<_Timestamp>other)._as_reso(self._reso, round_ok=False)
484-
elif self._reso > other._reso:
485-
self = (<_Timestamp>self)._as_reso(other._reso, round_ok=False)
482+
try:
483+
if self._reso < other._reso:
484+
other = (<_Timestamp>other)._as_reso(self._reso, round_ok=False)
485+
elif self._reso > other._reso:
486+
self = (<_Timestamp>self)._as_reso(other._reso, round_ok=False)
487+
except ValueError as err:
488+
raise ValueError(
489+
"Timestamp subtraction with mismatched resolutions is not "
490+
"allowed when casting to the lower resolution would require "
491+
"lossy rounding."
492+
) from err
486493

487494
# scalar Timestamp/datetime - Timestamp/datetime -> yields a
488495
# Timedelta

pandas/tests/scalar/timestamp/test_timestamp.py

+13-3
Original file line numberDiff line numberDiff line change
@@ -914,11 +914,22 @@ def test_addsub_offset(self, ts_tz):
914914
assert result.month == 12
915915
assert tz_compare(result.tz, ts_tz.tz)
916916

917+
result = ts_tz - off
918+
919+
assert isinstance(result, Timestamp)
920+
assert result._reso == ts_tz._reso
921+
assert result.year == ts_tz.year - 1
922+
assert result.day == 31
923+
assert result.month == 12
924+
assert tz_compare(result.tz, ts_tz.tz)
925+
917926
def test_sub_datetimelike_mismatched_reso(self, ts_tz):
918927
# case with non-lossy rounding
919928
ts = ts_tz
920929

921-
# choose a unit for `other` that doesn't match ts_tz's
930+
# choose a unit for `other` that doesn't match ts_tz's;
931+
# this construction ensures we get cases with other._reso < ts._reso
932+
# and cases with other._reso > ts._reso
922933
unit = {
923934
NpyDatetimeUnit.NPY_FR_us.value: "ms",
924935
NpyDatetimeUnit.NPY_FR_ms.value: "s",
@@ -937,8 +948,7 @@ def test_sub_datetimelike_mismatched_reso(self, ts_tz):
937948
assert result.value == 0
938949
assert result._reso == min(ts._reso, other._reso)
939950

940-
# TODO: clarify in message that add/sub is allowed only when lossless?
941-
msg = "Cannot losslessly convert units"
951+
msg = "Timestamp subtraction with mismatched resolutions"
942952
if ts._reso < other._reso:
943953
# Case where rounding is lossy
944954
other2 = other + Timedelta._from_value_and_reso(1, other._reso)

0 commit comments

Comments
 (0)