Source code for dateparser.timezone_parser

import os
import pickle
import zlib
from datetime import datetime, timedelta, timezone, tzinfo
from pathlib import Path

import regex as re

from .timezones import timezone_info_list


[docs] class StaticTzInfo(tzinfo): def __init__(self, name, offset): self.__offset = offset self.__name = name
[docs] def tzname(self, dt): return self.__name
[docs] def utcoffset(self, dt): return self.__offset
[docs] def dst(self, dt): return timedelta(0)
def __repr__(self): return "<%s '%s'>" % (self.__class__.__name__, self.__name)
[docs] def localize(self, dt, is_dst=False): if dt.tzinfo is not None: raise ValueError("Not naive datetime (tzinfo is already set)") return dt.replace(tzinfo=self)
def __getinitargs__(self): return self.__name, self.__offset
[docs] def pop_tz_offset_from_string(date_string, as_offset=True): if _search_regex_ignorecase.search(date_string): for name, info in _tz_offsets: timezone_re = info["regex"] timezone_match = timezone_re.search(date_string) if timezone_match: start, stop = timezone_match.span() date_string = date_string[: start + 1] + date_string[stop:] return ( date_string, StaticTzInfo(name, info["offset"]) if as_offset else name, ) return date_string, None
[docs] def word_is_tz(word): return bool(_search_regex.match(word))
[docs] def convert_to_local_tz(datetime_obj, datetime_tz_offset): return datetime_obj - datetime_tz_offset + local_tz_offset
[docs] def build_tz_offsets(search_regex_parts): def get_offset(tz_obj, regex, repl="", replw=""): return ( tz_obj[0], { "regex": re.compile( re.sub(repl, replw, regex % tz_obj[0]), re.IGNORECASE ), "offset": timedelta(seconds=tz_obj[1]), }, ) for tz_info in timezone_info_list: for regex in tz_info["regex_patterns"]: for tz_obj in tz_info["timezones"]: search_regex_parts.append(tz_obj[0]) yield get_offset(tz_obj, regex) # alternate patterns for replace, replacewith in tz_info.get("replace", []): search_regex_parts.append(re.sub(replace, replacewith, tz_obj[0])) yield get_offset(tz_obj, regex, repl=replace, replw=replacewith)
[docs] def get_local_tz_offset(): offset = datetime.now() - datetime.now(tz=timezone.utc).replace(tzinfo=None) offset = timedelta(days=offset.days, seconds=round(offset.seconds, -1)) return offset
local_tz_offset = get_local_tz_offset() _tz_offsets = None _search_regex = None _search_regex_ignorecase = None def _load_offsets(cache_path, current_hash): global _tz_offsets, _search_regex, _search_regex_ignorecase try: with open(cache_path, mode="rb") as file: ( serialized_hash, _tz_offsets, _search_regex, _search_regex_ignorecase, ) = pickle.load(file) if current_hash is None or current_hash == serialized_hash: return except (FileNotFoundError, ValueError, TypeError): pass _search_regex_parts = [] _tz_offsets = list(build_tz_offsets(_search_regex_parts)) _search_regex = re.compile("|".join(_search_regex_parts)) _search_regex_ignorecase = re.compile("|".join(_search_regex_parts), re.IGNORECASE) with open(cache_path, mode="wb") as file: pickle.dump( (current_hash, _tz_offsets, _search_regex, _search_regex_ignorecase), file, protocol=5, ) CACHE_PATH = Path(__file__).parent.joinpath("data", "dateparser_tz_cache.pkl") if "BUILD_TZ_CACHE" in os.environ: current_hash = zlib.crc32(str(timezone_info_list).encode("utf-8")) else: current_hash = None _load_offsets(CACHE_PATH, current_hash)