Skip to content

Commit 945445d

Browse files
jbrockmendeljreback
authored andcommitted
Make DTI[tz]._values and Series[tz]._values return DTA (pandas-dev#24534)
1 parent d659e7d commit 945445d

File tree

6 files changed

+33
-22
lines changed

6 files changed

+33
-22
lines changed

pandas/core/dtypes/concat.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -426,8 +426,7 @@ def _concat_datetime(to_concat, axis=0, typs=None):
426426
if any(typ.startswith('datetime') for typ in typs):
427427

428428
if 'datetime' in typs:
429-
to_concat = [np.array(x, copy=False).view(np.int64)
430-
for x in to_concat]
429+
to_concat = [x.astype(np.int64, copy=False) for x in to_concat]
431430
return _concatenate_2d(to_concat, axis=axis).view(_NS_DTYPE)
432431
else:
433432
# when to_concat has different tz, len(typs) > 1.
@@ -451,7 +450,7 @@ def _convert_datetimelike_to_object(x):
451450
# if dtype is of datetimetz or timezone
452451
if x.dtype.kind == _NS_DTYPE.kind:
453452
if getattr(x, 'tz', None) is not None:
454-
x = x.astype(object).values
453+
x = np.asarray(x.astype(object))
455454
else:
456455
shape = x.shape
457456
x = tslib.ints_to_pydatetime(x.view(np.int64).ravel(),

pandas/core/indexes/datetimes.py

+10-1
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,12 @@ def _simple_new(cls, values, name=None, freq=None, tz=None, dtype=None):
316316
we require the we have a dtype compat for the values
317317
if we are passed a non-dtype compat, then coerce using the constructor
318318
"""
319+
if isinstance(values, DatetimeArray):
320+
values = DatetimeArray(values, freq=freq, tz=tz, dtype=dtype)
321+
tz = values.tz
322+
freq = values.freq
323+
values = values._data
324+
319325
# DatetimeArray._simple_new will accept either i8 or M8[ns] dtypes
320326
assert isinstance(values, np.ndarray), type(values)
321327

@@ -340,7 +346,7 @@ def _values(self):
340346
# tz-naive -> ndarray
341347
# tz-aware -> DatetimeIndex
342348
if self.tz is not None:
343-
return self
349+
return self._eadata
344350
else:
345351
return self.values
346352

@@ -629,6 +635,9 @@ def intersection(self, other):
629635
not other.freq.isAnchored() or
630636
(not self.is_monotonic or not other.is_monotonic)):
631637
result = Index.intersection(self, other)
638+
# Invalidate the freq of `result`, which may not be correct at
639+
# this point, depending on the values.
640+
result.freq = None
632641
result = self._shallow_copy(result._values, name=result.name,
633642
tz=result.tz, freq=None)
634643
if result.freq is None:

pandas/core/internals/blocks.py

+12-4
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@
3434
_isna_compat, array_equivalent, is_null_datelike_scalar, isna, notna)
3535

3636
import pandas.core.algorithms as algos
37-
from pandas.core.arrays import Categorical, ExtensionArray
37+
from pandas.core.arrays import (
38+
Categorical, DatetimeArrayMixin as DatetimeArray, ExtensionArray)
3839
from pandas.core.base import PandasObject
3940
import pandas.core.common as com
4041
from pandas.core.indexes.datetimes import DatetimeIndex
@@ -2437,8 +2438,14 @@ def _try_coerce_args(self, values, other):
24372438
""" provide coercion to our input arguments """
24382439

24392440
if isinstance(other, ABCDatetimeIndex):
2440-
# to store DatetimeTZBlock as object
2441-
other = other.astype(object).values
2441+
# May get a DatetimeIndex here. Unbox it.
2442+
other = other.array
2443+
2444+
if isinstance(other, DatetimeArray):
2445+
# hit in pandas/tests/indexing/test_coercion.py
2446+
# ::TestWhereCoercion::test_where_series_datetime64[datetime64tz]
2447+
# when falling back to ObjectBlock.where
2448+
other = other.astype(object)
24422449

24432450
return values, other
24442451

@@ -2985,7 +2992,8 @@ def _try_coerce_args(self, values, other):
29852992
elif (is_null_datelike_scalar(other) or
29862993
(lib.is_scalar(other) and isna(other))):
29872994
other = tslibs.iNaT
2988-
elif isinstance(other, self._holder):
2995+
elif isinstance(other, (self._holder, DatetimeArray)):
2996+
# TODO: DatetimeArray check will be redundant after GH#24024
29892997
if other.tz != self.values.tz:
29902998
raise ValueError("incompatible or non tz-aware value")
29912999
other = _block_shape(other.asi8, ndim=self.ndim)

pandas/core/series.py

+4-5
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,10 @@ def _values(self):
477477
"""
478478
Return the internal repr of this data.
479479
"""
480-
return self._data.internal_values()
480+
result = self._data.internal_values()
481+
if isinstance(result, DatetimeIndex):
482+
result = result._eadata
483+
return result
481484

482485
def _formatting_values(self):
483486
"""
@@ -1602,10 +1605,6 @@ def unique(self):
16021605
Categories (3, object): [a < b < c]
16031606
"""
16041607
result = super(Series, self).unique()
1605-
if isinstance(result, DatetimeIndex):
1606-
# TODO: This should be unnecessary after Series._values returns
1607-
# DatetimeArray
1608-
result = result._eadata
16091608
return result
16101609

16111610
def drop_duplicates(self, keep='first', inplace=False):

pandas/tests/indexing/test_coercion.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ def has_test(combo):
3131
for combo in combos:
3232
if not has_test(combo):
3333
msg = 'test method is not defined: {0}, {1}'
34-
raise AssertionError(msg.format(type(cls), combo))
34+
raise AssertionError(msg.format(cls.__name__, combo))
3535

3636
yield
3737

pandas/tests/test_base.py

+4-8
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,12 @@
1717
PeriodIndex, Timedelta, IntervalIndex, Interval,
1818
CategoricalIndex, Timestamp, DataFrame, Panel)
1919
from pandas.core.arrays import (
20+
PandasArray,
2021
DatetimeArrayMixin as DatetimeArray,
2122
TimedeltaArrayMixin as TimedeltaArray,
2223
)
2324
from pandas.compat import StringIO, PYPY, long
2425
from pandas.compat.numpy import np_array_datetime64_compat
25-
from pandas.core.arrays import PandasArray
2626
from pandas.core.accessor import PandasDelegate
2727
from pandas.core.base import PandasObject, NoNewAttributesMixin
2828
from pandas.core.indexes.datetimelike import DatetimeIndexOpsMixin
@@ -388,11 +388,9 @@ def test_value_counts_unique_nunique(self):
388388
for r in result:
389389
assert isinstance(r, Timestamp)
390390

391-
# TODO(#24024) once orig._values returns DTA, remove
392-
# the `._eadata` below
393391
tm.assert_numpy_array_equal(
394392
result.astype(object),
395-
orig._values._eadata.astype(object))
393+
orig._values.astype(object))
396394
else:
397395
tm.assert_numpy_array_equal(result, orig.values)
398396

@@ -418,9 +416,7 @@ def test_value_counts_unique_nunique_null(self):
418416
else:
419417
o = o.copy()
420418
o[0:2] = iNaT
421-
# TODO(#24024) once Series._values returns DTA, remove
422-
# the `._eadata` here
423-
values = o._values._eadata
419+
values = o._values
424420

425421
elif needs_i8_conversion(o):
426422
values[0:2] = iNaT
@@ -1158,7 +1154,7 @@ def test_iter_box(self):
11581154
(np.array(['a', 'b']), np.ndarray, 'object'),
11591155
(pd.Categorical(['a', 'b']), pd.Categorical, 'category'),
11601156
(pd.DatetimeIndex(['2017', '2018']), np.ndarray, 'datetime64[ns]'),
1161-
(pd.DatetimeIndex(['2017', '2018'], tz="US/Central"), pd.DatetimeIndex,
1157+
(pd.DatetimeIndex(['2017', '2018'], tz="US/Central"), DatetimeArray,
11621158
'datetime64[ns, US/Central]'),
11631159
(pd.TimedeltaIndex([10**10]), np.ndarray, 'm8[ns]'),
11641160
(pd.PeriodIndex([2018, 2019], freq='A'), pd.core.arrays.PeriodArray,

0 commit comments

Comments
 (0)