REF: de-duplicate methods calling get_dst_info
State: closed

We have a 8ish functions that all do something like:

```
def do_thing_vectorized(values, tz):
    if is_utc(tz):
        for i in range(n):
             local_val = values[n]
             do_thing(local_val)
    elif is_tzlocal(tz);
        for i in range(n):
             local_val = get_local_val_for_tzlocal(values[n])
             do_thing(local_val)
    elif is_fixed_offset(tz):
        for i in range(n):
             local_val = get_local_val_for_fixed_offset(values[n])
             do_thing(local_val)
[...]
```

with each of these functions using a different "do_thing".  If this were happening in python-space, we would use a generator and it would look like:

```
def do_thing_vectorized(values, tz):
    for local_val in hypothetical_generator(tz):
         do_thing(local_val)
```

But we can't do that in cython-space.  Until now, we've just made do with having this repeated code.  This PR de-duplicates this code by implementing a Localizer class, so do_thing_vectorized becomes:

```
def do_thing_vectorized(values, tz):
    localizer = get_localizer(tz)
    
     for i in range(N):
          local_val = localizer.localize(value)
          do_thing(local_val)
```

I still need to run asvs, but based on ipython results, i am not seeing any performance degradation so far.

cc @jorisvandenbossche pretty good exposition huh?

Labels:

Comments:
nice pls run benchmarks 
asv full run
```
       before           after         ratio
     [1722c053]       [8b384488]
     <master>         <ref-get_dst_info-share>
+       233±0.3μs          494±2μs     2.12  indexing_engines.NumericEngineIndexing.time_get_loc((<class 'pandas._libs.index.Int16Engine'>, <class 'numpy.int16'>), 'monotonic_incr')
+        99.7±2ms          195±4ms     1.95  gil.ParallelDatetimeFields.time_datetime_to_period
+       323±0.5μs         490±20μs     1.52  indexing_engines.NumericEngineIndexing.time_get_loc((<class 'pandas._libs.index.Int8Engine'>, <class 'numpy.int8'>), 'monotonic_incr')
+     18.1±0.06ms      26.2±0.09ms     1.45  index_object.SetOperations.time_operation('strings', 'symmetric_difference')
+       920±0.6μs         1.28±0ms     1.40  series_methods.NanOps.time_func('sum', 1000000, 'int8')
+     2.32±0.01ms      3.13±0.03ms     1.35  timeseries.DatetimeAccessor.time_dt_accessor_normalize(None)
+     2.33±0.01ms      3.13±0.01ms     1.35  timeseries.DatetimeAccessor.time_dt_accessor_normalize('UTC')
+     2.34±0.01ms      3.11±0.01ms     1.33  timeseries.DatetimeAccessor.time_dt_accessor_normalize(tzutc())
+        1.25±0ms         1.62±0ms     1.29  series_methods.NanOps.time_func('prod', 1000000, 'int8')
+      1.81±0.1μs       2.06±0.1μs     1.14  index_cached_properties.IndexCache.time_inferred_type('IntervalIndex')
+         129±2ms          145±1ms     1.12  timeseries.ToDatetimeCache.time_dup_string_tzoffset_dates(False)
+     25.3±0.05ms       28.1±0.3ms     1.11  frame_methods.Dropna.time_dropna_axis_mixed_dtypes('any', 1)
+         259±6ms          286±4ms     1.10  timeseries.ToDatetimeISO8601.time_iso8601_tz_spaceformat
+      25.1±0.1ms       27.6±0.3ms     1.10  io.sql.WriteSQLDtypes.time_to_sql_dataframe_column('sqlite', 'bool')
+      55.9±0.2ms       61.6±0.6ms     1.10  io.sql.SQL.time_to_sql_dataframe('sqlite')
+     4.14±0.07ms       4.55±0.1ms     1.10  rolling.Engine.time_expanding_apply('Series', 'int', <function sum at 0x7fd85a7c9c80>, 'cython')
-     1.81±0.06μs      1.64±0.05μs     0.90  index_cached_properties.IndexCache.time_shape('UInt64Index')
-      3.54±0.1μs      3.17±0.02μs     0.89  categoricals.CategoricalSlicing.time_getitem_scalar('non_monotonic')
-      28.6±0.5ms       25.3±0.1ms     0.88  frame_methods.Dropna.time_dropna_axis_mixed_dtypes('any', 0)
-     1.51±0.02ms      1.33±0.01ms     0.88  arithmetic.NumericInferOps.time_divide(<class 'numpy.uint8'>)
-     1.86±0.01ms      1.64±0.01ms     0.88  index_object.Indexing.time_get_loc_non_unique('Int')
-        61.9±2ms       35.6±0.6ms     0.58  join_merge.Align.time_series_align_left_monotonic
```

Will re-run overnight to see which of these are real.
A second round of asv results look pretty similar, so this looking like a non-trivial perf hit for time_datetime_to_period and time_dt_accessor_normalize
did u have a look at generated c code and/cython profiling
> did u have a look at generated c code and/cython profiling

best guess right now is that this loses a "with nogil" for the naive/UTC case
will continue poking at this locally, closing for now to focus on the offsets/arith PRs