def is_aware(value: datetime.time): """Determine if a given datetime.datetime is aware. The concept is defined in Python's docs: https://docs.python.org/library/datetime.html#datetime.tzinfo Assuming value.tzinfo is either None or a proper datetime.tzinfo, value.utcoffset() implements the appropriate logic. """ return value.utcoffset() is not None
def _unconvert_time(self, value: datetime.time): if not hasattr(value, "utcoffset") or value.utcoffset() is None: msg = f"'{value}' isn't a timezone-aware {self.__type__} instance; can't convert to GMT" raise ValueError(msg) # Transform to GMT dt = datetime.datetime( 1999, 6, 8, value.hour, value.minute, value.second, microsecond=value.microsecond, ) dt -= value.utcoffset() # type: ignore milliseconds = "{0:03d}".format((dt.microsecond + 500) // 1000) fmt = "%H%M%S.{}[0:GMT]".format(milliseconds) return dt.strftime(fmt)
def _time_to_millis(t: datetime.time): if t.tzinfo is not None: offset = t.utcoffset() offset = offset if offset else datetime.timedelta() offset_millis = \ (offset.days * 86400 + offset.seconds) * 10 ** 3 + offset.microseconds // 1000 else: offset_millis = TIME_EPOCH_ORDINAL minutes = t.hour * 60 + t.minute seconds = minutes * 60 + t.second return seconds * 10**3 + t.microsecond // 1000 - offset_millis
def _unconvert_time(self, value: datetime.time): if not hasattr(value, "utcoffset") or value.utcoffset() is None: msg = f"'{value}' must be a timezone-aware {self.__type__} instance" raise ValueError(msg) dt = datetime.datetime( 1999, 6, 8, value.hour, value.minute, value.second, microsecond=value.microsecond, tzinfo=value.tzinfo, ) return format_datetime("%H%M%S", dt)
def encode_time(self, value: datetime.time) -> str: """Extends parent function since ODL allows a time zone offset from UTC to be included, and otherwise recommends that times be suffixed with a 'Z' to clearly indicate that they are in UTC. """ t = super().encode_time(value) if value.tzinfo is None or value.tzinfo == 0: return t + "Z" else: td_str = str(value.utcoffset()) (h, m, s) = td_str.split(":") if s != "00": raise ValueError("The datetime value had a timezone offset " f"with seconds values ({value}) which is " "not allowed in ODL.") if m == "00": return t + "+" + h else: return t + f"+{h}:{m}"
def encode_time(self, value: datetime.time) -> str: """Extends parent function since ODL allows a time zone offset from UTC to be included, and otherwise recommends that times be suffixed with a 'Z' to clearly indicate that they are in UTC. """ t = super().encode_time(value) if value.tzinfo is None: return t + 'Z' else: td_str = str(value.utcoffset()) (h, m, s) = td_str.split(':') if s != '00': raise ValueError('The datetime value had a timezone offset ' f'with seconds values ({value}) which is ' 'not allowed in ODL.') if m == '00': return t + '+' + h else: return t + f'+{h}:{m}'
def dump(self, obj: time) -> bytes: us = obj.microsecond + 1_000_000 * (obj.second + 60 * (obj.minute + 60 * obj.hour)) off = obj.utcoffset() assert off is not None return _pack_timetz(us, -int(off.total_seconds()))
def time_encoder(time: datetime.time): if time.utcoffset() is not None: raise ValueError("JSON can't represent timezone-aware times.") return time.isoformat()
def _convert_time(self, value: datetime.time): if value.utcoffset() is None: raise ValueError(f"{value} is not timezone-aware") return value