diff --git a/pandas/core/arrays/timedeltas.py b/pandas/core/arrays/timedeltas.py index 47b3f93f88b781..be1a7097b0e0d3 100644 --- a/pandas/core/arrays/timedeltas.py +++ b/pandas/core/arrays/timedeltas.py @@ -15,8 +15,8 @@ from pandas.util._decorators import Appender from pandas.core.dtypes.common import ( - _NS_DTYPE, _TD_DTYPE, ensure_int64, is_datetime64_dtype, is_dtype_equal, - is_float_dtype, is_integer_dtype, is_list_like, is_object_dtype, is_scalar, + _NS_DTYPE, _TD_DTYPE, ensure_int64, is_datetime64_dtype, is_float_dtype, + is_integer_dtype, is_list_like, is_object_dtype, is_scalar, is_string_dtype, is_timedelta64_dtype, is_timedelta64_ns_dtype, pandas_dtype) from pandas.core.dtypes.dtypes import DatetimeTZDtype @@ -134,28 +134,61 @@ def dtype(self): _attributes = ["freq"] def __init__(self, values, dtype=_TD_DTYPE, freq=None, copy=False): - if not hasattr(values, "dtype"): - raise ValueError( + if isinstance(values, (ABCSeries, ABCIndexClass)): + values = values._values + + inferred_freq = getattr(values, "_freq", None) + + if isinstance(values, type(self)): + if freq is None: + freq = values.freq + elif freq and values.freq: + freq = to_offset(freq) + freq, _ = dtl.validate_inferred_freq(freq, values.freq, False) + values = values._data + + if not isinstance(values, np.ndarray): + msg = ( "Unexpected type '{}'. 'values' must be a TimedeltaArray " "ndarray, or Series or Index containing one of those." - .format(type(values).__name__)) + ) + raise ValueError(msg.format(type(values).__name__)) + + if values.dtype == 'i8': + # for compat with datetime/timedelta/period shared methods, + # we can sometimes get here with int64 values. These represent + # nanosecond UTC (or tz-naive) unix timestamps + values = values.view(_TD_DTYPE) + + if values.dtype != _TD_DTYPE: + raise TypeError(_BAD_DTYPE.format(dtype=values.dtype)) + + try: + dtype_mismatch = dtype != _TD_DTYPE + except TypeError: + raise TypeError(_BAD_DTYPE.format(dtype=dtype)) + else: + if dtype_mismatch: + raise TypeError(_BAD_DTYPE.format(dtype=dtype)) + if freq == "infer": - raise ValueError( + msg = ( "Frequency inference not allowed in TimedeltaArray.__init__. " - "Use 'pd.array()' instead.") + "Use 'pd.array()' instead." + ) + raise ValueError(msg) - if dtype is not None and not is_dtype_equal(dtype, _TD_DTYPE): - raise TypeError("dtype {dtype} cannot be converted to " - "timedelta64[ns]".format(dtype=dtype)) + if copy: + values = values.copy() + if freq: + freq = to_offset(freq) - if values.dtype == 'i8': - values = values.view('timedelta64[ns]') + self._data = values + self._dtype = dtype + self._freq = freq - result = type(self)._from_sequence(values, dtype=dtype, - copy=copy, freq=freq) - self._data = result._data - self._freq = result._freq - self._dtype = result._dtype + if inferred_freq is None and freq is not None: + type(self)._validate_frequency(self, freq) @classmethod def _simple_new(cls, values, freq=None, dtype=_TD_DTYPE): diff --git a/pandas/tests/arrays/test_timedeltas.py b/pandas/tests/arrays/test_timedeltas.py index af23b2467fcdf7..a8745f78392ca7 100644 --- a/pandas/tests/arrays/test_timedeltas.py +++ b/pandas/tests/arrays/test_timedeltas.py @@ -43,7 +43,7 @@ def test_incorrect_dtype_raises(self): def test_copy(self): data = np.array([1, 2, 3], dtype='m8[ns]') arr = TimedeltaArray(data, copy=False) - assert arr._data.base is data + assert arr._data is data arr = TimedeltaArray(data, copy=True) assert arr._data is not data