diff --git a/pandas/_libs/algos.pyx b/pandas/_libs/algos.pyx index 4e3cdc0fdd14a..44234013c7a3c 100644 --- a/pandas/_libs/algos.pyx +++ b/pandas/_libs/algos.pyx @@ -750,7 +750,7 @@ def is_monotonic(ndarray[numeric_object_t, ndim=1] arr, bint timelike): n = len(arr) if n == 1: - if arr[0] != arr[0] or (timelike and arr[0] == NPY_NAT): + if arr[0] != arr[0] or (numeric_object_t is int64_t and timelike and arr[0] == NPY_NAT): # single value is NaN return False, False, True else: diff --git a/pandas/_libs/indexing.pyx b/pandas/_libs/indexing.pyx index 181de174c53fb..c274b28b7559a 100644 --- a/pandas/_libs/indexing.pyx +++ b/pandas/_libs/indexing.pyx @@ -2,21 +2,24 @@ cdef class NDFrameIndexerBase: """ A base class for _NDFrameIndexer for fast instantiation and attribute access. """ + cdef: + Py_ssize_t _ndim + cdef public: str name - object obj, _ndim + object obj def __init__(self, name: str, obj): self.obj = obj self.name = name - self._ndim = None + self._ndim = -1 @property def ndim(self) -> int: # Delay `ndim` instantiation until required as reading it # from `obj` isn't entirely cheap. ndim = self._ndim - if ndim is None: + if ndim == -1: ndim = self._ndim = self.obj.ndim if ndim > 2: raise ValueError( # pragma: no cover diff --git a/pandas/_libs/internals.pyx b/pandas/_libs/internals.pyx index ac423ef6c0ca2..d2dc60d27706d 100644 --- a/pandas/_libs/internals.pyx +++ b/pandas/_libs/internals.pyx @@ -544,7 +544,7 @@ cpdef update_blklocs_and_blknos( """ cdef: Py_ssize_t i - cnp.npy_intp length = len(blklocs) + 1 + cnp.npy_intp length = blklocs.shape[0] + 1 ndarray[intp_t, ndim=1] new_blklocs, new_blknos # equiv: new_blklocs = np.empty(length, dtype=np.intp) diff --git a/pandas/_libs/tslib.pyx b/pandas/_libs/tslib.pyx index 9dfc438319148..5c0b69d51367a 100644 --- a/pandas/_libs/tslib.pyx +++ b/pandas/_libs/tslib.pyx @@ -218,7 +218,7 @@ def array_with_unit_to_datetime( """ cdef: Py_ssize_t i, j, n=len(values) - int64_t m + int64_t mult int prec = 0 ndarray[float64_t] fvalues bint is_ignore = errors=='ignore' @@ -242,7 +242,7 @@ def array_with_unit_to_datetime( ) return result, tz - m, _ = precision_from_unit(unit) + mult, _ = precision_from_unit(unit) if is_raise: # try a quick conversion to i8/f8 @@ -254,7 +254,7 @@ def array_with_unit_to_datetime( # fill missing values by comparing to NPY_NAT mask = iresult == NPY_NAT iresult[mask] = 0 - fvalues = iresult.astype("f8") * m + fvalues = iresult.astype("f8") * mult need_to_iterate = False if not need_to_iterate: @@ -265,10 +265,10 @@ def array_with_unit_to_datetime( raise OutOfBoundsDatetime(f"cannot convert input with unit '{unit}'") if values.dtype.kind in ["i", "u"]: - result = (iresult * m).astype("M8[ns]") + result = (iresult * mult).astype("M8[ns]") elif values.dtype.kind == "f": - fresult = (values * m).astype("f8") + fresult = (values * mult).astype("f8") fresult[mask] = 0 if prec: fresult = round(fresult, prec) diff --git a/pandas/_libs/tslibs/conversion.pxd b/pandas/_libs/tslibs/conversion.pxd index 206e0171e0a55..ba03de6f0b81f 100644 --- a/pandas/_libs/tslibs/conversion.pxd +++ b/pandas/_libs/tslibs/conversion.pxd @@ -19,9 +19,9 @@ cdef class _TSObject: bint fold -cdef convert_to_tsobject(object ts, tzinfo tz, str unit, - bint dayfirst, bint yearfirst, - int32_t nanos=*) +cdef _TSObject convert_to_tsobject(object ts, tzinfo tz, str unit, + bint dayfirst, bint yearfirst, + int32_t nanos=*) cdef _TSObject convert_datetime_to_tsobject(datetime ts, tzinfo tz, int32_t nanos=*) diff --git a/pandas/_libs/tslibs/conversion.pyx b/pandas/_libs/tslibs/conversion.pyx index 457b27b293f11..cf85a5111e1a9 100644 --- a/pandas/_libs/tslibs/conversion.pyx +++ b/pandas/_libs/tslibs/conversion.pyx @@ -345,8 +345,8 @@ cdef class _TSObject: self.fold = 0 -cdef convert_to_tsobject(object ts, tzinfo tz, str unit, - bint dayfirst, bint yearfirst, int32_t nanos=0): +cdef _TSObject convert_to_tsobject(object ts, tzinfo tz, str unit, + bint dayfirst, bint yearfirst, int32_t nanos=0): """ Extract datetime and int64 from any of: - np.int64 (with unit providing a possible modifier) diff --git a/pandas/_libs/tslibs/dtypes.pxd b/pandas/_libs/tslibs/dtypes.pxd index f61409fc16653..8cc7bcb2a1aad 100644 --- a/pandas/_libs/tslibs/dtypes.pxd +++ b/pandas/_libs/tslibs/dtypes.pxd @@ -5,7 +5,7 @@ from pandas._libs.tslibs.np_datetime cimport NPY_DATETIMEUNIT cdef str npy_unit_to_abbrev(NPY_DATETIMEUNIT unit) cdef NPY_DATETIMEUNIT freq_group_code_to_npy_unit(int freq) nogil -cdef int64_t periods_per_day(NPY_DATETIMEUNIT reso=*) +cdef int64_t periods_per_day(NPY_DATETIMEUNIT reso=*) except? -1 cdef dict attrname_to_abbrevs diff --git a/pandas/_libs/tslibs/dtypes.pyx b/pandas/_libs/tslibs/dtypes.pyx index 48a06b2c01ae4..8f87bfe0b8c7c 100644 --- a/pandas/_libs/tslibs/dtypes.pyx +++ b/pandas/_libs/tslibs/dtypes.pyx @@ -307,7 +307,7 @@ cdef NPY_DATETIMEUNIT freq_group_code_to_npy_unit(int freq) nogil: return NPY_DATETIMEUNIT.NPY_FR_D -cdef int64_t periods_per_day(NPY_DATETIMEUNIT reso=NPY_DATETIMEUNIT.NPY_FR_ns): +cdef int64_t periods_per_day(NPY_DATETIMEUNIT reso=NPY_DATETIMEUNIT.NPY_FR_ns) except? -1: """ How many of the given time units fit into a single day? """ diff --git a/pandas/_libs/tslibs/offsets.pyx b/pandas/_libs/tslibs/offsets.pyx index 5a7f931292e7b..ce7246f7ab19e 100644 --- a/pandas/_libs/tslibs/offsets.pyx +++ b/pandas/_libs/tslibs/offsets.pyx @@ -1910,7 +1910,7 @@ cdef class WeekOfMonthMixin(SingleConstructorOffset): shifted = shift_month(other, months, "start") to_day = self._get_offset_day(shifted) - return shift_day(shifted, to_day - shifted.day) + return _shift_day(shifted, to_day - shifted.day) def is_on_offset(self, dt: datetime) -> bool: if self.normalize and not _is_normalized(dt): @@ -3132,7 +3132,7 @@ cdef class FY5253Quarter(FY5253Mixin): qtr_lens = self.get_weeks(norm) # check that qtr_lens is consistent with self._offset addition - end = shift_day(start, days=7 * sum(qtr_lens)) + end = _shift_day(start, days=7 * sum(qtr_lens)) assert self._offset.is_on_offset(end), (start, end, qtr_lens) tdelta = norm - start @@ -3173,7 +3173,7 @@ cdef class FY5253Quarter(FY5253Mixin): # Note: we always have 0 <= n < 4 weeks = sum(qtr_lens[:n]) if weeks: - res = shift_day(res, days=weeks * 7) + res = _shift_day(res, days=weeks * 7) return res @@ -3210,7 +3210,7 @@ cdef class FY5253Quarter(FY5253Mixin): current = next_year_end for qtr_len in qtr_lens: - current = shift_day(current, days=qtr_len * 7) + current = _shift_day(current, days=qtr_len * 7) if dt == current: return True return False @@ -3729,7 +3729,7 @@ cpdef to_offset(freq): # ---------------------------------------------------------------------- # RelativeDelta Arithmetic -def shift_day(other: datetime, days: int) -> datetime: +cdef datetime _shift_day(datetime other, int days): """ Increment the datetime `other` by the given number of days, retaining the time-portion of the datetime. For tz-naive datetimes this is @@ -3915,6 +3915,8 @@ cdef inline void _shift_quarters(const int64_t[:] dtindex, out[i] = dtstruct_to_dt64(&dts) +@cython.wraparound(False) +@cython.boundscheck(False) cdef ndarray[int64_t] _shift_bdays(const int64_t[:] i8other, int periods): """ Implementation of BusinessDay.apply_offset. diff --git a/pandas/_libs/tslibs/timedeltas.pxd b/pandas/_libs/tslibs/timedeltas.pxd index f054a22ed7ad7..f114fd9297920 100644 --- a/pandas/_libs/tslibs/timedeltas.pxd +++ b/pandas/_libs/tslibs/timedeltas.pxd @@ -15,4 +15,5 @@ cdef class _Timedelta(timedelta): int64_t _d, _h, _m, _s, _ms, _us, _ns cpdef timedelta to_pytimedelta(_Timedelta self) - cpdef bint _has_ns(self) + cdef bint _has_ns(self) + cdef _ensure_components(_Timedelta self) diff --git a/pandas/_libs/tslibs/timedeltas.pyx b/pandas/_libs/tslibs/timedeltas.pyx index b443ae283755c..7979feb076c6e 100644 --- a/pandas/_libs/tslibs/timedeltas.pyx +++ b/pandas/_libs/tslibs/timedeltas.pyx @@ -154,7 +154,7 @@ def ints_to_pytimedelta(const int64_t[:] arr, box=False): cdef: Py_ssize_t i, n = len(arr) int64_t value - object[:] result = np.empty(n, dtype=object) + object[::1] result = np.empty(n, dtype=object) for i in range(n): @@ -892,10 +892,10 @@ cdef class _Timedelta(timedelta): return cmp_scalar(self.value, ots.value, op) - cpdef bint _has_ns(self): + cdef bint _has_ns(self): return self.value % 1000 != 0 - def _ensure_components(_Timedelta self): + cdef _ensure_components(_Timedelta self): """ compute the components """ @@ -1160,7 +1160,10 @@ cdef class _Timedelta(timedelta): converted : string of a Timedelta """ - cdef object sign, seconds_pretty, subs, fmt, comp_dict + cdef: + str sign, fmt + dict comp_dict + object subs self._ensure_components() diff --git a/pandas/_libs/tslibs/timestamps.pxd b/pandas/_libs/tslibs/timestamps.pxd index 9b05fbc5be915..ce4c5d07ecc53 100644 --- a/pandas/_libs/tslibs/timestamps.pxd +++ b/pandas/_libs/tslibs/timestamps.pxd @@ -6,17 +6,18 @@ from numpy cimport int64_t from pandas._libs.tslibs.base cimport ABCTimestamp from pandas._libs.tslibs.np_datetime cimport npy_datetimestruct +from pandas._libs.tslibs.offsets cimport BaseOffset -cdef object create_timestamp_from_ts(int64_t value, - npy_datetimestruct dts, - tzinfo tz, object freq, bint fold) +cdef _Timestamp create_timestamp_from_ts(int64_t value, + npy_datetimestruct dts, + tzinfo tz, BaseOffset freq, bint fold) cdef class _Timestamp(ABCTimestamp): cdef readonly: int64_t value, nanosecond - object _freq + BaseOffset _freq cdef bint _get_start_end_field(self, str field, freq) cdef _get_date_name_field(self, str field, object locale) diff --git a/pandas/_libs/tslibs/timestamps.pyx b/pandas/_libs/tslibs/timestamps.pyx index 5ba28a9fae429..698e19f97c6aa 100644 --- a/pandas/_libs/tslibs/timestamps.pyx +++ b/pandas/_libs/tslibs/timestamps.pyx @@ -82,6 +82,7 @@ from pandas._libs.tslibs.np_datetime cimport ( from pandas._libs.tslibs.np_datetime import OutOfBoundsDatetime from pandas._libs.tslibs.offsets cimport ( + BaseOffset, is_offset_object, to_offset, ) @@ -113,9 +114,9 @@ _no_input = object() # ---------------------------------------------------------------------- -cdef inline object create_timestamp_from_ts(int64_t value, - npy_datetimestruct dts, - tzinfo tz, object freq, bint fold): +cdef inline _Timestamp create_timestamp_from_ts(int64_t value, + npy_datetimestruct dts, + tzinfo tz, BaseOffset freq, bint fold): """ convenience routine to construct a Timestamp from its parts """ cdef _Timestamp ts_base ts_base = _Timestamp.__new__(Timestamp, dts.year, dts.month, diff --git a/pandas/_libs/tslibs/timezones.pyx b/pandas/_libs/tslibs/timezones.pyx index 224c5be1f3b7d..6e3f7a370e5dd 100644 --- a/pandas/_libs/tslibs/timezones.pyx +++ b/pandas/_libs/tslibs/timezones.pyx @@ -230,10 +230,10 @@ cdef object _get_utc_trans_times_from_dateutil_tz(tzinfo tz): return new_trans -cdef int64_t[:] unbox_utcoffsets(object transinfo): +cdef int64_t[::1] unbox_utcoffsets(object transinfo): cdef: Py_ssize_t i, sz - int64_t[:] arr + int64_t[::1] arr sz = len(transinfo) arr = np.empty(sz, dtype='i8') diff --git a/pandas/_libs/tslibs/tzconversion.pyx b/pandas/_libs/tslibs/tzconversion.pyx index afcfe94a695bb..cee2de0cf0f4a 100644 --- a/pandas/_libs/tslibs/tzconversion.pyx +++ b/pandas/_libs/tslibs/tzconversion.pyx @@ -610,7 +610,7 @@ cdef int64_t _tz_localize_using_tzinfo_api( int64_t val, tzinfo tz, bint to_utc=True, bint* fold=NULL ) except? -1: """ - Convert the i8 representation of a datetime from a general-cast timezone to + Convert the i8 representation of a datetime from a general-case timezone to UTC, or vice-versa using the datetime/tzinfo API. Private, not intended for use outside of tslibs.tzconversion. diff --git a/pandas/core/arrays/datetimes.py b/pandas/core/arrays/datetimes.py index 9ffe33e0cf38e..e40acad0cb51a 100644 --- a/pandas/core/arrays/datetimes.py +++ b/pandas/core/arrays/datetimes.py @@ -2006,10 +2006,10 @@ def sequence_to_datetimes(data, require_iso8601: bool = False) -> DatetimeArray: def _sequence_to_dt64ns( data, dtype=None, - copy=False, + copy: bool = False, tz=None, - dayfirst=False, - yearfirst=False, + dayfirst: bool = False, + yearfirst: bool = False, ambiguous="raise", *, allow_mixed: bool = False,