REF: de-duplicate methods calling get_dst_info
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?