BUG: Fix overflow bugs in date_Range
State: closed

- [x] closes #24123
- [x] tests added / passed
- [x] passes `git diff upstream/master -u -- "*.py" | flake8 --diff`
- [ ] whatsnew entry

Fixing this turned out to be a small beast.  The overflows of interest fall into three categories.  First: overflows when computing `periods * stride` that ATM are _not_ caught, so give incorrect results:

```
>>> pd.date_range('1969-05-04', periods=200000000, freq='30000D')
DatetimeIndex(['1969-05-04', '2051-06-23', '2133-08-12'], dtype='datetime64[ns]', freq='30000D')

>>> dti = pd.date_range(start='1677-09-22', end='2262-04-11', freq='D')
>>> pd.date_range(start=dti[0], periods=len(dti), freq='D')
DatetimeIndex([], dtype='datetime64[ns]', freq='D')
```

Second, overflows when `periods * stride` overflow the int64 bounds but not uint64 bounds, which in some cases are recoverable.  The following should _not_ raise:

```
>>> dti = pd.date_range(start='1677-09-22', end='2262-04-11', freq='D')
>>> pd.date_range(start=dti[0], periods=len(dti)-1, freq='D')
[...]
pandas._libs.tslibs.np_datetime.OutOfBoundsDatetime: Cannot generate range with start=-9223286400000000000 and periods=213502
```

Last is a similar one with a negative stride where we can recover, but not by converting to uint64:

```
>>> dti = pd.date_range(start='1677-09-22', end='2262-04-11', freq='D')
>>> pd.date_range(end=dti[-1], periods=len(dti), freq='D')
[...]
pandas._libs.tslibs.np_datetime.OutOfBoundsDatetime: Cannot generate range with end=9223372800000000000 and periods=213503
```

Labels:
name: Bug
name: Datetime
description: Datetime data dtype

Comments:
Hello @jbrockmendel! Thanks for updating the PR.







Cheers ! There are no PEP8 issues in this Pull Request. :beers: 

##### Comment last updated on December 23, 2018 at 16:48 Hours UTC
# [Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/24255?src=pr&el=h1) Report
> Merging [#24255](https://codecov.io/gh/pandas-dev/pandas/pull/24255?src=pr&el=desc) into [master](https://codecov.io/gh/pandas-dev/pandas/commit/9bc42f9d296cf717533051ee76130e72ea9ce557?src=pr&el=desc) will **decrease** coverage by `<.01%`.
> The diff coverage is `92.3%`.

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

```diff
@@            Coverage Diff             @@
##           master   #24255      +/-   ##
==========================================
- Coverage   92.21%   92.21%   -0.01%     
==========================================
  Files         162      162              
  Lines       51768    51806      +38     
==========================================
+ Hits        47739    47773      +34     
- Misses       4029     4033       +4
```

| Flag | Coverage Δ | |
|---|---|---|
| #multiple | `90.61% <92.3%> (-0.01%)` | :arrow_down: |
| #single | `42.98% <38.46%> (-0.02%)` | :arrow_down: |

| [Impacted Files](https://codecov.io/gh/pandas-dev/pandas/pull/24255?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pandas/core/arrays/datetimes.py](https://codecov.io/gh/pandas-dev/pandas/pull/24255/diff?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvYXJyYXlzL2RhdGV0aW1lcy5weQ==) | `97.98% <92.3%> (-0.58%)` | :arrow_down: |

------

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

# [Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/24255?src=pr&el=h1) Report
> Merging [#24255](https://codecov.io/gh/pandas-dev/pandas/pull/24255?src=pr&el=desc) into [master](https://codecov.io/gh/pandas-dev/pandas/commit/d7bf6f2cc870c6ba5e465307c5e8271cbaab8af7?src=pr&el=desc) will **increase** coverage by `<.01%`.
> The diff coverage is `98.73%`.

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

```diff
@@            Coverage Diff             @@
##           master   #24255      +/-   ##
==========================================
+ Coverage   92.29%    92.3%   +<.01%     
==========================================
  Files         162      163       +1     
  Lines       51890    51932      +42     
==========================================
+ Hits        47892    47934      +42     
  Misses       3998     3998
```

| Flag | Coverage Δ | |
|---|---|---|
| #multiple | `90.71% <98.73%> (ø)` | :arrow_up: |
| #single | `42.98% <55.69%> (-0.02%)` | :arrow_down: |

| [Impacted Files](https://codecov.io/gh/pandas-dev/pandas/pull/24255?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pandas/core/arrays/datetimes.py](https://codecov.io/gh/pandas-dev/pandas/pull/24255/diff?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvYXJyYXlzL2RhdGV0aW1lcy5weQ==) | `97.77% <100%> (+0.04%)` | :arrow_up: |
| [pandas/core/arrays/\_ranges.py](https://codecov.io/gh/pandas-dev/pandas/pull/24255/diff?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvYXJyYXlzL19yYW5nZXMucHk=) | `98.66% <98.66%> (ø)` | |

------

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

> why are you not using algos.checked_add_with_arr?

We are in one place, but it is mostly unnecessary, adds a lot of machinery for NA-masking that isn't relevant here.

> I am -1 on using uint64 here at all. why add all of this complexity, simply raise?

Why would we want to raise on valid inputs?  It's entirely possible that there is a simpler way to do this; I banged my head against it for a while before I got it working, so by the end elegance was not a priority.

These overflows were found when debugging the pickle problems in #24074.  There is a test that creates a DTI (something like) `dti = pd.date_range(start='1677-09-22', end='2262-04-11', freq='D')`, pickles it, then tries to unpickle it.  In the unpickling, it calls validate_frequency, which calls `cls._generate_range(start=dti[0], periods=len(dti), freq=dti.freq)`, which in master currently returns an incorrect result because of a silent overflow in multiplication.
> Why would we want to raise on valid inputs? It's entirely possible that there is a simpler way to do this; I banged my head against it for a while before I got it working, so by the end elegance was not a priority

how are these valid inputs iif you are overflowing int64? I would rather not jump thru hoops and have over complex code. 


> how are these valid inputs iif you are overflowing int64?

Because the biggest number we can get by adding an int64 to `np.iinfo(np.int64).min` is -1, but we can have date_ranges that start near the lower implementation bound and proceed well past 1970-01-01.

I claim that for _any_ DTI produced with `dti = pd.date_range(start=start, end=end, freq=freq)`, we should be able to write `dti2 = pd.date_range(start=dti[0], periods=len(dti), freq=dti.freq)` and have `assert dti2.equals(dti)`.  Ditto for `dti3 = pd.date_range('end=dti[-1], periods=len(dti), freq=dti.freq)`.

Travis fail is Hypothesis
Updated with a couple of tests for previously un-hit cases, removed some code that turned out to be un-reachable, fleshed out docstring params.

It turns out the call to `np.arange` can overflow.  Now catch that too (with test)
gentle ping.  I think this will fix the inability to do frequency validation discussed in #24024.
thanks