我将以4个字节存储的日期和时间转换为Python格式。我先想出天真的做法。然后我尝试使用ctypes
所以它应该更快:
from ctypes import *
from datetime import datetime
def bit_unpack(data, bits):
value = int.from_bytes(data, "big")
unpacked = []
for i, field in enumerate(bits):
shift = sum(bits[i+1:])
mask = 2 ** field - 1
bit_field = (value >> shift) & mask
unpacked.append(bit_field)
return unpacked
def to_date(data):
y, m, d, h, n, s = bit_unpack(data, (6, 4, 5, 5, 6, 6))
return datetime(1980 + y, m, d, h, n, s)
class PackedDate(BigEndianStructure):
_fields_ = [
("year", c_uint, 6),
("month", c_uint, 4),
("day", c_uint, 5),
("hours", c_uint, 5),
("minutes", c_uint, 6),
("seconds", c_uint, 6),
]
class Transfer(Union):
_fields_ = [
("bytes", c_uint32),
("date", PackedDate),
]
def to_date2(data):
transfer = Transfer()
transfer.bytes = int.from_bytes(data, "little")
date = transfer.date
return datetime(date.year + 1980, date.month, date.day, date.hours, date.minutes, date.seconds)
if __name__ == "__main__":
byte_data = b'q\xa6\xb1\xdf'
print(to_date(byte_data))
print(to_date2(byte_data))
import timeit
print(timeit.timeit("to_date(byte_data)", r"from bitunpack import to_date; byte_data = b'q\xa6\xb1\xdf'"))
print(timeit.timeit("to_date2(byte_data)", r"from bitunpack import to_date2; byte_data = b'q\xa6\xb1\xdf'"))
然而,我不喜欢的是这部分:
transfer.bytes = int.from_bytes(data, "little")
我将4个字节转换为uint32。我可以更改我的联盟,以便能够更容易地接受4字节数组而不首先将其转换为uint32吗?我尝试了c_ubyte * 4
,但获得了TypeError: expected c_ubyte_Array_4 instance, got bytes
。
答案 0 :(得分:0)
您可以使用所有ctypes
类型上提供的from_buffer_copy
方法直接从PackedDate
数据创建bytes
对象:
>>> date = PackedDate.from_buffer_copy(data)
>>> datetime(date.year + 1980, date.month, date.day, date.hours, date.minutes, date.seconds)
datetime.datetime(2008, 6, 19, 11, 7, 31)