Skip to content

Move comparison utilities to np_datetime; #18080

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

Merged
merged 2 commits into from
Nov 2, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
35 changes: 6 additions & 29 deletions pandas/_libs/tslib.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ from datetime cimport (
from datetime import time as datetime_time

from tslibs.np_datetime cimport (check_dts_bounds,
reverse_ops,
cmp_scalar,
pandas_datetimestruct,
dt64_to_dtstruct, dtstruct_to_dt64,
pydatetime_to_dt64, pydate_to_dt64)
Expand Down Expand Up @@ -893,31 +895,6 @@ def unique_deltas(ndarray[int64_t] arr):
return result


cdef inline bint _cmp_scalar(int64_t lhs, int64_t rhs, int op) except -1:
if op == Py_EQ:
return lhs == rhs
elif op == Py_NE:
return lhs != rhs
elif op == Py_LT:
return lhs < rhs
elif op == Py_LE:
return lhs <= rhs
elif op == Py_GT:
return lhs > rhs
elif op == Py_GE:
return lhs >= rhs


cdef int _reverse_ops[6]

_reverse_ops[Py_LT] = Py_GT
_reverse_ops[Py_LE] = Py_GE
_reverse_ops[Py_EQ] = Py_EQ
_reverse_ops[Py_NE] = Py_NE
_reverse_ops[Py_GT] = Py_LT
_reverse_ops[Py_GE] = Py_LE


cdef str _NDIM_STRING = "ndim"

# This is PITA. Because we inherit from datetime, which has very specific
Expand Down Expand Up @@ -970,7 +947,7 @@ cdef class _Timestamp(datetime):
raise TypeError('Cannot compare type %r with type %r' %
(type(self).__name__,
type(other).__name__))
return PyObject_RichCompare(other, self, _reverse_ops[op])
return PyObject_RichCompare(other, self, reverse_ops[op])
else:
if op == Py_EQ:
return False
Expand All @@ -980,7 +957,7 @@ cdef class _Timestamp(datetime):
(type(self).__name__, type(other).__name__))

self._assert_tzawareness_compat(other)
return _cmp_scalar(self.value, ots.value, op)
return cmp_scalar(self.value, ots.value, op)

def __reduce_ex__(self, protocol):
# python 3.6 compat
Expand Down Expand Up @@ -2066,7 +2043,7 @@ cdef class _Timedelta(timedelta):
type(other).__name__))
if util.is_array(other):
return PyObject_RichCompare(np.array([self]), other, op)
return PyObject_RichCompare(other, self, _reverse_ops[op])
return PyObject_RichCompare(other, self, reverse_ops[op])
else:
if op == Py_EQ:
return False
Expand All @@ -2075,7 +2052,7 @@ cdef class _Timedelta(timedelta):
raise TypeError('Cannot compare type %r with type %r' %
(type(self).__name__, type(other).__name__))

return _cmp_scalar(self.value, ots.value, op)
return cmp_scalar(self.value, ots.value, op)

def _ensure_components(_Timedelta self):
"""
Expand Down
4 changes: 4 additions & 0 deletions pandas/_libs/tslibs/np_datetime.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ cdef extern from "../src/datetime/np_datetime.h":
int32_t month, day, hour, min, sec, us, ps, as


cdef int reverse_ops[6]

cdef bint cmp_scalar(int64_t lhs, int64_t rhs, int op) except -1

cdef check_dts_bounds(pandas_datetimestruct *dts)

cdef int64_t dtstruct_to_dt64(pandas_datetimestruct* dts) nogil
Expand Down
31 changes: 31 additions & 0 deletions pandas/_libs/tslibs/np_datetime.pyx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# -*- coding: utf-8 -*-
# cython: profile=False

from cpython cimport Py_EQ, Py_NE, Py_GE, Py_GT, Py_LT, Py_LE

from cpython.datetime cimport (datetime, date,
PyDateTime_IMPORT,
PyDateTime_GET_YEAR, PyDateTime_GET_MONTH,
Expand Down Expand Up @@ -47,6 +49,35 @@ cdef extern from "../src/datetime/np_datetime.h":
pandas_datetimestruct _NS_MIN_DTS, _NS_MAX_DTS

# ----------------------------------------------------------------------
# Comparison

cdef int reverse_ops[6]

reverse_ops[Py_LT] = Py_GT
reverse_ops[Py_LE] = Py_GE
reverse_ops[Py_EQ] = Py_EQ
reverse_ops[Py_NE] = Py_NE
reverse_ops[Py_GT] = Py_LT
reverse_ops[Py_GE] = Py_LE


cdef inline bint cmp_scalar(int64_t lhs, int64_t rhs, int op) except -1:
"""
cmp_scalar is a more performant version of PyObject_RichCompare
typed for int64_t arguments.
"""
if op == Py_EQ:
return lhs == rhs
elif op == Py_NE:
return lhs != rhs
elif op == Py_LT:
return lhs < rhs
elif op == Py_LE:
return lhs <= rhs
elif op == Py_GT:
return lhs > rhs
elif op == Py_GE:
return lhs >= rhs


class OutOfBoundsDatetime(ValueError):
Expand Down