def dehydrate_datetime(value): """ Dehydrator for `datetime` values. :param value: :type value: datetime :return: """ def seconds_and_nanoseconds(dt): if isinstance(dt, datetime): dt = DateTime.from_native(dt) zone_epoch = DateTime(1970, 1, 1, tzinfo=dt.tzinfo) t = dt.to_clock_time() - zone_epoch.to_clock_time() return t.seconds, t.nanoseconds tz = value.tzinfo if tz is None: # without time zone value = utc.localize(value) seconds, nanoseconds = seconds_and_nanoseconds(value) return Structure(b"d", seconds, nanoseconds) elif hasattr(tz, "zone") and tz.zone: # with named time zone seconds, nanoseconds = seconds_and_nanoseconds(value) return Structure(b"f", seconds, nanoseconds, tz.zone) else: # with time offset seconds, nanoseconds = seconds_and_nanoseconds(value) return Structure(b"F", seconds, nanoseconds, tz.utcoffset(value).seconds)
def dehydrate_datetime(value): """ Dehydrator for `datetime` values. :param value: :type value: datetime :return: """ def seconds_and_nanoseconds(dt): zone_epoch = datetime(1970, 1, 1, tzinfo=dt.tzinfo) total_seconds = (dt - zone_epoch).total_seconds() whole_seconds = int(total_seconds) fraction_of_second = total_seconds - whole_seconds microseconds = int(round(1000000 * fraction_of_second)) return whole_seconds, 1000 * microseconds tz = value.tzinfo if tz is None: # without time zone value = utc.localize(value) seconds, nanoseconds = seconds_and_nanoseconds(value) return Structure(b"d", seconds, nanoseconds) elif hasattr(tz, "zone") and tz.zone: # with named time zone seconds, nanoseconds = seconds_and_nanoseconds(value) return Structure(b"f", seconds, nanoseconds, tz.zone) else: # with time offset seconds, nanoseconds = seconds_and_nanoseconds(value) return Structure(b"F", seconds, nanoseconds, tz.utcoffset(value).seconds)
def dehydrate_datetime(value): """ Dehydrator for `datetime` values. :param value: :type value: datetime :return: """ def seconds_and_nanoseconds(dt): whole_seconds, fraction_of_second = divmod((dt - UNIX_EPOCH_DATETIME_UTC).total_seconds(), 1) return int(whole_seconds), int(1000000000 * fraction_of_second) # Save the TZ info as this will get lost during the conversion to UTC tz = value.tzinfo if tz is None: # without time zone value = utc.localize(value) seconds, nanoseconds = seconds_and_nanoseconds(value) return Structure(b"d", seconds, nanoseconds) elif hasattr(tz, "zone") and tz.zone: # with named time zone value = value.astimezone(utc) seconds, nanoseconds = seconds_and_nanoseconds(value) return Structure(b"f", seconds, nanoseconds, tz.zone) else: # with time offset value = value.astimezone(utc) seconds, nanoseconds = seconds_and_nanoseconds(value) return Structure(b"F", seconds, nanoseconds, tz.utcoffset(value).seconds)
def dehydrate_point(value): """ Dehydrator for Point data. :param value: :type value: Point :return: """ dim = len(value) if dim == 2: return Structure(b"X", value.srid, *value) elif dim == 3: return Structure(b"Y", value.srid, *value) else: raise ValueError("Cannot dehydrate Point with %d dimensions" % dim)
def dehydrate_time(value): """ Dehydrator for `time` values. :param value: :type value: time :return: """ minutes = 60 * value.hour + value.minute seconds = 60 * minutes + value.second microseconds = 1000000 * seconds + value.microsecond nanoseconds = 1000 * microseconds if value.tzinfo: return Structure(b"T", nanoseconds, value.tzinfo.utcoffset(value).seconds) else: return Structure(b"t", nanoseconds)
def dehydrate_date(value): """ Dehydrator for `date` values. :param value: :type value: Date :return: """ return Structure(b"D", value.toordinal() - UNIX_EPOCH_DATE.toordinal())
def dehydrate_duration(value): """ Dehydrator for `duration` values. :param value: :type value: Duration :return: """ return Structure(b"E", value.months, value.days, value.seconds, int(1000000000 * value.subseconds))
def dehydrate_time(value): """ Dehydrator for `time` values. :param value: :type value: Time :return: """ if isinstance(value, Time): nanoseconds = int(value.ticks * 1000000000) elif isinstance(value, time): nanoseconds = (3600000000000 * value.hour + 60000000000 * value.minute + 1000000000 * value.second + 1000 * value.microsecond) else: raise TypeError("Value must be a neotime.Time or a datetime.time") if value.tzinfo: return Structure(b"T", nanoseconds, value.tzinfo.utcoffset(value).seconds) else: return Structure(b"t", nanoseconds)
def dehydrate_date(value): """ Dehydrator for `date` values. :param value: :type value: date :return: """ delta = value - UNIX_EPOCH_DATE return Structure(b"D", delta.days)
def dehydrate_timedelta(value): """ Dehydrator for `timedelta` values. :param value: :type value: timedelta :return: """ months = 0 days = value.days seconds = value.seconds nanoseconds = 1000 * value.microseconds return Structure(b"E", months, days, seconds, nanoseconds)
def dehydrate_duration(value): """ Dehydrator for `duration` values. :param value: :type value: duration :return: """ months = 12 * value.years + value.months days = value.days seconds, fraction_of_second = divmod(value.seconds, 1) seconds = 60 * (60 * value.hours + value.minutes) + int(seconds) nanoseconds = 1000 * int(round(1000000 * fraction_of_second)) return Structure(b"E", months, days, seconds, nanoseconds)
def test_tiny_struct(self): self.assert_packable(Structure(b"Z", u"A", 1), b"\xB2Z\x81A\x01")
def test_empty_struct(self): self.assert_packable(Structure(b"X"), b"\xB0X")
def test_illegal_signature(self): with self.assertRaises(ValueError): self.assert_packable(Structure(b"XXX"), b"\xB0XXX")