REF: array_to_datetime catch overflows in one place
State: closed

The diff is big, but all this is doing is changing:

```
if A:
    try:
        foo(...)
    except OutOfBoundsDatetime:
        handle(...)
elif B:
    try:
        bar(...)
    except OutOfBoundsDatetime:
        handle(...)
...
```

to:

```
try:
    if A:
        foo(...)
    elif B:
        bar(...)
    ...
except OutOfBoundsDatetime:
    handle(...)
...
```

Orthogonal to #24032, will need rebasing following #24031.  All three of these should go before #24006.

Labels:
name: Datetime
description: Datetime data dtype
name: Clean

Comments:
# [Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/24049?src=pr&el=h1) Report
> Merging [#24049](https://codecov.io/gh/pandas-dev/pandas/pull/24049?src=pr&el=desc) into [master](https://codecov.io/gh/pandas-dev/pandas/commit/26d7c5265d2c784dc04980f355cb115c4e692759?src=pr&el=desc) will **decrease** coverage by `<.01%`.
> The diff coverage is `n/a`.

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

```diff
@@            Coverage Diff             @@
##           master   #24049      +/-   ##
==========================================
- Coverage   42.45%   42.45%   -0.01%     
==========================================
  Files         161      161              
  Lines       51562    51561       -1     
==========================================
- Hits        21892    21888       -4     
- Misses      29670    29673       +3
```

| Flag | Coverage Δ | |
|---|---|---|
| #single | `42.45% <ø> (-0.01%)` | :arrow_down: |

| [Impacted Files](https://codecov.io/gh/pandas-dev/pandas/pull/24049?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pandas/core/arrays/datetimelike.py](https://codecov.io/gh/pandas-dev/pandas/pull/24049/diff?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvYXJyYXlzL2RhdGV0aW1lbGlrZS5weQ==) | `50.43% <0%> (-1.36%)` | :arrow_down: |
| [pandas/core/indexes/datetimes.py](https://codecov.io/gh/pandas-dev/pandas/pull/24049/diff?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvaW5kZXhlcy9kYXRldGltZXMucHk=) | `52.18% <0%> (ø)` | :arrow_up: |
| [pandas/core/indexes/timedeltas.py](https://codecov.io/gh/pandas-dev/pandas/pull/24049/diff?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvaW5kZXhlcy90aW1lZGVsdGFzLnB5) | `39.82% <0%> (ø)` | :arrow_up: |
| [pandas/core/arrays/datetimes.py](https://codecov.io/gh/pandas-dev/pandas/pull/24049/diff?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvYXJyYXlzL2RhdGV0aW1lcy5weQ==) | `63.48% <0%> (ø)` | :arrow_up: |
| [pandas/core/indexes/datetimelike.py](https://codecov.io/gh/pandas-dev/pandas/pull/24049/diff?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvaW5kZXhlcy9kYXRldGltZWxpa2UucHk=) | `53.54% <0%> (+1%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/24049?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/24049?src=pr&el=footer). Last update [26d7c52...1004c9e](https://codecov.io/gh/pandas-dev/pandas/pull/24049?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/24049?src=pr&el=h1) Report
> Merging [#24049](https://codecov.io/gh/pandas-dev/pandas/pull/24049?src=pr&el=desc) into [master](https://codecov.io/gh/pandas-dev/pandas/commit/26d7c5265d2c784dc04980f355cb115c4e692759?src=pr&el=desc) will **not change** coverage.
> The diff coverage is `n/a`.

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

```diff
@@           Coverage Diff           @@
##           master   #24049   +/-   ##
=======================================
  Coverage   42.45%   42.45%           
=======================================
  Files         161      161           
  Lines       51562    51562           
=======================================
  Hits        21892    21892           
  Misses      29670    29670
```

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


------

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

so what i think you should *really* do, is instead of nesting this further, move all that you have inside the try/except (in order to catch OutOfBounds), and put it in another function, then have ``array_to_datetime`` call it. will be much easier on the eyes i think. (see line 712)

maybe something like
```
try:
    return array_to_datetime(...)
except OutOfBounds:
    return array_to_object(...)
else:
    raise TypeError
```
> and put it in another function

Works for me.  This hypothetical function would look _a lot_ like `convert_to_tsobject`.  Hopefully we'll be able to iron out the handful of differences between these and de-duplicate a bunch of code.

```
else:
    raise TypeError
```

I'm not wild about using TypeError for flow-control here because it obscures cases when a TypeError is raised naturally.  #24032 is an orthogonal refactor that I think improves the situation.  Following that I'll take a look at implementing your suggestion here.
> Works for me. This hypothetical function would look a lot like convert_to_tsobject. Hopefully we'll be able to iron out the handful of differences between these and de-duplicate a bunch of code.

yep

> I'm not wild about using TypeError for flow-control here because it obscures cases when a TypeError is raised naturally. #24032 is an orthogonal refactor that I think improves the situation. Following that I'll take a look at implementing your suggestion here

oh, that's what the original does, didn't actually mean to change anything.
> oh, that's what the original does, didn't actually mean to change anything.

Yah, its 24032 that does change the behavior.  I'm pretty sure the suggestion you made here will need tweaking after 24032, and I think that's a more important change, so should go first.
ok, #24032 merged. rebase this and will look.
I'm putting this together now and _think_ the suggestion will work, but there are a bunch of state variables (seen_datetime, seen_integer, seen_string, out_tzoffset_vals) to keep track of, so it is getting pretty pointer-y.  We should consider whether this refactor is worthwhile in its current form without separating out a new function.
right it’s nice and clean but might involve some duplicated code

but i think reducing nesting is worth that it becomes easier to reason about
So I've gotten a version working with the new function separated out, but it adds enough non-pythonic complication that I'd rather leave the status quo than push it.  If there's consensus that this PR as-is is an improvement on master then let's go for that, otherwise I'll close.  #23675 and #23885 are much higher priorities.
ok this is a net improvment. that function is a bear. but if you have time / maybe open an issue to refactor even more.