Module datetimecalc.tz
helper functions for working with timezones
Functions
def gen_tz_regex() ‑> re.Pattern-
Expand source code
def gen_tz_regex() -> re.Pattern: """ Generates a regular expression pattern for matching timezone strings. Returns: Compiled regular expression pattern for matching timezone abbreviations. Examples: >>> pattern = gen_tz_regex() >>> pattern.match('CEST') <re.Match object; span=(0, 4), match='CEST'> """ grouped_tzs = collections.defaultdict(list) for tzname in zoneinfo.available_timezones(): slashidx = tzname.find("/") if slashidx == -1: grouped_tzs["ROOT"].append(tzname) continue grouped_tzs[tzname[0:slashidx]].append(tzname[slashidx + 1 :]) tz_regex_parts = grouped_tzs.pop("ROOT") tz_regex_parts.extend( [ f"{region}/{noncapture_join(subregions)}" for region, subregions in grouped_tzs.items() ] ) tz_regex_parts.extend(TZ_ADDITIONS.keys()) tz_regex_parts.extend(time.tzname) return re.compile( noncapture_join( [ OFFSET_REGEX, bounded_capture_join(tz_regex_parts), ] ) )Generates a regular expression pattern for matching timezone strings.
Returns
Compiled regular expression pattern for matching timezone abbreviations.
Examples
>>> pattern = gen_tz_regex() >>> pattern.match('CEST') <re.Match object; span=(0, 4), match='CEST'> def offset_timezone(spec: str) ‑> datetime.timezone-
Expand source code
def offset_timezone(spec: str) -> datetime.timezone: """ Accepts spec strings like "-05:00", "-04:00", "+05:30" that specify a timezone based on an offset in hours and minutes east from UTC; returns a datetime.timezone. :param spec: string representing an offset from UTC; format is +/-HH:MM :return: datetime.timezone object representing the specified timezone. >>> offset_timezone('-05:00') datetime.timezone(datetime.timedelta(days=-1, seconds=68400)) >>> offset_timezone('+05:30') datetime.timezone(datetime.timedelta(seconds=19800)) """ # sanity-check if not (spec[0] in "+-" and len(spec) == 6 and spec.index(":") == 3): raise ValueError( f'Input "{spec}" is not a valid UTC offset string. ' "Must be in the format +/-HH:MM." ) # split and parse sign, hours, minutes = spec[0], int(spec[1:3]), int(spec[4:]) # make the timedelta offset_in_minutes = hours * 60 + minutes if sign == "-": offset_in_minutes = -offset_in_minutes return datetime.timezone(datetime.timedelta(minutes=offset_in_minutes))Accepts spec strings like "-05:00", "-04:00", "+05:30" that specify a timezone based on an offset in hours and minutes east from UTC; returns a datetime.timezone.
:param spec: string representing an offset from UTC; format is +/-HH:MM :return: datetime.timezone object representing the specified timezone.
>>> offset_timezone('-05:00') datetime.timezone(datetime.timedelta(days=-1, seconds=68400)) >>> offset_timezone('+05:30') datetime.timezone(datetime.timedelta(seconds=19800)) def search_tz(input_date: str, fullmatch: bool = False) ‑> Tuple[datetime.tzinfo | None, str | None]-
Expand source code
def search_tz( input_date: str, fullmatch: bool = False ) -> Tuple[Optional[datetime.tzinfo], Optional[str]]: """ Searches for a timezone name in an input date string and returns the corresponding ZoneInfo object. If 'fullmatch' is True, the entire input_date string must be a timezone name. Args: input_date: A string representing a date with a timezone in it. fullmatch: Indicates that the search must match the entire input_date string. Returns: The ZoneInfo object corresponding to the timezone if found, else None. The input_date with any matched timezone deleted, else None Examples: >>> search_tz("Sun 13 Aug 2023 09:08:52 AM CEST") (zoneinfo.ZoneInfo(key='Europe/Brussels'), 'Sun 13 Aug 2023 09:08:52 AM ') >>> search_tz("Sun 13 Aug 2023 09:08:52 AM EST") (zoneinfo.ZoneInfo(key='EST'), 'Sun 13 Aug 2023 09:08:52 AM ') """ search_func = tz_regex.fullmatch if fullmatch else tz_regex.search match = search_func(input_date) if not match: return None, None name = match.group(1) if match.group(1) else match.group(2) filtered_input = delspan(input_date, match.span()) # Check if the name is actually an offset try: return offset_timezone(name), filtered_input except ValueError: pass try: return zoneinfo.ZoneInfo(name), filtered_input except zoneinfo.ZoneInfoNotFoundError: pass # Check if name matches the local timezone abbreviations if name in time.tzname: # If we have a TZ envvar set, we use the ZoneInfo matching that if tz_env := os.environ.get("TZ"): return zoneinfo.ZoneInfo(tz_env), filtered_input # Return a ZoneInfo based on UTC offset utc_offset_sec = time.altzone if time.localtime().tm_isdst else time.timezone utc_offset = datetime.timedelta(seconds=utc_offset_sec) return datetime.timezone(utc_offset), filtered_input try: return zoneinfo.ZoneInfo(TZ_ADDITIONS[name]), filtered_input except zoneinfo.ZoneInfoNotFoundError: pass except KeyError: pass return None, NoneSearches for a timezone name in an input date string and returns the corresponding ZoneInfo object. If 'fullmatch' is True, the entire input_date string must be a timezone name.
Args
input_date- A string representing a date with a timezone in it.
fullmatch- Indicates that the search must match the entire input_date string.
Returns
The ZoneInfo object corresponding to the timezone if found, else None. The input_date with any matched timezone deleted, else None
Examples
>>> search_tz("Sun 13 Aug 2023 09:08:52 AM CEST") (zoneinfo.ZoneInfo(key='Europe/Brussels'), 'Sun 13 Aug 2023 09:08:52 AM ')>>> search_tz("Sun 13 Aug 2023 09:08:52 AM EST") (zoneinfo.ZoneInfo(key='EST'), 'Sun 13 Aug 2023 09:08:52 AM ')