diff --git a/pandas/_libs/lib.pyx b/pandas/_libs/lib.pyx index f844ad45c7026..658f7fb202531 100644 --- a/pandas/_libs/lib.pyx +++ b/pandas/_libs/lib.pyx @@ -75,7 +75,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.period cimport is_period_object +from pandas._libs.tslibs.base cimport is_period_object from pandas._libs.missing cimport ( checknull, diff --git a/pandas/_libs/tslibs/conversion.pyx b/pandas/_libs/tslibs/conversion.pyx index 264861ef8a2d4..0721f4cdbf911 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 +from pandas._libs.tslibs.base cimport ABCTimestamp, is_period_object from pandas._libs.tslibs.np_datetime cimport ( check_dts_bounds, npy_datetimestruct, pandas_datetime_to_datetimestruct, @@ -37,10 +37,11 @@ from pandas._libs.tslibs.nattype import nat_strings from pandas._libs.tslibs.nattype cimport ( NPY_NAT, checknull_with_nat, c_NaT as NaT) -from pandas._libs.tslibs.tzconversion import ( - tz_localize_to_utc, tz_convert_single) +from pandas._libs.tslibs.tzconversion import tz_localize_to_utc from pandas._libs.tslibs.tzconversion cimport ( - _tz_convert_tzlocal_utc, _tz_convert_tzlocal_fromutc) + _tz_convert_tzlocal_utc, _tz_convert_tzlocal_fromutc, + tz_convert_single +) # ---------------------------------------------------------------------- # Constants @@ -286,7 +287,7 @@ 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 getattr(ts, '_typ', None) == 'period': + elif is_period_object(ts): raise ValueError("Cannot convert Period to Timestamp " "unambiguously. Use to_timestamp") else: diff --git a/pandas/_libs/tslibs/frequencies.pyx b/pandas/_libs/tslibs/frequencies.pyx index 31747f96399ee..41de364c392f7 100644 --- a/pandas/_libs/tslibs/frequencies.pyx +++ b/pandas/_libs/tslibs/frequencies.pyx @@ -3,7 +3,7 @@ import re cimport numpy as cnp cnp.import_array() -from pandas._libs.tslibs.util cimport is_integer_object +from pandas._libs.tslibs.util cimport is_integer_object, is_offset_object from pandas._libs.tslibs.ccalendar import MONTH_NUMBERS @@ -153,7 +153,7 @@ cpdef get_freq_code(freqstr): >>> get_freq_code(('D', 3)) (6000, 3) """ - if getattr(freqstr, '_typ', None) == 'dateoffset': + if is_offset_object(freqstr): freqstr = (freqstr.rule_code, freqstr.n) if isinstance(freqstr, tuple): @@ -451,8 +451,8 @@ cdef str _maybe_coerce_freq(code): code : string """ assert code is not None - if getattr(code, '_typ', None) == 'dateoffset': - # i.e. isinstance(code, ABCDateOffset): + if is_offset_object(code): + # i.e. isinstance(code, DateOffset): code = code.rule_code return code.upper() diff --git a/pandas/_libs/tslibs/nattype.pyx b/pandas/_libs/tslibs/nattype.pyx index a45e10e8337a4..79af440128010 100644 --- a/pandas/_libs/tslibs/nattype.pyx +++ b/pandas/_libs/tslibs/nattype.pyx @@ -15,11 +15,10 @@ from cpython.datetime cimport ( datetime, timedelta, ) +PyDateTime_IMPORT from cpython.version cimport PY_MINOR_VERSION -PyDateTime_IMPORT - import numpy as np cimport numpy as cnp from numpy cimport int64_t @@ -30,6 +29,7 @@ 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 from pandas._libs.missing cimport C_NA @@ -150,7 +150,7 @@ cdef class _NaT(datetime): elif util.is_offset_object(other): return c_NaT - elif util.is_integer_object(other) or util.is_period_object(other): + elif util.is_integer_object(other) or is_period_object(other): # For Period compat # TODO: the integer behavior is deprecated, remove it return c_NaT @@ -186,7 +186,7 @@ cdef class _NaT(datetime): elif util.is_offset_object(other): return c_NaT - elif util.is_integer_object(other) or util.is_period_object(other): + elif util.is_integer_object(other) or is_period_object(other): # For Period compat # TODO: the integer behavior is deprecated, remove it return c_NaT diff --git a/pandas/_libs/tslibs/offsets.pyx b/pandas/_libs/tslibs/offsets.pyx index ff0d96f0f2525..0c9e0e2f7d2de 100644 --- a/pandas/_libs/tslibs/offsets.pyx +++ b/pandas/_libs/tslibs/offsets.pyx @@ -435,12 +435,12 @@ class _BaseOffset: return self.apply(other) def __mul__(self, other): - if hasattr(other, "_typ"): - return NotImplemented if util.is_array(other): return np.array([self * x for x in other]) - return type(self)(n=other * self.n, normalize=self.normalize, - **self.kwds) + elif is_integer_object(other): + return type(self)(n=other * self.n, normalize=self.normalize, + **self.kwds) + return NotImplemented def __neg__(self): # Note: we are deferring directly to __mul__ instead of __rmul__, as diff --git a/pandas/_libs/tslibs/parsing.pyx b/pandas/_libs/tslibs/parsing.pyx index 5fda0db4891c3..c31d4d92c6054 100644 --- a/pandas/_libs/tslibs/parsing.pyx +++ b/pandas/_libs/tslibs/parsing.pyx @@ -34,7 +34,11 @@ from pandas._config import get_option from pandas._libs.tslibs.ccalendar import MONTH_NUMBERS from pandas._libs.tslibs.nattype import nat_strings, NaT -from pandas._libs.tslibs.util cimport is_array, get_c_string_buf_and_size +from pandas._libs.tslibs.util cimport ( + is_array, + is_offset_object, + get_c_string_buf_and_size, +) from pandas._libs.tslibs.frequencies cimport get_rule_month cdef extern from "../src/headers/portable.h": @@ -262,7 +266,7 @@ def parse_time_string(arg: str, freq=None, dayfirst=None, yearfirst=None): if not isinstance(arg, str): raise TypeError("parse_time_string argument must be str") - if getattr(freq, "_typ", None) == "dateoffset": + if is_offset_object(freq): freq = freq.rule_code if dayfirst is None or yearfirst is None: diff --git a/pandas/_libs/tslibs/period.pxd b/pandas/_libs/tslibs/period.pxd deleted file mode 100644 index eb11a4a572e85..0000000000000 --- a/pandas/_libs/tslibs/period.pxd +++ /dev/null @@ -1 +0,0 @@ -cdef bint is_period_object(object obj) diff --git a/pandas/_libs/tslibs/period.pyx b/pandas/_libs/tslibs/period.pyx index 3c02cda651728..c5f48fdc8c411 100644 --- a/pandas/_libs/tslibs/period.pyx +++ b/pandas/_libs/tslibs/period.pyx @@ -37,7 +37,7 @@ cdef extern from "src/datetime/np_datetime.h": cimport pandas._libs.tslibs.util as util -from pandas._libs.tslibs.base cimport ABCPeriod +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 @@ -2452,15 +2452,6 @@ class Period(_Period): return cls._from_ordinal(ordinal, freq) -cdef bint is_period_object(object obj): - """ - Cython-optimized equivalent of isinstance(obj, Period) - """ - # Note: this is significantly faster than the implementation in tslibs.util, - # only use the util version when necessary to prevent circular imports. - 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) diff --git a/pandas/_libs/tslibs/resolution.pyx b/pandas/_libs/tslibs/resolution.pyx index ecf31c15bb72c..80a3466f5a1aa 100644 --- a/pandas/_libs/tslibs/resolution.pyx +++ b/pandas/_libs/tslibs/resolution.pyx @@ -1,7 +1,7 @@ import numpy as np from numpy cimport ndarray, int64_t, int32_t -from pandas._libs.tslibs.util cimport get_nat +from pandas._libs.tslibs.util cimport get_nat, is_offset_object from pandas._libs.tslibs.np_datetime cimport ( npy_datetimestruct, dt64_to_dtstruct) @@ -118,7 +118,7 @@ def get_freq_group(freq) -> int: >>> get_freq_group('W-FRI') 4000 """ - if getattr(freq, '_typ', None) == 'dateoffset': + if is_offset_object(freq): freq = freq.rule_code if isinstance(freq, str): diff --git a/pandas/_libs/tslibs/util.pxd b/pandas/_libs/tslibs/util.pxd index cc98781dc73cf..eb535a994e538 100644 --- a/pandas/_libs/tslibs/util.pxd +++ b/pandas/_libs/tslibs/util.pxd @@ -168,21 +168,6 @@ cdef inline bint is_array(object val): return PyArray_Check(val) -cdef inline bint is_period_object(object val): - """ - Cython equivalent of `isinstance(val, pd.Period)` - - Parameters - ---------- - val : object - - Returns - ------- - is_period : bool - """ - return getattr(val, '_typ', '_typ') == 'period' - - cdef inline bint is_offset_object(object val): """ Check if an object is a DateOffset object. diff --git a/pandas/core/resample.py b/pandas/core/resample.py index 06751d9c35fab..6cd28965dfca8 100644 --- a/pandas/core/resample.py +++ b/pandas/core/resample.py @@ -1700,8 +1700,8 @@ def _get_period_range_edges(first, last, offset, closed="left", base=0): first, last, offset, closed=closed, base=base ) - first = (first + adjust_first * offset).to_period(offset) - last = (last - adjust_last * offset).to_period(offset) + first = (first + int(adjust_first) * offset).to_period(offset) + last = (last - int(adjust_last) * offset).to_period(offset) return first, last diff --git a/pandas/tests/tslibs/test_conversion.py b/pandas/tests/tslibs/test_conversion.py index d0066988faec7..fd8c9df026674 100644 --- a/pandas/tests/tslibs/test_conversion.py +++ b/pandas/tests/tslibs/test_conversion.py @@ -12,7 +12,7 @@ def _compare_utc_to_local(tz_didx): def f(x): - return conversion.tz_convert_single(x, UTC, tz_didx.tz) + return tzconversion.tz_convert_single(x, UTC, tz_didx.tz) result = tzconversion.tz_convert(tz_didx.asi8, UTC, tz_didx.tz) expected = np.vectorize(f)(tz_didx.asi8) @@ -22,7 +22,7 @@ def f(x): def _compare_local_to_utc(tz_didx, utc_didx): def f(x): - return conversion.tz_convert_single(x, tz_didx.tz, UTC) + return tzconversion.tz_convert_single(x, tz_didx.tz, UTC) result = tzconversion.tz_convert(utc_didx.asi8, tz_didx.tz, UTC) expected = np.vectorize(f)(utc_didx.asi8)