Skip to content

Commit 392bd53

Browse files
committed
BUG: Allow unions of TZ and non-TZ aware indices
1 parent 2b13605 commit 392bd53

File tree

1 file changed

+43
-24
lines changed

1 file changed

+43
-24
lines changed

pandas/core/indexes/datetimes.py

+43-24
Original file line numberDiff line numberDiff line change
@@ -1094,37 +1094,56 @@ def unique(self, level=None):
10941094

10951095
def union(self, other):
10961096
"""
1097-
Specialized union for DatetimeIndex objects. If combine
1098-
overlapping ranges with the same DateOffset, will be much
1099-
faster than Index.union
1097+
Specialized union for `DatetimeIndex` objects.
1098+
1099+
If overlapping ranges with the same `DateOffset` are combined, this
1100+
will be much faster than `Index.union`.
11001101
11011102
Parameters
11021103
----------
11031104
other : DatetimeIndex or array-like
11041105
11051106
Returns
11061107
-------
1107-
y : Index or DatetimeIndex
1108+
index_union : Index or DatetimeIndex
11081109
"""
1110+
11091111
self._assert_can_do_setop(other)
1112+
11101113
if not isinstance(other, DatetimeIndex):
11111114
try:
11121115
other = DatetimeIndex(other)
11131116
except TypeError:
11141117
pass
11151118

1116-
this, other = self._maybe_utc_convert(other)
1119+
this = self
11171120

1118-
if this._can_fast_union(other):
1119-
return this._fast_union(other)
1120-
else:
1121-
result = Index.union(this, other)
1122-
if isinstance(result, DatetimeIndex):
1123-
result._tz = timezones.tz_standardize(this.tz)
1124-
if (result.freq is None and
1125-
(this.freq is not None or other.freq is not None)):
1126-
result.freq = to_offset(result.inferred_freq)
1127-
return result
1121+
try:
1122+
this, other = this._maybe_utc_convert(other)
1123+
1124+
if this._can_fast_union(other):
1125+
return this._fast_union(other)
1126+
except TypeError as e:
1127+
if "join tz-naive with tz-aware" in str(e):
1128+
# see gh-21671
1129+
#
1130+
# If one Index is TZ-aware, and the other
1131+
# is not, we just return an Index object.
1132+
this = this.astype(object)
1133+
other = other.astype(object)
1134+
else:
1135+
raise
1136+
1137+
result = Index.union(this, other)
1138+
1139+
if isinstance(result, DatetimeIndex):
1140+
result._tz = timezones.tz_standardize(this.tz)
1141+
1142+
if (result.freq is None and
1143+
(this.freq is not None or other.freq is not None)):
1144+
result.freq = to_offset(result.inferred_freq)
1145+
1146+
return result
11281147

11291148
def to_perioddelta(self, freq):
11301149
"""
@@ -1193,18 +1212,18 @@ def join(self, other, how='left', level=None, return_indexers=False,
11931212

11941213
def _maybe_utc_convert(self, other):
11951214
this = self
1215+
11961216
if isinstance(other, DatetimeIndex):
1197-
if self.tz is not None:
1198-
if other.tz is None:
1199-
raise TypeError('Cannot join tz-naive with tz-aware '
1200-
'DatetimeIndex')
1201-
elif other.tz is not None:
1202-
raise TypeError('Cannot join tz-naive with tz-aware '
1203-
'DatetimeIndex')
1217+
if ((self.tz is not None and other.tz is None) or
1218+
(self.tz is None and other.tz is not None)):
1219+
raise TypeError("Cannot join tz-naive with "
1220+
"tz-aware DatetimeIndex")
12041221

12051222
if not timezones.tz_compare(self.tz, other.tz):
1206-
this = self.tz_convert('UTC')
1207-
other = other.tz_convert('UTC')
1223+
utc_tz = "UTC"
1224+
this = self.tz_convert(utc_tz)
1225+
other = other.tz_convert(utc_tz)
1226+
12081227
return this, other
12091228

12101229
def _wrap_joined_index(self, joined, other):

0 commit comments

Comments
 (0)