diff --git a/pandas/_libs/tslibs/offsets.pyx b/pandas/_libs/tslibs/offsets.pyx index 77b60d0c22322..f37705b255298 100644 --- a/pandas/_libs/tslibs/offsets.pyx +++ b/pandas/_libs/tslibs/offsets.pyx @@ -31,8 +31,6 @@ from pandas._libs.tslibs.util cimport ( is_float_object, ) -from pandas._libs.tslibs.base cimport ABCTimestamp - from pandas._libs.tslibs.ccalendar import ( MONTH_ALIASES, MONTH_TO_CAL_NUM, weekday_to_int, int_to_weekday, ) @@ -49,7 +47,9 @@ from pandas._libs.tslibs.timezones cimport utc_pytz as UTC from pandas._libs.tslibs.tzconversion cimport tz_convert_single from .timedeltas cimport delta_to_nanoseconds - +from .timedeltas import Timedelta +from .timestamps cimport _Timestamp +from .timestamps import Timestamp # --------------------------------------------------------------------- # Misc Helpers @@ -63,7 +63,7 @@ cdef bint is_tick_object(object obj): cdef datetime _as_datetime(datetime obj): - if isinstance(obj, ABCTimestamp): + if isinstance(obj, _Timestamp): return obj.to_pydatetime() return obj @@ -72,7 +72,7 @@ cdef bint _is_normalized(datetime dt): if dt.hour != 0 or dt.minute != 0 or dt.second != 0 or dt.microsecond != 0: # Regardless of whether dt is datetime vs Timestamp return False - if isinstance(dt, ABCTimestamp): + if isinstance(dt, _Timestamp): return dt.nanosecond == 0 return True @@ -107,7 +107,6 @@ def apply_wraps(func): # not play nicely with cython class methods def wrapper(self, other): - from pandas import Timestamp if other is NaT: return NaT @@ -584,7 +583,6 @@ cdef class BaseOffset: TimeStamp Rolled timestamp if not on offset, otherwise unchanged timestamp. """ - from pandas import Timestamp dt = Timestamp(dt) if not self.is_on_offset(dt): dt = dt - type(self)(1, normalize=self.normalize, **self.kwds) @@ -599,7 +597,6 @@ cdef class BaseOffset: TimeStamp Rolled timestamp if not on offset, otherwise unchanged timestamp. """ - from pandas import Timestamp dt = Timestamp(dt) if not self.is_on_offset(dt): dt = dt + type(self)(1, normalize=self.normalize, **self.kwds) @@ -766,7 +763,6 @@ cdef class Tick(SingleConstructorOffset): @property def delta(self): - from .timedeltas import Timedelta return self.n * Timedelta(self._nanos_inc) @property @@ -853,7 +849,7 @@ cdef class Tick(SingleConstructorOffset): def apply(self, other): # Timestamp can handle tz and nano sec, thus no need to use apply_wraps - if isinstance(other, ABCTimestamp): + if isinstance(other, _Timestamp): # GH#15126 # in order to avoid a recursive @@ -868,7 +864,6 @@ cdef class Tick(SingleConstructorOffset): return NaT elif is_datetime64_object(other) or PyDate_Check(other): # PyDate_Check includes date, datetime - from pandas import Timestamp return Timestamp(other) + self if PyDelta_Check(other): @@ -1020,7 +1015,6 @@ cdef class RelativeDeltaOffset(BaseOffset): # bring tz back from UTC calculation other = localize_pydatetime(other, tzinfo) - from .timestamps import Timestamp return Timestamp(other) else: return other + timedelta(self.n) @@ -1069,7 +1063,6 @@ cdef class RelativeDeltaOffset(BaseOffset): if k in ["days", "hours", "minutes", "seconds", "microseconds"] } if timedelta_kwds: - from .timedeltas import Timedelta delta = Timedelta(**timedelta_kwds) index = index + (self.n * delta) return index @@ -2265,7 +2258,6 @@ cdef class SemiMonthOffset(SingleConstructorOffset): @apply_index_wraps def apply_index(self, dtindex): # determine how many days away from the 1st of the month we are - from pandas import Timedelta dti = dtindex i8other = dtindex.asi8 @@ -2368,8 +2360,6 @@ cdef class SemiMonthEnd(SemiMonthOffset): ------- result : DatetimeIndex """ - from pandas import Timedelta - nanos = (roll % 2) * Timedelta(days=self.day_of_month).value dtindex += nanos.astype("timedelta64[ns]") return dtindex + Timedelta(days=-1) @@ -2427,7 +2417,6 @@ cdef class SemiMonthBegin(SemiMonthOffset): ------- result : DatetimeIndex """ - from pandas import Timedelta nanos = (roll % 2) * Timedelta(days=self.day_of_month - 1).value return dtindex + nanos.astype("timedelta64[ns]") @@ -2516,7 +2505,6 @@ cdef class Week(SingleConstructorOffset): ------- result : DatetimeIndex """ - from pandas import Timedelta from .frequencies import get_freq_code # TODO: avoid circular import i8other = dtindex.asi8 @@ -2818,8 +2806,6 @@ cdef class FY5253(FY5253Mixin): @apply_wraps def apply(self, other): - from pandas import Timestamp - norm = Timestamp(other).normalize() n = self.n @@ -3040,8 +3026,6 @@ cdef class FY5253Quarter(FY5253Mixin): num_qtrs : int tdelta : Timedelta """ - from pandas import Timestamp, Timedelta - num_qtrs = 0 norm = Timestamp(other).tz_localize(None) @@ -3072,7 +3056,6 @@ cdef class FY5253Quarter(FY5253Mixin): @apply_wraps def apply(self, other): # Note: self.n == 0 is not allowed. - from pandas import Timedelta n = self.n @@ -3112,8 +3095,6 @@ cdef class FY5253Quarter(FY5253Mixin): def year_has_extra_week(self, dt: datetime) -> bool: # Avoid round-down errors --> normalize to get # e.g. '370D' instead of '360D23H' - from pandas import Timestamp - norm = Timestamp(dt).normalize().tz_localize(None) next_year_end = self._offset.rollforward(norm) @@ -3592,9 +3573,6 @@ cpdef to_offset(freq): >>> to_offset(Hour()) """ - # TODO: avoid runtime imports - from pandas._libs.tslibs.timedeltas import Timedelta - if freq is None: return None diff --git a/pandas/_libs/tslibs/tzconversion.pyx b/pandas/_libs/tslibs/tzconversion.pyx index a90d06fa53997..02fe203637d62 100644 --- a/pandas/_libs/tslibs/tzconversion.pyx +++ b/pandas/_libs/tslibs/tzconversion.pyx @@ -20,7 +20,6 @@ from pandas._libs.tslibs.ccalendar cimport DAY_NANOS, HOUR_NANOS from pandas._libs.tslibs.nattype cimport NPY_NAT from pandas._libs.tslibs.np_datetime cimport ( npy_datetimestruct, dt64_to_dtstruct) -from pandas._libs.tslibs.timedeltas cimport delta_to_nanoseconds from pandas._libs.tslibs.timezones cimport ( get_dst_info, is_tzlocal, is_utc, get_timezone, get_utcoffset) @@ -123,6 +122,7 @@ timedelta-like} elif nonexistent == 'shift_backward': shift_backward = True elif PyDelta_Check(nonexistent): + from .timedeltas import delta_to_nanoseconds shift_delta = delta_to_nanoseconds(nonexistent) elif nonexistent not in ('raise', None): msg = ("nonexistent must be one of {'NaT', 'raise', 'shift_forward', "