import datetime DATETIME_UNITS = { 'second': datetime.timedelta(seconds=1), 'seconds': datetime.timedelta(seconds=1), 'minute': datetime.timedelta(minutes=1), 'minutes': datetime.timedelta(minutes=1), 'hour': datetime.timedelta(hours=1), 'hours': datetime.timedelta(hours=1), 'day': datetime.timedelta(days=1), 'days': datetime.timedelta(days=1), 'week': datetime.timedelta(days=7), 'weeks': datetime.timedelta(days=7), 'month': datetime.timedelta(days=30), 'months': datetime.timedelta(days=30), 'year': datetime.timedelta(days=365), 'years': datetime.timedelta(days=365), } FORMAT_DATE_HEADER = '%a, %d %b %Y %H:%M:%S GMT' def parse_duration(text: str) -> datetime.timedelta: (num_str, unit_str) = text.split(' ') num = float(num_str) unit = DATETIME_UNITS[unit_str] return unit * num def parse_response_datetime(response) -> datetime.datetime: return datetime.datetime.strptime( response.headers['Date'], FORMAT_DATE_HEADER, ).replace(tzinfo=datetime.UTC) NOW = datetime.datetime.now(datetime.UTC) LOCAL_TIMEZONE = NOW.astimezone().tzinfo def try_parse(text: str, fmt: str) -> datetime.datetime | None: try: time = datetime.datetime.strptime(text, fmt) # noqa: DTZ007 if time.tzinfo is None: time = time.replace(tzinfo=LOCAL_TIMEZONE) except ValueError: time = None return time def parse_time(text: str) -> datetime.datetime: text = text.replace('\n', ' ') text = text.strip() time = try_parse(text, '%d %b %Y %I:%M:%S %p') time = time or try_parse(text, '%d %b, %Y @ %I:%M%p') if time is None and (m := try_parse(text, '%d %b @ %I:%M%p')): time = m.replace(year=NOW.year) if time is None: msg = 'Unknown format: ' + text raise RuntimeError(msg) if time.tzinfo is None: time = time.replace(tzinfo=LOCAL_TIMEZONE) if time.tzinfo is None: msg = 'Could not parse timezone: ' + text raise RuntimeError(msg) return time.astimezone(datetime.UTC) def parse_date(text: str) -> datetime.date: text = text.strip() if dt := try_parse(text, '%d %B %Y'): return dt.date() if dt := try_parse(text, '%b %d, %Y'): return dt.date() if dt := try_parse(text, '%B %d, %Y'): return dt.date() if dt := try_parse(text, '%b %d'): return dt.date() msg = 'Unknown format: ' + text raise RuntimeError(msg)