Repository: pandas-dev/pandas

Issue:
BUG: incorrect casting in ndarray + DataFrame
```
tdi = pd.timedelta_range('1s', periods=10)
df = pd.DataFrame({'a': tdi, 'b': tdi})
arr = np.arange(2)

>>> df + arr
[...]
AssertionError
# should be TypeError, but close enough for government work

>>> arr + df
                a                      b
0 0 days 00:00:01 0 days 00:00:01.000000
1 1 days 00:00:01 1 days 00:00:01.000000
2 2 days 00:00:01 2 days 00:00:01.000000
3 3 days 00:00:01 3 days 00:00:01.000000
4 4 days 00:00:01 4 days 00:00:01.000000
5 5 days 00:00:01 5 days 00:00:01.000000
6 6 days 00:00:01 6 days 00:00:01.000000
7 7 days 00:00:01 7 days 00:00:01.000000
8 8 days 00:00:01 8 days 00:00:01.000000
9 9 days 00:00:01 9 days 00:00:01.000000
```


Discussion:

Resolving patch:
diff --git a/pandas/core/frame.py b/pandas/core/frame.py
--- a/pandas/core/frame.py
+++ b/pandas/core/frame.py
@@ -4886,7 +4886,7 @@ def _arith_op(left, right):
             left, right = ops.fill_binop(left, right, fill_value)
             return func(left, right)
 
-        if this._is_mixed_type or other._is_mixed_type:
+        if ops.should_series_dispatch(this, other, func):
             # iterate over columns
             return ops.dispatch_to_series(this, other, _arith_op)
         else:
diff --git a/pandas/core/ops.py b/pandas/core/ops.py
--- a/pandas/core/ops.py
+++ b/pandas/core/ops.py
@@ -900,6 +900,42 @@ def invalid_comparison(left, right, op):
     return res_values
 
 
+# -----------------------------------------------------------------------------
+# Dispatch logic
+
+def should_series_dispatch(left, right, op):
+    """
+    Identify cases where a DataFrame operation should dispatch to its
+    Series counterpart.
+
+    Parameters
+    ----------
+    left : DataFrame
+    right : DataFrame
+    op : binary operator
+
+    Returns
+    -------
+    override : bool
+    """
+    if left._is_mixed_type or right._is_mixed_type:
+        return True
+
+    if not len(left.columns) or not len(right.columns):
+        # ensure obj.dtypes[0] exists for each obj
+        return False
+
+    ldtype = left.dtypes.iloc[0]
+    rdtype = right.dtypes.iloc[0]
+
+    if ((is_timedelta64_dtype(ldtype) and is_integer_dtype(rdtype)) or
+            (is_timedelta64_dtype(rdtype) and is_integer_dtype(ldtype))):
+        # numpy integer dtypes as timedelta64 dtypes in this scenario
+        return True
+
+    return False
+
+
 # -----------------------------------------------------------------------------
 # Functions that add arithmetic methods to objects, given arithmetic factory
 # methods
@@ -1802,8 +1838,10 @@ def f(self, other, axis=default_axis, level=None, fill_value=None):
 
         other = _align_method_FRAME(self, other, axis)
 
-        if isinstance(other, ABCDataFrame):  # Another DataFrame
-            return self._combine_frame(other, na_op, fill_value, level)
+        if isinstance(other, ABCDataFrame):
+            # Another DataFrame
+            pass_op = op if should_series_dispatch(self, other, op) else na_op
+            return self._combine_frame(other, pass_op, fill_value, level)
         elif isinstance(other, ABCSeries):
             return _combine_series_frame(self, other, na_op,
                                          fill_value=fill_value, axis=axis,


Test patch:
diff --git a/pandas/tests/frame/test_arithmetic.py b/pandas/tests/frame/test_arithmetic.py
--- a/pandas/tests/frame/test_arithmetic.py
+++ b/pandas/tests/frame/test_arithmetic.py
@@ -266,3 +266,18 @@ def test_df_bool_mul_int(self):
         result = 1 * df
         kinds = result.dtypes.apply(lambda x: x.kind)
         assert (kinds == 'i').all()
+
+    def test_td64_df_add_int_frame(self):
+        # GH#22696 Check that we don't dispatch to numpy implementation,
+        # which treats int64 as m8[ns]
+        tdi = pd.timedelta_range('1', periods=3)
+        df = tdi.to_frame()
+        other = pd.DataFrame([1, 2, 3], index=tdi)  # indexed like `df`
+        with pytest.raises(TypeError):
+            df + other
+        with pytest.raises(TypeError):
+            other + df
+        with pytest.raises(TypeError):
+            df - other
+        with pytest.raises(TypeError):
+            other - df