Skip to content

Commit 1dafea5

Browse files
authored
PERF: DatetimeIndex.get_indexer with mismatched tz (#39332)
1 parent 56476d1 commit 1dafea5

File tree

3 files changed

+29
-7
lines changed

3 files changed

+29
-7
lines changed

asv_bench/benchmarks/indexing.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,20 @@ def time_loc_list(self, monotonic):
243243
monotonic.loc[80000:]
244244

245245

246+
class DatetimeIndexIndexing:
247+
def setup(self):
248+
dti = date_range("2016-01-01", periods=10000, tz="US/Pacific")
249+
dti2 = dti.tz_convert("UTC")
250+
self.dti = dti
251+
self.dti2 = dti2
252+
253+
def time_get_indexer_mismatched_tz(self):
254+
# reached via e.g.
255+
# ser = Series(range(len(dti)), index=dti)
256+
# ser[dti2]
257+
self.dti.get_indexer(self.dti2)
258+
259+
246260
class CategoricalIndexIndexing:
247261

248262
params = ["monotonic_incr", "monotonic_decr", "non_monotonic"]

pandas/core/indexes/base.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5166,7 +5166,16 @@ def _maybe_promote(self, other: Index):
51665166
if we can upcast the object-dtype one to improve performance.
51675167
"""
51685168

5169-
if self.inferred_type == "date" and isinstance(other, ABCDatetimeIndex):
5169+
if isinstance(self, ABCDatetimeIndex) and isinstance(other, ABCDatetimeIndex):
5170+
if (
5171+
self.tz is not None
5172+
and other.tz is not None
5173+
and not tz_compare(self.tz, other.tz)
5174+
):
5175+
# standardize on UTC
5176+
return self.tz_convert("UTC"), other.tz_convert("UTC")
5177+
5178+
elif self.inferred_type == "date" and isinstance(other, ABCDatetimeIndex):
51705179
try:
51715180
return type(other)(self), other
51725181
except OutOfBoundsDatetime:

pandas/core/indexes/datetimelike.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -815,11 +815,10 @@ def _fast_union(self: _T, other: _T, sort=None) -> _T:
815815
def _union(self, other, sort):
816816
# We are called by `union`, which is responsible for this validation
817817
assert isinstance(other, type(self))
818+
assert self.dtype == other.dtype
818819

819-
this, other = self._maybe_utc_convert(other)
820-
821-
if this._can_fast_union(other):
822-
result = this._fast_union(other, sort=sort)
820+
if self._can_fast_union(other):
821+
result = self._fast_union(other, sort=sort)
823822
if sort is None:
824823
# In the case where sort is None, _can_fast_union
825824
# implies that result.freq should match self.freq
@@ -851,9 +850,9 @@ def join(
851850
pother, how=how, level=level, return_indexers=return_indexers, sort=sort
852851
)
853852

854-
this, other = self._maybe_utc_convert(other)
853+
self._maybe_utc_convert(other) # raises if we dont have tzawareness compat
855854
return Index.join(
856-
this,
855+
self,
857856
other,
858857
how=how,
859858
level=level,

0 commit comments

Comments
 (0)