Repository: pandas-dev/pandas

Issue:
TimedeltaIndex +/- NaT inconsistency with Series[timedelta64]+/- NaT
Analogous to (#18808)

Adapted from `tests.indexes.timedeltas.test_arithmetic.TestTimedeltaIndexArithmetic.test_timedelta_ops_with_missing_values`

```
tdi = pd.TimedeltaIndex(['00:00:01'])
ser = pd.Series(tdi)

>>> tdi + pd.NaT
DatetimeIndex(['NaT'], dtype='datetime64[ns]', freq=None)
>>> tdi - pd.NaT
DatetimeIndex(['NaT'], dtype='datetime64[ns]', freq=None)

>>> ser + pd.NaT
0   NaT
dtype: timedelta64[ns]
>>> ser - pd.NaT
0   NaT
dtype: timedelta64[ns]
```

i.e. `Series[timedelta64]` treats `pd.NaT` as a `timedelta`, while `TimedeltaIndex` treats `pd.NaT` as a `datetime` (in a way that makes sense for addition but not for subtraction).

Expected Behavior
Internal consistency in the sense that:
```
(tdi - pd.NaT).dtype == (ser - pd.NaT).dtype
(tdi + pd.NaT).dtype == (ser + pd.NaT).dtype
```

For `tdi - pd.NaT` it _only_ makes sense for the result to be `timedelta64`, so the `TimedeltaIndex` behavior is wrong.

For `tdi + pd.NaT` a reasonable argument can be made for the result being either `timedelta64` or `datetime64`.  Returning timedelta64 maintains consistency with `TimedeltaIndex.__sub__`, while `datetime64` maintains consistency with `TimedeltaIndex.__radd__`.  All in all I think keeping addition commutative is the more important of the two.


Discussion:
these should all be timedelta 
> these should all be timedelta

I'm fine with this, but it merits double-checking because the current behavior is [specifically tested](https://github.com/pandas-dev/pandas/blob/master/pandas/tests/scalar/test_nat.py#L312):

```
    tdi = TimedeltaIndex(['1 day', '2 day'], name='x')
    exp = DatetimeIndex([NaT, NaT], name='x')
    for (left, right) in [(NaT, tdi)]:
        tm.assert_index_equal(left + right, exp)
        tm.assert_index_equal(right + left, exp)
        tm.assert_index_equal(left - right, exp)
        tm.assert_index_equal(right - left, exp)
```

The subtraction is clearly wrong as is, but if the default is to view `NaT` as a `datetime`, then `pd.NaT + tdi` should be a `DatetimeIndex`, in which case `tdi + pd.NaT` probably should too. 

Resolving patch:
diff --git a/pandas/core/indexes/timedeltas.py b/pandas/core/indexes/timedeltas.py
--- a/pandas/core/indexes/timedeltas.py
+++ b/pandas/core/indexes/timedeltas.py
@@ -403,7 +403,8 @@ def _add_datelike(self, other):
         # adding a timedeltaindex to a datetimelike
         from pandas import Timestamp, DatetimeIndex
         if other is NaT:
-            result = self._nat_new(box=False)
+            # GH#19124 pd.NaT is treated like a timedelta
+            return self._nat_new()
         else:
             other = Timestamp(other)
             i8 = self.asi8
@@ -413,12 +414,13 @@ def _add_datelike(self, other):
         return DatetimeIndex(result, name=self.name, copy=False)
 
     def _sub_datelike(self, other):
-        from pandas import DatetimeIndex
+        # GH#19124 Timedelta - datetime is not in general well-defined.
+        # We make an exception for pd.NaT, which in this case quacks
+        # like a timedelta.
         if other is NaT:
-            result = self._nat_new(box=False)
+            return self._nat_new()
         else:
             raise TypeError("cannot subtract a datelike from a TimedeltaIndex")
-        return DatetimeIndex(result, name=self.name, copy=False)
 
     def _add_offset_array(self, other):
         # Array/Index of DateOffset objects


Test patch:
diff --git a/pandas/tests/scalar/test_nat.py b/pandas/tests/scalar/test_nat.py
--- a/pandas/tests/scalar/test_nat.py
+++ b/pandas/tests/scalar/test_nat.py
@@ -302,14 +302,30 @@ def test_nat_arithmetic_index():
         tm.assert_index_equal(left - right, exp)
         tm.assert_index_equal(right - left, exp)
 
-    # timedelta
+    # timedelta # GH#19124
     tdi = TimedeltaIndex(['1 day', '2 day'], name='x')
-    exp = DatetimeIndex([NaT, NaT], name='x')
-    for (left, right) in [(NaT, tdi)]:
-        tm.assert_index_equal(left + right, exp)
-        tm.assert_index_equal(right + left, exp)
-        tm.assert_index_equal(left - right, exp)
-        tm.assert_index_equal(right - left, exp)
+    tdi_nat = TimedeltaIndex([NaT, NaT], name='x')
+
+    tm.assert_index_equal(tdi + NaT, tdi_nat)
+    tm.assert_index_equal(NaT + tdi, tdi_nat)
+    tm.assert_index_equal(tdi - NaT, tdi_nat)
+    tm.assert_index_equal(NaT - tdi, tdi_nat)
+
+
+@pytest.mark.parametrize('box, assert_func', [
+    (TimedeltaIndex, tm.assert_index_equal),
+    pytest.param(Series, tm.assert_series_equal,
+                 marks=pytest.mark.xfail(reason='NaT - Series returns NaT'))
+])
+def test_nat_arithmetic_td64_vector(box, assert_func):
+    # GH#19124
+    vec = box(['1 day', '2 day'], dtype='timedelta64[ns]')
+    box_nat = box([NaT, NaT], dtype='timedelta64[ns]')
+
+    assert_func(vec + NaT, box_nat)
+    assert_func(NaT + vec, box_nat)
+    assert_func(vec - NaT, box_nat)
+    assert_func(NaT - vec, box_nat)
 
 
 def test_nat_pinned_docstrings():