BUG: fix raise of TypeError when subtracting timedelta array
State: closed

closes #21980

- [x] closes #xxxx
- [x] tests added / passed
- [x] passes `git diff upstream/master -u -- "*.py" | flake8 --diff`
- [x] whatsnew entry


Labels:
name: Bug
name: Timedelta
description: Timedelta data type

Comments:
Actually I'm a little confused now @jbrockmendel, checking on one of the failing tests that I have it is the one for ```test_ops_series_object``` (GH #13043),  it seems like based on the functionality that I'm changing the expectation there should change? Should the dtype now actually be a ```<M8[ns]``` when you do an addition rather than a ```O``` since we do the conversion properly now?
> rather than a O since we do the conversion properly now?

The thing is that the line `converted_other = other.astype('datetime64[ns]')` doesn't belong at all.  Among other things the case to test is `other = np.array([pd.Timestamp.now(), pd.Timedelta('1D')])`.  That has an object-dtype, `__radd__` and `__rsub__` should both be valid, and the `astype` call would fail.
Yea adding in the test for `other = np.array([pd.Timestamp.now(), pd.Timedelta('1D')])` exposes the failure you mentioned. I can remove that but moving forward I'm not sure how to implement that since the `O` type object fails to apply the lambda since Numpy just errors on the application of the lambda. 
> not sure how to implement that since the O type object fails to apply the lambda since Numpy just errors on the application of the lambda.

I'm not sure what lambda you're referring to, but I imagine this will end up looking something like:

```
if other.dtype.kind in ['m', 'M']:
     [do what it does now]
elif other.dtype.kind == 'O':
    return np.array([op(self, x) for x in other])
raise TypeError(...)
```
Oh dang nice! I was just working through something similar in a REPL. I'll push up a revision in the next few minutes. Thanks for the help! EDIT: The lambda I was referring to was  op function that gets passed in.
Ok so I'm not sure why my build wouldn't output anything for the tests that did fail on TravisCI - @jbrockmendel is there a way I can retrigger travis? Is that known to be flakey? Or should I look into something else? I appreciate the help.
Travis error looks unrelated.  When this happens I usually find some typo somewhere to fix and make a dummy commit to force it to re-run.
@jbrockmendel hmm upon further investigation this AM it seems that when doing the reverse subtract ie 
```python
        arr = np.array([Timestamp('20130101 9:01'),
                        Timestamp('20121230 9:02')])
        exp = np.array([Timestamp('20121231 9:01'),
                        Timestamp('20121229 9:02')])
        res = pd.Timedelta('1D') - arr
        tm.assert_numpy_array_equal(res, exp)
```

I get `TypeError: descriptor '__sub__' requires a 'datetime.datetime' object but received a 'Timedelta'` in `pandas/_libs/tslibs/timestamps.pyx:330`. Still investigating but it seems like I might have to do a bigger change than I thought.
> I get TypeError: descriptor '__sub__' requires a 'datetime.datetime' object but received a 'Timedelta' in pandas/_libs/tslibs/timestamps.pyx:330

The operation being run is `Timedelta - Timestamp` right?  That _should_ raise a `TypeError`, you're OK.
Hmm actually, it appears that rsub doesn't work originally with `Timedelta` and `Timestamps`...maybe this is an existing issue?

```
>>> pd.Timedelta('1d') - Timestamp('20130101 9:01')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "pandas/_libs/tslibs/timestamps.pyx", line 332, in pandas._libs.tslibs.timestamps._Timestamp.__sub__
TypeError: descriptor '__sub__' requires a 'datetime.datetime' object but received a 'Timedelta'
```
Ok so in that case I'll just check that these raise appropriately then.

Thanks for all the help!
Hello @illegalnumbers! Thanks for updating the PR.

 - There are no PEP8 issues in the file [`pandas/tests/scalar/timedelta/test_arithmetic.py`](https://github.com/illegalnumbers/pandas/blob/20c93d2ee12a550d053f57a7e370ec924e59cfca/pandas/tests/scalar/timedelta/test_arithmetic.py) !



##### Comment last updated on September 06, 2018 at 04:04 Hours UTC
# [Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/22054?src=pr&el=h1) Report
> Merging [#22054](https://codecov.io/gh/pandas-dev/pandas/pull/22054?src=pr&el=desc) into [master](https://codecov.io/gh/pandas-dev/pandas/commit/46abe186d21f2bab3c5df53c906b6a62d07e922b?src=pr&el=desc) will **increase** coverage by `<.01%`.
> The diff coverage is `n/a`.

[![Impacted file tree graph](https://codecov.io/gh/pandas-dev/pandas/pull/22054/graphs/tree.svg?width=650&token=eZ4WkYLtcO&height=150&src=pr)](https://codecov.io/gh/pandas-dev/pandas/pull/22054?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master   #22054      +/-   ##
==========================================
+ Coverage   92.04%   92.05%   +<.01%     
==========================================
  Files         169      169              
  Lines       50782    50782              
==========================================
+ Hits        46744    46745       +1     
+ Misses       4038     4037       -1
```

| Flag | Coverage Δ | |
|---|---|---|
| #multiple | `90.46% <ø> (ø)` | :arrow_up: |
| #single | `42.26% <ø> (ø)` | :arrow_up: |

| [Impacted Files](https://codecov.io/gh/pandas-dev/pandas/pull/22054?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pandas/core/ops.py](https://codecov.io/gh/pandas-dev/pandas/pull/22054/diff?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvb3BzLnB5) | `97.04% <0%> (+0.14%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/22054?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/22054?src=pr&el=footer). Last update [46abe18...20c93d2](https://codecov.io/gh/pandas-dev/pandas/pull/22054?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

@jbrockmendel lemme know if there's anything else I need to do to get this guy merged! :)
Status update: I'll try and finish wrapping this up sometime next weekend!
@illegalnumbers any word?  Last I checked this was really close to ready.
Sorry I suck! I haven't had any 20% time to commit to this and school kicked up so my priorities have been scattered. I will fix this up tonight and address the feedback and make a push.
Ok I think this should be good to go barring any other additional feedback! Thanks for being patient.
I haven't used `pytest.mark.parametrize` before so you're going to have to wait until I have time to learn how to use that and work on this again. It might be a while.
Additionally, an example of what you're looking for specifically would be wonderful!
see http://pandas.pydata.org/pandas-docs/stable/contributing.html#using-pytest
Gonna see if I can finish this up today!
Took a little while extra but it should be ready for review again. Barring any lint failures of course.
I'm not sure if these are related to my ps? Kind of hard to read the build output.

EDIT: Seems like most are in the excel writer?
> EDIT: Seems like most are in the excel writer?

Yes.  I think this is fixed now.  If you rebase/push it _should_ go through alright.  I'll go over this one more time today, after which jreback will be called in for the final OK.
Done! Like I said on the parameterize, I did the best I could without getting stuck. There were a few tests that seemed really similar but I kept getting exceptions when I tried to parameterize them so it seemed like more work than it was worth considering my experience.
@jbrockmendel I think this should be good again!
The tests could be parametrized a bit further, but at some point that just becomes equivalent to re-writing the method this PR is implementing.

@jreback LGTM.
I'm super happy to have contributed! This was fun. Sorry it took so long.
thanks!