diff --git a/pandas/_libs/tslibs/conversion.pyx b/pandas/_libs/tslibs/conversion.pyx index 5a8d0a0ec1670..6dd5b4b2fa798 100644 --- a/pandas/_libs/tslibs/conversion.pyx +++ b/pandas/_libs/tslibs/conversion.pyx @@ -265,7 +265,7 @@ cdef convert_to_tsobject(object ts, object tz, object unit, ts = ts except OverflowError: # GH#26651 re-raise as OutOfBoundsDatetime - raise OutOfBoundsDatetime(ts) + raise OutOfBoundsDatetime(f"Out of bounds nanosecond timestamp {ts}") if ts == NPY_NAT: obj.value = NPY_NAT else: diff --git a/pandas/tseries/offsets.py b/pandas/tseries/offsets.py index c1ab752bf9550..e1de9d1bcf832 100644 --- a/pandas/tseries/offsets.py +++ b/pandas/tseries/offsets.py @@ -8,7 +8,6 @@ from pandas._libs.tslibs import ( NaT, - OutOfBoundsDatetime, Period, Timedelta, Timestamp, @@ -16,9 +15,7 @@ conversion, delta_to_nanoseconds, frequencies as libfrequencies, - normalize_date, offsets as liboffsets, - timezones, ) from pandas._libs.tslibs.offsets import ( ApplyTypeError, @@ -76,73 +73,47 @@ "DateOffset", ] -# convert to/from datetime/timestamp to allow invalid Timestamp ranges to -# pass thru - - -def as_timestamp(obj): - if isinstance(obj, Timestamp): - return obj - try: - return Timestamp(obj) - except (OutOfBoundsDatetime): - pass - return obj - def apply_wraps(func): @functools.wraps(func) def wrapper(self, other): if other is NaT: return NaT - elif isinstance(other, (timedelta, Tick, DateOffset)): + elif isinstance(other, (timedelta, DateOffset)): # timedelta path return func(self, other) elif isinstance(other, (np.datetime64, datetime, date)): - other = as_timestamp(other) - - tz = getattr(other, "tzinfo", None) - nano = getattr(other, "nanosecond", 0) - - try: - if self._adjust_dst and isinstance(other, Timestamp): - other = other.tz_localize(None) - - result = func(self, other) - - if self._adjust_dst: - result = conversion.localize_pydatetime(result, tz) + other = Timestamp(other) + else: + raise TypeError(other) - result = Timestamp(result) - if self.normalize: - result = result.normalize() + tz = other.tzinfo + nano = other.nanosecond - # nanosecond may be deleted depending on offset process - if not self.normalize and nano != 0: - if not isinstance(self, Nano) and result.nanosecond != nano: - if result.tz is not None: - # convert to UTC - value = conversion.tz_convert_single( - result.value, timezones.UTC, result.tz - ) - else: - value = result.value - result = Timestamp(value + nano) + if self._adjust_dst: + other = other.tz_localize(None) - if tz is not None and result.tzinfo is None: - result = conversion.localize_pydatetime(result, tz) + result = func(self, other) - except OutOfBoundsDatetime: - result = func(self, as_datetime(other)) + result = Timestamp(result) + if self._adjust_dst: + result = result.tz_localize(tz) - if self.normalize: - # normalize_date returns normal datetime - result = normalize_date(result) + if self.normalize: + result = result.normalize() - if tz is not None and result.tzinfo is None: - result = conversion.localize_pydatetime(result, tz) + # nanosecond may be deleted depending on offset process + if not self.normalize and nano != 0: + if not isinstance(self, Nano) and result.nanosecond != nano: + if result.tz is not None: + # convert to UTC + value = result.tz_localize(None).value + else: + value = result.value + result = Timestamp(value + nano) - result = Timestamp(result) + if tz is not None and result.tzinfo is None: + result = result.tz_localize(tz) return result @@ -290,7 +261,7 @@ def apply(self, other): # bring tz back from UTC calculation other = conversion.localize_pydatetime(other, tzinfo) - return as_timestamp(other) + return Timestamp(other) else: return other + timedelta(self.n) @@ -394,7 +365,7 @@ def rollback(self, dt): TimeStamp Rolled timestamp if not on offset, otherwise unchanged timestamp. """ - dt = as_timestamp(dt) + dt = Timestamp(dt) if not self.is_on_offset(dt): dt = dt - type(self)(1, normalize=self.normalize, **self.kwds) return dt @@ -408,7 +379,7 @@ def rollforward(self, dt): TimeStamp Rolled timestamp if not on offset, otherwise unchanged timestamp. """ - dt = as_timestamp(dt) + dt = Timestamp(dt) if not self.is_on_offset(dt): dt = dt + type(self)(1, normalize=self.normalize, **self.kwds) return dt @@ -2505,7 +2476,7 @@ def apply(self, other): raise OverflowError return result elif isinstance(other, (datetime, np.datetime64, date)): - return as_timestamp(other) + self + return Timestamp(other) + self if isinstance(other, timedelta): return other + self.delta