Skip to content
2 changes: 2 additions & 0 deletions doc/source/whatsnew/v0.25.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -603,6 +603,8 @@ Datetimelike
- Bug when comparing a :class:`PeriodIndex` against a zero-dimensional numpy array (:issue:`26689`)
- Bug in constructing a ``Series`` or ``DataFrame`` from a numpy ``datetime64`` array with a non-ns unit and out-of-bound timestamps generating rubbish data, which will now correctly raise an ``OutOfBoundsDatetime`` error (:issue:`26206`).
- Bug in :func:`date_range` with unnecessary ``OverflowError`` being raised for very large or very small dates (:issue:`26651`)
- Bug where adding :class:`Timestamp` to a ``np.timedelta64`` object would raise instead of returning a :class:`Timestamp` (:issue:`24775`)
- Bug where comparing a zero-dimensional numpy array containing a ``np.datetime64`` object to a :class:`Timestamp` would incorrect raise ``TypeError`` (:issue:`26916`)

Timedelta
^^^^^^^^^
Expand Down
12 changes: 12 additions & 0 deletions pandas/_libs/tslibs/c_timestamp.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ def maybe_integer_op_deprecated(obj):

cdef class _Timestamp(datetime):

# higher than np.ndarray and np.matrix
__array_priority__ = 100

def __hash__(_Timestamp self):
if self.nanosecond:
return hash(self.value)
Expand Down Expand Up @@ -85,6 +88,15 @@ cdef class _Timestamp(datetime):
if ndim == 0:
if is_datetime64_object(other):
other = self.__class__(other)
elif is_array(other):
# zero-dim array, occurs if try comparison with
# datetime64 scalar on the left hand side
# Unfortunately, for datetime64 values, other.item()
# incorrectly returns an integer, so we need to use
# the numpy C api to extract it.
other = cnp.PyArray_ToScalar(cnp.PyArray_DATA(other),
other)
other = self.__class__(other)
else:
return NotImplemented
elif is_array(other):
Expand Down
20 changes: 20 additions & 0 deletions pandas/tests/scalar/timestamp/test_arithmetic.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,3 +112,23 @@ def test_addition_subtraction_preserve_frequency(self):
td64 = np.timedelta64(1, 'D')
assert (ts + td64).freq == original_freq
assert (ts - td64).freq == original_freq

@pytest.mark.parametrize('td', [Timedelta(hours=3),
np.timedelta64(3, 'h'),
timedelta(hours=3)])
def test_radd_tdscalar(self, td):
# GH#24775 timedelta64+Timestamp should not raise
ts = Timestamp.now()
assert td + ts == ts + td

@pytest.mark.parametrize('other,expected_difference', [
(np.timedelta64(-123, 'ns'), -123),
(np.timedelta64(1234567898, 'ns'), 1234567898),
(np.timedelta64(-123, 'us'), -123000),
(np.timedelta64(-123, 'ms'), -123000000)
])
def test_timestamp_add_timedelta64_unit(self, other, expected_difference):
ts = Timestamp(datetime.utcnow())
result = ts + other
valdiff = result.value - ts.value
assert valdiff == expected_difference
12 changes: 12 additions & 0 deletions pandas/tests/scalar/timestamp/test_comparisons.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,18 @@ def test_timestamp_compare_with_early_datetime(self):
assert stamp < datetime(2700, 1, 1)
assert stamp <= datetime(2700, 1, 1)

def test_compare_zerodim_array(self):
# GH#26916
ts = Timestamp.now()
dt64 = np.datetime64('2016-01-01', 'ns')
arr = np.array(dt64)
assert arr.ndim == 0

result = arr < ts
assert result is True
result = arr > ts
assert result is False


def test_rich_comparison_with_unsupported_type():
# Comparisons with unsupported objects should return NotImplemented
Expand Down
25 changes: 0 additions & 25 deletions pandas/tests/scalar/timestamp/test_timestamp.py
Original file line number Diff line number Diff line change
Expand Up @@ -796,31 +796,6 @@ def test_tz_conversion_freq(self, tz_naive_fixture):

class TestTimestampNsOperations:

def setup_method(self, method):
self.timestamp = Timestamp(datetime.utcnow())

def assert_ns_timedelta(self, modified_timestamp, expected_value):
value = self.timestamp.value
modified_value = modified_timestamp.value

assert modified_value - value == expected_value

def test_timedelta_ns_arithmetic(self):
self.assert_ns_timedelta(self.timestamp + np.timedelta64(-123, 'ns'),
-123)

def test_timedelta_ns_based_arithmetic(self):
self.assert_ns_timedelta(self.timestamp + np.timedelta64(
1234567898, 'ns'), 1234567898)

def test_timedelta_us_arithmetic(self):
self.assert_ns_timedelta(self.timestamp + np.timedelta64(-123, 'us'),
-123000)

def test_timedelta_ms_arithmetic(self):
time = self.timestamp + np.timedelta64(-123, 'ms')
self.assert_ns_timedelta(time, -123000000)

def test_nanosecond_string_parsing(self):
ts = Timestamp('2013-05-01 07:15:45.123456789')
# GH 7878
Expand Down