Replace hand-rolled binary search with bisect_left (#50410)
Replace hand-rolled binary search with bisect_left (#50410)

The `bisect` module exposes a `bisect_left` function which does
basically what the bulk of `_lower_bound` does. From my tests, it is
slightly faster (~5%) in the probably common ideal case where `arr` is short.
In the worst case scenario, `bisect.bisect_left` is *much* faster.

```
>>> arr = list(range(60))
>>> cmp = 59
>>> %timeit _lower_bound(arr, cmp)
736 ns ± 6.24 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
>>> %timeit bisect_lower_bound(arr, cmp)
290 ns ± 7.77 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
```

I doubt this is a huge bottleneck or anything, but I think it's a bit
more readable, and it's more efficient, so it seems like it's mostly a
win.

This commit *will* add a new unconditional import for `bisect` when
importing `util.dt`, and `bisect` is not currently imported for any of
the standard library modules. It is possible to make this conditional by
placing `import bisect` in the _lower_bound function, or in the function
it's nested in.
w1ll1am23/home-assistant,rohitranjan1991/home-assistant,toddeye/home-assistant,aronsky/home-assistant,w1ll1am23/home-assistant,nkgilley/home-assistant,nkgilley/home-assistant,rohitranjan1991/home-assistant,lukas-hetzenecker/home-assistant,FreekingDean/home-assistant,home-assistant/home-assistant,aronsky/home-assistant,GenericStudent/home-assistant,home-assistant/home-assistant,toddeye/home-assistant,mezz64/home-assistant,mezz64/home-assistant,jawilson/home-assistant,kennedyshead/home-assistant,kennedyshead/home-assistant,sander76/home-assistant,GenericStudent/home-assistant,Danielhiversen/home-assistant,jawilson/home-assistant,lukas-hetzenecker/home-assistant,rohitranjan1991/home-assistant,sander76/home-assistant,Danielhiversen/home-assistant,FreekingDean/home-assistant