Refactor _TimeOp._validate to separate datetime vs timedelta vs dateoffset
Trying to mirror the logic in the datetimelike index classes.

Separate some of the tests in the same vein.  

No logic should be changed in this PR, it should be pure refactor.

This _will_ have a merge conflict with #18831.

# [Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/18832?src=pr&el=h1) Report
> Merging [#18832](https://codecov.io/gh/pandas-dev/pandas/pull/18832?src=pr&el=desc) into [master](https://codecov.io/gh/pandas-dev/pandas/commit/b6a7cc9d4686f62596de031c9cc4a1d62d12c52e?src=pr&el=desc) will **decrease** coverage by `0.01%`.
> The diff coverage is `67.74%`.

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

```diff
@@            Coverage Diff             @@
##           master   #18832      +/-   ##
==========================================
- Coverage   91.64%   91.63%   -0.02%     
==========================================
  Files         154      154              
  Lines       51408    51387      -21     
==========================================
- Hits        47113    47088      -25     
- Misses       4295     4299       +4
```

| Flag | Coverage Δ | |
|---|---|---|
| #multiple | `89.5% <67.74%> (+0.01%)` | :arrow_up: |
| #single | `40.83% <29.03%> (-0.13%)` | :arrow_down: |

| [Impacted Files](https://codecov.io/gh/pandas-dev/pandas/pull/18832?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pandas/core/ops.py](https://codecov.io/gh/pandas-dev/pandas/pull/18832/diff?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvb3BzLnB5) | `90.17% <67.74%> (-1.6%)` | :arrow_down: |
| [pandas/io/gbq.py](https://codecov.io/gh/pandas-dev/pandas/pull/18832/diff?src=pr&el=tree#diff-cGFuZGFzL2lvL2dicS5weQ==) | `25% <0%> (-58.34%)` | :arrow_down: |
| [pandas/compat/numpy/function.py](https://codecov.io/gh/pandas-dev/pandas/pull/18832/diff?src=pr&el=tree#diff-cGFuZGFzL2NvbXBhdC9udW1weS9mdW5jdGlvbi5weQ==) | `88.48% <0%> (-3.64%)` | :arrow_down: |
| [pandas/util/\_test\_decorators.py](https://codecov.io/gh/pandas-dev/pandas/pull/18832/diff?src=pr&el=tree#diff-cGFuZGFzL3V0aWwvX3Rlc3RfZGVjb3JhdG9ycy5weQ==) | `92.06% <0%> (-2.49%)` | :arrow_down: |
| [pandas/plotting/\_converter.py](https://codecov.io/gh/pandas-dev/pandas/pull/18832/diff?src=pr&el=tree#diff-cGFuZGFzL3Bsb3R0aW5nL19jb252ZXJ0ZXIucHk=) | `65.22% <0%> (-1.3%)` | :arrow_down: |
| [pandas/io/sql.py](https://codecov.io/gh/pandas-dev/pandas/pull/18832/diff?src=pr&el=tree#diff-cGFuZGFzL2lvL3NxbC5weQ==) | `94.3% <0%> (-0.49%)` | :arrow_down: |
| [pandas/io/common.py](https://codecov.io/gh/pandas-dev/pandas/pull/18832/diff?src=pr&el=tree#diff-cGFuZGFzL2lvL2NvbW1vbi5weQ==) | `69.06% <0%> (-0.43%)` | :arrow_down: |
| [pandas/core/series.py](https://codecov.io/gh/pandas-dev/pandas/pull/18832/diff?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvc2VyaWVzLnB5) | `94.65% <0%> (-0.17%)` | :arrow_down: |
| [pandas/core/dtypes/common.py](https://codecov.io/gh/pandas-dev/pandas/pull/18832/diff?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvZHR5cGVzL2NvbW1vbi5weQ==) | `94.29% <0%> (-0.17%)` | :arrow_down: |
| [pandas/core/frame.py](https://codecov.io/gh/pandas-dev/pandas/pull/18832/diff?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvZnJhbWUucHk=) | `97.68% <0%> (-0.11%)` | :arrow_down: |
| ... and [13 more](https://codecov.io/gh/pandas-dev/pandas/pull/18832/diff?src=pr&el=tree-more) | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/18832?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/18832?src=pr&el=footer). Last update [b6a7cc9...a3cab61](https://codecov.io/gh/pandas-dev/pandas/pull/18832?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).
 thanks!