core/time: more flexible support for resolving TZ abbreviation -> TZ ambiguities
addresses https://github.com/karlicoss/HPI/issues/103 for now via experimental time.tz.force_abbreviations config variable not sure if this whole things is doomed to be resolved properly
This commit is contained in:
parent
5ef638694e
commit
1fd2a9f643
3 changed files with 54 additions and 12 deletions
|
@ -1,20 +1,50 @@
|
|||
from functools import lru_cache
|
||||
from datetime import datetime, tzinfo
|
||||
from typing import Sequence
|
||||
|
||||
import pytz # type: ignore
|
||||
|
||||
# https://gist.github.com/edwardabraham/8680198
|
||||
tz_lookup = {
|
||||
pytz.timezone(x).localize(datetime.now()).tzname(): pytz.timezone(x)
|
||||
for x in pytz.all_timezones
|
||||
}
|
||||
tz_lookup['UTC'] = pytz.utc # ugh. otherwise it'z Zulu...
|
||||
|
||||
def user_forced() -> Sequence[str]:
|
||||
# conversion from abbreviations is always ambiguous
|
||||
# https://stackoverflow.com/questions/36067621/python-all-possible-timezone-abbreviations-for-given-timezone-name-and-vise-ve
|
||||
try:
|
||||
from my.config import time as user_config
|
||||
return user_config.tz.force_abbreviations # type: ignore[attr-defined]
|
||||
except:
|
||||
# todo log/apply policy
|
||||
return []
|
||||
|
||||
|
||||
# TODO dammit, lru_cache interferes with mypy?
|
||||
@lru_cache(1)
|
||||
def _abbr_to_timezone_map():
|
||||
# also force UTC to always correspond to utc
|
||||
# this makes more sense than Zulu it ends up by default
|
||||
timezones = pytz.all_timezones + ['UTC'] + list(user_forced())
|
||||
|
||||
res = {}
|
||||
for tzname in timezones:
|
||||
tz = pytz.timezone(tzname)
|
||||
infos = getattr(tz, '_tzinfos', []) # not sure if can rely on attr always present?
|
||||
for info in infos:
|
||||
abbr = info[-1]
|
||||
# todo could support this with a better error handling strategy?
|
||||
# otz = res.get(abbr, tz)
|
||||
# if otz != tz:
|
||||
# raise RuntimeError(abbr, tz, otz)
|
||||
res[abbr] = tz
|
||||
# ugh. also necessary, e.g. for Zulu?? why is it not in _tzinfos?
|
||||
# note: somehow this is not the same as the tzname!
|
||||
tzn = getattr(tz, '_tzname', None)
|
||||
if tzn is not None:
|
||||
res[tzn] = tz
|
||||
return res
|
||||
|
||||
|
||||
# todo dammit, lru_cache interferes with mypy?
|
||||
@lru_cache(None)
|
||||
def abbr_to_timezone(abbr: str) -> tzinfo:
|
||||
return tz_lookup[abbr]
|
||||
return _abbr_to_timezone_map()[abbr]
|
||||
|
||||
|
||||
def zone_to_countrycode(zone: str) -> str:
|
||||
|
@ -30,3 +60,6 @@ def _zones_to_countrycode():
|
|||
for timezone in timezones:
|
||||
res[timezone] = countrycode
|
||||
return res
|
||||
|
||||
|
||||
# todo stuff here could be a bit more defensive? e.g. dependent on policy
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue