Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions pandas/_libs/tslibs/tzconversion.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -519,7 +519,7 @@ cdef ndarray[int64_t] _get_dst_hours(
trans_idx = mismatch.nonzero()[0]

if trans_idx.size == 1:
# TODO: not reached in tests 2022-05-02; possible?
# see test_tz_localize_to_utc_ambiguous_infer
stamp = _render_tstamp(vals[trans_idx[0]], reso=reso)
raise pytz.AmbiguousTimeError(
f"Cannot infer dst time from {stamp} as there "
Expand All @@ -541,15 +541,15 @@ cdef ndarray[int64_t] _get_dst_hours(

delta = np.diff(result_a[grp])
if grp.size == 1 or np.all(delta > 0):
# TODO: not reached in tests 2022-05-02; possible?
# see test_tz_localize_to_utc_ambiguous_infer
stamp = _render_tstamp(vals[grp[0]], reso=reso)
raise pytz.AmbiguousTimeError(stamp)

# Find the index for the switch and pull from a for dst and b
# for standard
switch_idxs = (delta <= 0).nonzero()[0]
if switch_idxs.size > 1:
# TODO: not reached in tests 2022-05-02; possible?
# see test_tz_localize_to_utc_ambiguous_infer
raise pytz.AmbiguousTimeError(
f"There are {switch_idxs.size} dst switches when "
"there should only be 1."
Expand Down
20 changes: 10 additions & 10 deletions pandas/core/arrays/datetimelike.py
Original file line number Diff line number Diff line change
Expand Up @@ -1088,12 +1088,13 @@ def _cmp_method(self, other, op):

@final
def _add_datetimelike_scalar(self, other):
# Overridden by TimedeltaArray
if not is_timedelta64_dtype(self.dtype):
raise TypeError(
f"cannot add {type(self).__name__} and {type(other).__name__}"
)

self = cast("TimedeltaArray", self)

from pandas.core.arrays import DatetimeArray

assert other is not NaT
Expand All @@ -1111,7 +1112,7 @@ def _add_datetimelike_scalar(self, other):
return DatetimeArray(result, dtype=dtype, freq=self.freq)

@final
def _add_datetime_arraylike(self, other):
def _add_datetime_arraylike(self, other) -> DatetimeArray:
if not is_timedelta64_dtype(self.dtype):
raise TypeError(
f"cannot add {type(self).__name__} and {type(other).__name__}"
Expand Down Expand Up @@ -1176,24 +1177,24 @@ def _sub_datetime_arraylike(self, other):
return new_values.view("timedelta64[ns]")

@final
def _sub_period(self, other: Period):
def _sub_period(self, other: Period) -> npt.NDArray[np.object_]:
if not is_period_dtype(self.dtype):
raise TypeError(f"cannot subtract Period from a {type(self).__name__}")

# If the operation is well-defined, we return an object-dtype ndarray
# of DateOffsets. Null entries are filled with pd.NaT
self._check_compatible_with(other)
asi8 = self.asi8
new_data = asi8 - other.ordinal
new_data = np.array([self.freq.base * x for x in new_data])
new_i8_data = asi8 - other.ordinal # TODO: checked_add_with_arr
new_data = np.array([self.freq.base * x for x in new_i8_data])

if self._hasna:
new_data[self._isnan] = NaT

return new_data

@final
def _add_period(self, other: Period):
def _add_period(self, other: Period) -> PeriodArray:
if not is_timedelta64_dtype(self.dtype):
raise TypeError(f"cannot add Period to a {type(self).__name__}")

Expand Down Expand Up @@ -1683,12 +1684,11 @@ def median(self, *, axis: int | None = None, skipna: bool = True, **kwargs):
return self._wrap_reduction_result(axis, result)

def _mode(self, dropna: bool = True):
values = self
mask = None
if dropna:
mask = values.isna()
values = values[~mask]
mask = self.isna()

i8modes = mode(values.view("i8"))
i8modes = mode(self.view("i8"), mask=mask)
npmodes = i8modes.view(self._ndarray.dtype)
npmodes = cast(np.ndarray, npmodes)
return self._from_backing_data(npmodes)
Expand Down
23 changes: 23 additions & 0 deletions pandas/tests/tslibs/test_tzconversion.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import numpy as np
import pytest
import pytz

from pandas._libs.tslibs.tzconversion import tz_localize_to_utc


class TestTZLocalizeToUTC:
def test_tz_localize_to_utc_ambiguous_infer(self):
# val is a timestamp that is ambiguous when localized to US/Eastern
val = 1_320_541_200_000_000_000
vals = np.array([val, val - 1, val], dtype=np.int64)

with pytest.raises(pytz.AmbiguousTimeError, match="2011-11-06 01:00:00"):
tz_localize_to_utc(vals, pytz.timezone("US/Eastern"), ambiguous="infer")

with pytest.raises(pytz.AmbiguousTimeError, match="are no repeated times"):
tz_localize_to_utc(vals[:1], pytz.timezone("US/Eastern"), ambiguous="infer")

vals[1] += 1
msg = "There are 2 dst switches when there should only be 1"
with pytest.raises(pytz.AmbiguousTimeError, match=msg):
tz_localize_to_utc(vals, pytz.timezone("US/Eastern"), ambiguous="infer")