diff --git a/pandas/_libs/index.pyx b/pandas/_libs/index.pyx index b4dcdaa10d0ef..6b3d1c1ec2c13 100644 --- a/pandas/_libs/index.pyx +++ b/pandas/_libs/index.pyx @@ -22,7 +22,8 @@ cnp.import_array() from pandas._libs cimport util from pandas._libs.tslibs.nattype cimport c_NaT as NaT -from pandas._libs.tslibs.base cimport ABCTimestamp, ABCTimedelta, ABCPeriod +from pandas._libs.tslibs.base cimport ABCTimestamp, ABCTimedelta +from pandas._libs.tslibs.period cimport is_period_object from pandas._libs.hashtable cimport HashTable @@ -479,7 +480,7 @@ cdef class PeriodEngine(Int64Engine): cdef int64_t _unbox_scalar(self, scalar) except? -1: if scalar is NaT: return scalar.value - if isinstance(scalar, ABCPeriod): + if is_period_object(scalar): # NB: we assume that we have the correct freq here. return scalar.ordinal raise TypeError(scalar) diff --git a/pandas/_libs/lib.pyx b/pandas/_libs/lib.pyx index bd623a39010f6..bbd19a33fd34e 100644 --- a/pandas/_libs/lib.pyx +++ b/pandas/_libs/lib.pyx @@ -74,7 +74,7 @@ from pandas._libs.tslibs.nattype cimport ( from pandas._libs.tslibs.conversion cimport convert_to_tsobject from pandas._libs.tslibs.timedeltas cimport convert_to_timedelta64 from pandas._libs.tslibs.timezones cimport get_timezone, tz_compare -from pandas._libs.tslibs.base cimport is_period_object +from pandas._libs.tslibs.period cimport is_period_object from pandas._libs.missing cimport ( checknull, diff --git a/pandas/_libs/tslibs/base.pxd b/pandas/_libs/tslibs/base.pxd index 0521279025d4f..d8c76542f3457 100644 --- a/pandas/_libs/tslibs/base.pxd +++ b/pandas/_libs/tslibs/base.pxd @@ -6,10 +6,3 @@ cdef class ABCTimedelta(timedelta): cdef class ABCTimestamp(datetime): pass - - -cdef class ABCPeriod: - pass - - -cdef bint is_period_object(object obj) diff --git a/pandas/_libs/tslibs/base.pyx b/pandas/_libs/tslibs/base.pyx index 91178fe3933f7..6a5ee3f784334 100644 --- a/pandas/_libs/tslibs/base.pyx +++ b/pandas/_libs/tslibs/base.pyx @@ -14,11 +14,3 @@ cdef class ABCTimedelta(timedelta): cdef class ABCTimestamp(datetime): pass - - -cdef class ABCPeriod: - pass - - -cdef bint is_period_object(object obj): - return isinstance(obj, ABCPeriod) diff --git a/pandas/_libs/tslibs/conversion.pyx b/pandas/_libs/tslibs/conversion.pyx index 7d8c85b6c8e0b..b8544e2a9f39e 100644 --- a/pandas/_libs/tslibs/conversion.pyx +++ b/pandas/_libs/tslibs/conversion.pyx @@ -13,7 +13,7 @@ from cpython.datetime cimport (datetime, time, tzinfo, PyDateTime_IMPORT) PyDateTime_IMPORT -from pandas._libs.tslibs.base cimport ABCTimestamp, is_period_object +from pandas._libs.tslibs.base cimport ABCTimestamp from pandas._libs.tslibs.np_datetime cimport ( check_dts_bounds, npy_datetimestruct, pandas_datetime_to_datetimestruct, @@ -290,10 +290,11 @@ cdef convert_to_tsobject(object ts, object tz, object unit, # Keep the converter same as PyDateTime's ts = datetime.combine(ts, time()) return convert_datetime_to_tsobject(ts, tz) - elif is_period_object(ts): - raise ValueError("Cannot convert Period to Timestamp " - "unambiguously. Use to_timestamp") else: + from .period import Period + if isinstance(ts, Period): + raise ValueError("Cannot convert Period to Timestamp " + "unambiguously. Use to_timestamp") raise TypeError(f'Cannot convert input [{ts}] of type {type(ts)} to ' f'Timestamp') diff --git a/pandas/_libs/tslibs/nattype.pyx b/pandas/_libs/tslibs/nattype.pyx index 84733f50681e4..6342735888550 100644 --- a/pandas/_libs/tslibs/nattype.pyx +++ b/pandas/_libs/tslibs/nattype.pyx @@ -29,7 +29,6 @@ from pandas._libs.tslibs.np_datetime cimport ( get_timedelta64_value, ) cimport pandas._libs.tslibs.util as util -from pandas._libs.tslibs.base cimport is_period_object # ---------------------------------------------------------------------- @@ -149,7 +148,7 @@ cdef class _NaT(datetime): elif util.is_offset_object(other): return c_NaT - elif util.is_integer_object(other) or is_period_object(other): + elif util.is_integer_object(other): # For Period compat # TODO: the integer behavior is deprecated, remove it return c_NaT @@ -163,6 +162,7 @@ cdef class _NaT(datetime): return result raise TypeError(f"Cannot add NaT to ndarray with dtype {other.dtype}") + # Includes Period going through here return NotImplemented def __sub__(self, other): @@ -185,7 +185,7 @@ cdef class _NaT(datetime): elif util.is_offset_object(other): return c_NaT - elif util.is_integer_object(other) or is_period_object(other): + elif util.is_integer_object(other): # For Period compat # TODO: the integer behavior is deprecated, remove it return c_NaT @@ -216,6 +216,7 @@ cdef class _NaT(datetime): f"Cannot subtract NaT from ndarray with dtype {other.dtype}" ) + # Includes Period going through here return NotImplemented def __pos__(self): diff --git a/pandas/_libs/tslibs/period.pxd b/pandas/_libs/tslibs/period.pxd new file mode 100644 index 0000000000000..eb11a4a572e85 --- /dev/null +++ b/pandas/_libs/tslibs/period.pxd @@ -0,0 +1 @@ +cdef bint is_period_object(object obj) diff --git a/pandas/_libs/tslibs/period.pyx b/pandas/_libs/tslibs/period.pyx index 380231129c9b2..246abd0602add 100644 --- a/pandas/_libs/tslibs/period.pyx +++ b/pandas/_libs/tslibs/period.pyx @@ -37,8 +37,6 @@ cdef extern from "src/datetime/np_datetime.h": cimport pandas._libs.tslibs.util as util -from pandas._libs.tslibs.base cimport ABCPeriod, is_period_object - from pandas._libs.tslibs.timestamps import Timestamp from pandas._libs.tslibs.timezones cimport is_utc, is_tzlocal, get_dst_info from pandas._libs.tslibs.timedeltas import Timedelta @@ -1533,7 +1531,7 @@ class IncompatibleFrequency(ValueError): pass -cdef class _Period(ABCPeriod): +cdef class _Period: cdef readonly: int64_t ordinal @@ -1657,8 +1655,11 @@ cdef class _Period(ABCPeriod): raise IncompatibleFrequency(msg) # GH 23915 - mul by base freq since __add__ is agnostic of n return (self.ordinal - other.ordinal) * self.freq.base + elif other is NaT: + return NaT return NotImplemented elif is_period_object(other): + # this can be reached via __rsub__ because of cython rules if self is NaT: return NaT return NotImplemented @@ -2463,6 +2464,10 @@ class Period(_Period): return cls._from_ordinal(ordinal, freq) +cdef bint is_period_object(object obj): + return isinstance(obj, _Period) + + cdef int64_t _ordinal_from_fields(int year, int month, quarter, int day, int hour, int minute, int second, freq): base, mult = get_freq_code(freq)