Repository: pandas-dev/pandas

Issue:
BUG: subtraction of datetime / timedelta should be allowed
```
In [12]: s2
Out[12]:
0   1 days
1   2 days
2   3 days
dtype: timedelta64[ns]

In [9]: pd.Timestamp('2012-01-01') + s2
Out[9]:
0   2012-01-02
1   2012-01-03
2   2012-01-04
dtype: datetime64[ns]

In [10]: pd.Timestamp('2012-01-01') - s2
TypeError: can only operate on a timedelta/DateOffset and a datetime for addition, but the operator [__rsub__] was passed

In [11]: pd.Timestamp('2012-01-01') + (-s2)
Out[11]:
0   2011-12-31
1   2011-12-30
2   2011-12-29
dtype: datetime64[ns]
```



Discussion:

Resolving patch:
diff --git a/pandas/core/ops.py b/pandas/core/ops.py
--- a/pandas/core/ops.py
+++ b/pandas/core/ops.py
@@ -291,6 +291,7 @@ def __init__(self, left, right, name, na_op):
         self.is_datetime64tz_lhs = is_datetime64tz_dtype(lvalues)
         self.is_datetime_lhs = self.is_datetime64_lhs or self.is_datetime64tz_lhs
         self.is_integer_lhs = left.dtype.kind in ['i', 'u']
+        self.is_floating_lhs = left.dtype.kind == 'f'
 
         # right
         self.right = right
@@ -300,6 +301,7 @@ def __init__(self, left, right, name, na_op):
         self.is_datetime_rhs = self.is_datetime64_rhs or self.is_datetime64tz_rhs
         self.is_timedelta_rhs = is_timedelta64_dtype(rvalues)
         self.is_integer_rhs = rvalues.dtype.kind in ('i', 'u')
+        self.is_floating_rhs = rvalues.dtype.kind == 'f'
 
         self._validate(lvalues, rvalues, name)
         self.lvalues, self.rvalues = self._convert_for_datetime(lvalues, rvalues)
@@ -307,25 +309,17 @@ def __init__(self, left, right, name, na_op):
     def _validate(self, lvalues, rvalues, name):
         # timedelta and integer mul/div
 
-        if (self.is_timedelta_lhs and self.is_integer_rhs) or (
-            self.is_integer_lhs and self.is_timedelta_rhs):
+        if (self.is_timedelta_lhs and
+                (self.is_integer_rhs or self.is_floating_rhs)) or (
+            self.is_timedelta_rhs and
+                    (self.is_integer_lhs or self.is_floating_lhs)):
 
-            if name not in ('__div__', '__truediv__', '__mul__'):
+            if name not in ('__div__', '__truediv__', '__mul__', '__rmul__'):
                 raise TypeError("can only operate on a timedelta and an "
-                                "integer for division, but the operator [%s]"
-                                "was passed" % name)
+                                "integer or a float for division and "
+                                "multiplication, but the operator [%s] was"
+                                "passed" % name)
 
-        # 2 datetimes
-        elif self.is_datetime_lhs and self.is_datetime_rhs:
-
-            if name not in ('__sub__','__rsub__'):
-                raise TypeError("can only operate on a datetimes for"
-                                " subtraction, but the operator [%s] was"
-                                " passed" % name)
-
-            # if tz's must be equal (same or None)
-            if getattr(lvalues,'tz',None) != getattr(rvalues,'tz',None):
-                raise ValueError("Incompatbile tz's on datetime subtraction ops")
 
         # 2 timedeltas
         elif ((self.is_timedelta_lhs and
@@ -339,6 +333,7 @@ def _validate(self, lvalues, rvalues, name):
                                 "addition, subtraction, and division, but the"
                                 " operator [%s] was passed" % name)
 
+
         # datetime and timedelta/DateOffset
         elif (self.is_datetime_lhs and
               (self.is_timedelta_rhs or self.is_offset_rhs)):
@@ -349,6 +344,28 @@ def _validate(self, lvalues, rvalues, name):
                                 " but the operator [%s] was passed" %
                                 name)
 
+        elif (self.is_datetime_rhs and
+              (self.is_timedelta_lhs or self.is_offset_lhs)):
+            if name not in ('__add__', '__radd__', '__rsub__'):
+                raise TypeError("can only operate on a timedelta/DateOffset with a rhs of"
+                                " a datetime for addition,"
+                                " but the operator [%s] was passed" %
+                                name)
+
+
+        # 2 datetimes
+        elif self.is_datetime_lhs and self.is_datetime_rhs:
+
+            if name not in ('__sub__','__rsub__'):
+                raise TypeError("can only operate on a datetimes for"
+                                " subtraction, but the operator [%s] was"
+                                " passed" % name)
+
+            # if tz's must be equal (same or None)
+            if getattr(lvalues,'tz',None) != getattr(rvalues,'tz',None):
+                raise ValueError("Incompatbile tz's on datetime subtraction ops")
+
+
         elif ((self.is_timedelta_lhs or self.is_offset_lhs)
               and self.is_datetime_rhs):
 
@@ -357,7 +374,7 @@ def _validate(self, lvalues, rvalues, name):
                                 " a datetime for addition, but the operator"
                                 " [%s] was passed" % name)
         else:
-            raise TypeError('cannot operate on a series with out a rhs '
+            raise TypeError('cannot operate on a series without a rhs '
                             'of a series/ndarray of type datetime64[ns] '
                             'or a timedelta')
 
@@ -366,17 +383,25 @@ def _convert_to_array(self, values, name=None, other=None):
         from pandas.tseries.timedeltas import to_timedelta
 
         ovalues = values
+        supplied_dtype = None
         if not is_list_like(values):
             values = np.array([values])
-
-        inferred_type = lib.infer_dtype(values)
-
-        if inferred_type in ('datetime64', 'datetime', 'date', 'time'):
+        # if this is a Series that contains relevant dtype info, then use this
+        # instead of the inferred type; this avoids coercing Series([NaT],
+        # dtype='datetime64[ns]') to Series([NaT], dtype='timedelta64[ns]')
+        elif isinstance(values, pd.Series) and (
+                    is_timedelta64_dtype(values) or is_datetime64_dtype(values)):
+            supplied_dtype = values.dtype
+        inferred_type = supplied_dtype or lib.infer_dtype(values)
+        if (inferred_type in ('datetime64', 'datetime', 'date', 'time')
+            or com.is_datetimetz(inferred_type)):
             # if we have a other of timedelta, but use pd.NaT here we
             # we are in the wrong path
-            if (other is not None and other.dtype == 'timedelta64[ns]' and
-                    all(isnull(v) for v in values)):
-                values = np.empty(values.shape, dtype=other.dtype)
+            if (supplied_dtype is None
+                and other is not None
+                and (other.dtype in ('timedelta64[ns]', 'datetime64[ns]'))
+                and isnull(values).all()):
+                values = np.empty(values.shape, dtype='timedelta64[ns]')
                 values[:] = iNaT
 
             # a datelike
@@ -401,18 +426,15 @@ def _convert_to_array(self, values, name=None, other=None):
                 values = values.astype('timedelta64[ns]')
             elif isinstance(values, pd.PeriodIndex):
                 values = values.to_timestamp().to_series()
-            elif name not in ('__truediv__', '__div__', '__mul__'):
+            elif name not in ('__truediv__', '__div__', '__mul__', '__rmul__'):
                 raise TypeError("incompatible type for a datetime/timedelta "
                                 "operation [{0}]".format(name))
         elif inferred_type == 'floating':
-            # all nan, so ok, use the other dtype (e.g. timedelta or datetime)
-            if isnull(values).all():
+            if isnull(values).all() and name in ('__add__', '__radd__',
+                                                 '__sub__', '__rsub__'):
                 values = np.empty(values.shape, dtype=other.dtype)
                 values[:] = iNaT
-            else:
-                raise TypeError(
-                    'incompatible type [{0}] for a datetime/timedelta '
-                    'operation'.format(np.array(values).dtype))
+            return values
         elif self._is_offset(values):
             return values
         else:
@@ -431,7 +453,10 @@ def _convert_for_datetime(self, lvalues, rvalues):
 
             # datetime subtraction means timedelta
             if self.is_datetime_lhs and self.is_datetime_rhs:
-                self.dtype = 'timedelta64[ns]'
+                if self.name in ('__sub__', '__rsub__'):
+                    self.dtype = 'timedelta64[ns]'
+                else:
+                    self.dtype = 'datetime64[ns]'
             elif self.is_datetime64tz_lhs:
                 self.dtype = lvalues.dtype
             elif self.is_datetime64tz_rhs:
@@ -482,7 +507,8 @@ def _offset(lvalues, rvalues):
                 rvalues = to_timedelta(rvalues)
 
             lvalues = lvalues.astype(np.int64)
-            rvalues = rvalues.astype(np.int64)
+            if not self.is_floating_rhs:
+                rvalues = rvalues.astype(np.int64)
 
             # time delta division -> unit less
             # integer gets converted to timedelta in np < 1.6
@@ -580,7 +606,7 @@ def wrapper(left, right, name=name, na_op=na_op):
             lvalues, rvalues = left, right
             dtype = None
             wrap_results = lambda x: x
-        elif time_converted == NotImplemented:
+        elif time_converted is NotImplemented:
             return NotImplemented
         else:
             left, right = time_converted.left, time_converted.right
diff --git a/pandas/core/series.py b/pandas/core/series.py
--- a/pandas/core/series.py
+++ b/pandas/core/series.py
@@ -2078,8 +2078,9 @@ def map(self, arg, na_action=None):
             same index as caller
         """
         values = self._values
-        if com.is_datetime64_dtype(values.dtype):
-            values = lib.map_infer(values, lib.Timestamp)
+        if needs_i8_conversion(values.dtype):
+            boxer = i8_boxer(values)
+            values = lib.map_infer(values, boxer)
 
         if na_action == 'ignore':
             mask = isnull(values)
@@ -2210,8 +2211,9 @@ def apply(self, func, convert_dtype=True, args=(), **kwds):
             return f(self)
 
         values = _values_from_object(self)
-        if com.is_datetime64_dtype(values.dtype):
-            values = lib.map_infer(values, lib.Timestamp)
+        if needs_i8_conversion(values.dtype):
+            boxer = i8_boxer(values)
+            values = lib.map_infer(values, boxer)
 
         mapped = lib.map_infer(values, f, convert=convert_dtype)
         if len(mapped) and isinstance(mapped[0], Series):


Test patch:
diff --git a/pandas/tests/test_series.py b/pandas/tests/test_series.py
--- a/pandas/tests/test_series.py
+++ b/pandas/tests/test_series.py
@@ -19,7 +19,7 @@
 import numpy.ma as ma
 import pandas as pd
 
-from pandas import (Index, Series, DataFrame, isnull, notnull, bdate_range,
+from pandas import (Index, Series, DataFrame, isnull, notnull, bdate_range, NaT,
                     date_range, period_range, timedelta_range, _np_version_under1p8)
 from pandas.core.index import MultiIndex
 from pandas.core.indexing import IndexingError
@@ -3466,6 +3466,13 @@ def test_timedeltas_with_DateOffset(self):
         assert_series_equal(result, expected)
         assert_series_equal(result2, expected)
 
+        result = s - pd.offsets.Second(5)
+        result2 = -pd.offsets.Second(5) + s
+        expected = Series(
+            [Timestamp('20130101 9:00:55'), Timestamp('20130101 9:01:55')])
+        assert_series_equal(result, expected)
+        assert_series_equal(result2, expected)
+
         result = s + pd.offsets.Milli(5)
         result2 = pd.offsets.Milli(5) + s
         expected = Series(
@@ -3500,6 +3507,19 @@ def test_timedeltas_with_DateOffset(self):
             s + op(5)
             op(5) + s
 
+    def test_timedelta_series_ops(self):
+        #GH11925
+
+        s = Series(timedelta_range('1 day', periods=3))
+        ts = Timestamp('2012-01-01')
+        expected = Series(date_range('2012-01-02', periods=3))
+        assert_series_equal(ts + s, expected)
+        assert_series_equal(s + ts, expected)
+
+        expected2 = Series(date_range('2011-12-31', periods=3, freq='-1D'))
+        assert_series_equal(ts - s, expected2)
+        assert_series_equal(ts + (-s), expected2)
+
 
     def test_timedelta64_operations_with_DateOffset(self):
         # GH 10699
@@ -3619,11 +3639,14 @@ def test_timedelta64_operations_with_integers(self):
         assert_series_equal(result,expected)
 
         # invalid ops
-        for op in ['__true_div__','__div__','__mul__']:
-            sop = getattr(s1,op,None)
-            if sop is not None:
-                self.assertRaises(TypeError, sop, s2.astype(float))
-                self.assertRaises(TypeError, sop, 2.)
+        assert_series_equal(s1 / s2.astype(float),
+                            Series([Timedelta('2 days 22:48:00'),
+                                    Timedelta('1 days 23:12:00'),
+                                    Timedelta('NaT')]))
+        assert_series_equal(s1 / 2.0,
+                            Series([Timedelta('29 days 12:00:00'),
+                                    Timedelta('29 days 12:00:00'),
+                                    Timedelta('NaT')]))
 
         for op in ['__add__','__sub__']:
             sop = getattr(s1,op,None)
@@ -3653,7 +3676,7 @@ def test_timedelta64_conversions(self):
                     assert_series_equal(result, expected)
 
                 # reverse op
-                expected = s1.apply(lambda x: np.timedelta64(m,unit) / x)
+                expected = s1.apply(lambda x: Timedelta(np.timedelta64(m,unit)) / x)
                 result = np.timedelta64(m,unit) / s1
 
         # astype
@@ -3759,7 +3782,7 @@ def run_ops(ops, get_ser, test_ser):
 
         ### timetimedelta with datetime64 ###
         ops = ['__sub__', '__mul__', '__floordiv__', '__truediv__', '__div__',
-               '__pow__', '__rsub__', '__rmul__', '__rfloordiv__',
+               '__pow__', '__rmul__', '__rfloordiv__',
                '__rtruediv__', '__rdiv__', '__rpow__']
         run_ops(ops, td1, dt1)
         td1 + dt1
@@ -3825,6 +3848,151 @@ def run_ops(ops, get_ser, test_ser):
         self.assertRaises(TypeError, lambda: td1 - dt1)
         self.assertRaises(TypeError, lambda: td2 - dt2)
 
+    def test_ops_nat(self):
+        # GH 11349
+        timedelta_series = Series([NaT, Timedelta('1s')])
+        datetime_series = Series([NaT, Timestamp('19900315')])
+        nat_series_dtype_timedelta = Series([NaT, NaT], dtype='timedelta64[ns]')
+        nat_series_dtype_timestamp = Series([NaT, NaT], dtype='datetime64[ns]')
+        single_nat_dtype_datetime = Series([NaT], dtype='datetime64[ns]')
+        single_nat_dtype_timedelta = Series([NaT], dtype='timedelta64[ns]')
+
+        # subtraction
+        assert_series_equal(timedelta_series - NaT, nat_series_dtype_timedelta)
+        assert_series_equal(-NaT + timedelta_series, nat_series_dtype_timedelta)
+
+        assert_series_equal(timedelta_series - single_nat_dtype_timedelta,
+                            nat_series_dtype_timedelta)
+        assert_series_equal(-single_nat_dtype_timedelta + timedelta_series,
+                            nat_series_dtype_timedelta)
+
+        assert_series_equal(datetime_series - NaT, nat_series_dtype_timestamp)
+        assert_series_equal(-NaT + datetime_series, nat_series_dtype_timestamp)
+
+        assert_series_equal(datetime_series - single_nat_dtype_datetime,
+                            nat_series_dtype_timedelta)
+        with tm.assertRaises(TypeError):
+            -single_nat_dtype_datetime + datetime_series
+
+        assert_series_equal(datetime_series - single_nat_dtype_timedelta,
+                            nat_series_dtype_timestamp)
+        assert_series_equal(-single_nat_dtype_timedelta + datetime_series ,
+                            nat_series_dtype_timestamp)
+
+        # without a Series wrapping the NaT, it is ambiguous
+        # whether it is a datetime64 or timedelta64
+        # defaults to interpreting it as timedelta64
+        assert_series_equal(nat_series_dtype_timestamp - NaT,
+                            nat_series_dtype_timestamp)
+        assert_series_equal(-NaT + nat_series_dtype_timestamp,
+                            nat_series_dtype_timestamp)
+
+        assert_series_equal(nat_series_dtype_timestamp - single_nat_dtype_datetime,
+                            nat_series_dtype_timedelta)
+        with tm.assertRaises(TypeError):
+            -single_nat_dtype_datetime + nat_series_dtype_timestamp
+
+        assert_series_equal(nat_series_dtype_timestamp - single_nat_dtype_timedelta,
+                            nat_series_dtype_timestamp)
+        assert_series_equal(-single_nat_dtype_timedelta + nat_series_dtype_timestamp,
+                            nat_series_dtype_timestamp)
+
+        with tm.assertRaises(TypeError):
+            timedelta_series - single_nat_dtype_datetime
+
+        # addition
+        assert_series_equal(nat_series_dtype_timestamp + NaT,
+                            nat_series_dtype_timestamp)
+        assert_series_equal(NaT + nat_series_dtype_timestamp,
+                            nat_series_dtype_timestamp)
+
+        assert_series_equal(nat_series_dtype_timestamp + single_nat_dtype_timedelta,
+                            nat_series_dtype_timestamp)
+        assert_series_equal(single_nat_dtype_timedelta + nat_series_dtype_timestamp,
+                            nat_series_dtype_timestamp)
+
+        assert_series_equal(nat_series_dtype_timedelta + NaT,
+                            nat_series_dtype_timedelta)
+        assert_series_equal(NaT + nat_series_dtype_timedelta,
+                            nat_series_dtype_timedelta)
+
+        assert_series_equal(nat_series_dtype_timedelta + single_nat_dtype_timedelta,
+                            nat_series_dtype_timedelta)
+        assert_series_equal(single_nat_dtype_timedelta + nat_series_dtype_timedelta,
+                            nat_series_dtype_timedelta)
+
+        assert_series_equal(timedelta_series + NaT, nat_series_dtype_timedelta)
+        assert_series_equal(NaT + timedelta_series, nat_series_dtype_timedelta)
+
+        assert_series_equal(timedelta_series + single_nat_dtype_timedelta,
+                            nat_series_dtype_timedelta)
+        assert_series_equal(single_nat_dtype_timedelta + timedelta_series,
+                            nat_series_dtype_timedelta)
+
+        assert_series_equal(nat_series_dtype_timestamp + NaT,
+                            nat_series_dtype_timestamp)
+        assert_series_equal(NaT + nat_series_dtype_timestamp,
+                            nat_series_dtype_timestamp)
+
+        assert_series_equal(nat_series_dtype_timestamp + single_nat_dtype_timedelta,
+                            nat_series_dtype_timestamp)
+        assert_series_equal(single_nat_dtype_timedelta + nat_series_dtype_timestamp,
+                            nat_series_dtype_timestamp)
+
+        assert_series_equal(nat_series_dtype_timedelta + NaT,
+                            nat_series_dtype_timedelta)
+        assert_series_equal(NaT + nat_series_dtype_timedelta,
+                            nat_series_dtype_timedelta)
+
+        assert_series_equal(nat_series_dtype_timedelta + single_nat_dtype_timedelta,
+                            nat_series_dtype_timedelta)
+        assert_series_equal(single_nat_dtype_timedelta + nat_series_dtype_timedelta,
+                            nat_series_dtype_timedelta)
+
+        assert_series_equal(nat_series_dtype_timedelta + single_nat_dtype_datetime,
+                            nat_series_dtype_timestamp)
+        assert_series_equal(single_nat_dtype_datetime + nat_series_dtype_timedelta,
+                            nat_series_dtype_timestamp)
+
+        # multiplication
+        assert_series_equal(nat_series_dtype_timedelta * 1.0,
+                            nat_series_dtype_timedelta)
+        assert_series_equal(1.0 * nat_series_dtype_timedelta,
+                            nat_series_dtype_timedelta)
+
+        assert_series_equal(timedelta_series * 1, timedelta_series)
+        assert_series_equal(1 * timedelta_series, timedelta_series)
+
+        assert_series_equal(timedelta_series * 1.5,
+                            Series([NaT, Timedelta('1.5s')]))
+        assert_series_equal(1.5 * timedelta_series,
+                            Series([NaT, Timedelta('1.5s')]))
+
+        assert_series_equal(timedelta_series * nan, nat_series_dtype_timedelta)
+        assert_series_equal(nan * timedelta_series, nat_series_dtype_timedelta)
+
+        with tm.assertRaises(TypeError):
+            datetime_series * 1
+        with tm.assertRaises(TypeError):
+            nat_series_dtype_timestamp * 1
+        with tm.assertRaises(TypeError):
+            datetime_series * 1.0
+        with tm.assertRaises(TypeError):
+            nat_series_dtype_timestamp * 1.0
+
+        # division
+        assert_series_equal(timedelta_series / 2,
+                            Series([NaT, Timedelta('0.5s')]))
+        assert_series_equal(timedelta_series / 2.0,
+                            Series([NaT, Timedelta('0.5s')]))
+        assert_series_equal(timedelta_series / nan,
+                            nat_series_dtype_timedelta)
+        with tm.assertRaises(TypeError):
+            nat_series_dtype_timestamp / 1.0
+        with tm.assertRaises(TypeError):
+            nat_series_dtype_timestamp / 1
+
+
     def test_ops_datetimelike_align(self):
         # GH 7500
         # datetimelike ops need to align
diff --git a/pandas/tseries/tests/test_timedeltas.py b/pandas/tseries/tests/test_timedeltas.py
--- a/pandas/tseries/tests/test_timedeltas.py
+++ b/pandas/tseries/tests/test_timedeltas.py
@@ -270,7 +270,7 @@ def test_ops(self):
         self.assertEqual(abs(td), td)
         self.assertEqual(abs(-td), td)
         self.assertEqual(td / td, 1)
-        self.assertTrue((td / pd.NaT) is pd.NaT)
+        self.assertTrue((td / pd.NaT) is np.nan)
 
         # invert
         self.assertEqual(-td,Timedelta('-10d'))
@@ -881,20 +881,32 @@ def test_timedelta_ops_with_missing_values(self):
 
         actual = s1 + scalar1
         assert_series_equal(actual, s2)
+        actual = scalar1 + s1
+        assert_series_equal(actual, s2)
         actual = s2 - scalar1
         assert_series_equal(actual, s1)
+        actual = -scalar1 + s2
+        assert_series_equal(actual, s1)
 
         actual = s1 + timedelta_NaT
         assert_series_equal(actual, sn)
+        actual = timedelta_NaT + s1
+        assert_series_equal(actual, sn)
         actual = s1 - timedelta_NaT
         assert_series_equal(actual, sn)
+        actual = -timedelta_NaT + s1
+        assert_series_equal(actual, sn)
 
         actual = s1 + NA
         assert_series_equal(actual, sn)
+        actual = NA + s1
+        assert_series_equal(actual, sn)
         actual = s1 - NA
         assert_series_equal(actual, sn)
+        actual = -NA + s1
+        assert_series_equal(actual, sn)
 
-        actual = s1 + pd.NaT  # NaT is datetime, not timedelta
+        actual = s1 + pd.NaT
         assert_series_equal(actual, sn)
         actual = s2 - pd.NaT
         assert_series_equal(actual, sn)
diff --git a/pandas/tseries/tests/test_timeseries.py b/pandas/tseries/tests/test_timeseries.py
--- a/pandas/tseries/tests/test_timeseries.py
+++ b/pandas/tseries/tests/test_timeseries.py
@@ -11,7 +11,8 @@
 
 from pandas import (Index, Series, DataFrame,
                     isnull, date_range, Timestamp, Period, DatetimeIndex,
-                    Int64Index, to_datetime, bdate_range, Float64Index, TimedeltaIndex, NaT)
+                    Int64Index, to_datetime, bdate_range, Float64Index,
+                    TimedeltaIndex, NaT, timedelta_range, Timedelta)
 
 import pandas.core.datetools as datetools
 import pandas.tseries.offsets as offsets
@@ -369,6 +370,12 @@ def test_series_box_timestamp(self):
 
         tm.assertIsInstance(s.iat[5], Timestamp)
 
+    def test_series_box_timedelta(self):
+        rng = timedelta_range('1 day 1 s',periods=5,freq='h')
+        s = Series(rng)
+        tm.assertIsInstance(s[1], Timedelta)
+        tm.assertIsInstance(s.iat[2], Timedelta)
+
     def test_date_range_ambiguous_arguments(self):
         # #2538
         start = datetime(2011, 1, 1, 5, 3, 40)
@@ -2086,6 +2093,16 @@ def f(x):
         s.apply(f)
         DataFrame(s).applymap(f)
 
+    def test_series_map_box_timedelta(self):
+        # GH 11349
+        s = Series(timedelta_range('1 day 1 s',periods=5,freq='h'))
+
+        def f(x):
+            return x.total_seconds()
+        s.map(f)
+        s.apply(f)
+        DataFrame(s).applymap(f)
+
     def test_concat_datetime_datetime64_frame(self):
         # #2624
         rows = []
diff --git a/pandas/tseries/tests/test_tslib.py b/pandas/tseries/tests/test_tslib.py
--- a/pandas/tseries/tests/test_tslib.py
+++ b/pandas/tseries/tests/test_tslib.py
@@ -860,31 +860,34 @@ def test_nat_arithmetic(self):
         t = Timestamp('2014-01-01')
         dt = datetime.datetime(2014, 1, 1)
         delta = datetime.timedelta(3600)
-
-        # Timestamp / datetime
-        for (left, right) in [(nat, nat), (nat, t), (dt, nat)]:
-            # NaT + Timestamp-like should raise TypeError
-            with tm.assertRaises(TypeError):
-                left + right
+        td = Timedelta('5s')
+        i = 2
+        f = 1.5
+
+        for (left, right) in [(nat, i), (nat, f), (nat, np.nan)]:
+            self.assertTrue((left / right) is nat)
+            self.assertTrue((left * right) is nat)
+            self.assertTrue((right * left) is nat)
             with tm.assertRaises(TypeError):
-                right + left
+                right / left
 
-            # NaT - Timestamp-like (or inverse) returns NaT
-            self.assertTrue((left - right) is tslib.NaT)
-            self.assertTrue((right - left) is tslib.NaT)
+        # Timestamp / datetime
+        for (left, right) in [(nat, nat), (nat, t), (nat, dt)]:
+            # NaT __add__ or __sub__ Timestamp-like (or inverse) returns NaT
+            self.assertTrue((right + left) is nat)
+            self.assertTrue((left + right) is nat)
+            self.assertTrue((left - right) is nat)
+            self.assertTrue((right - left) is nat)
 
         # timedelta-like
         # offsets are tested in test_offsets.py
-        for (left, right) in [(nat, delta)]:
+        for (left, right) in [(nat, delta), (nat, td)]:
             # NaT + timedelta-like returns NaT
-            self.assertTrue((left + right) is tslib.NaT)
-            # timedelta-like + NaT should raise TypeError
-            with tm.assertRaises(TypeError):
-                right + left
+            self.assertTrue((right + left) is nat)
+            self.assertTrue((left + right) is nat)
+            self.assertTrue((right - left) is nat)
+            self.assertTrue((left - right) is nat)
 
-            self.assertTrue((left - right) is tslib.NaT)
-            with tm.assertRaises(TypeError):
-                right - left
 
 
 class TestTslib(tm.TestCase):