Car*_*res 5 python datetime unix-timestamp python-3.x python-3.4
我想将微秒分辨率的日期时间保存为时间戳。但似乎 Python 3 日期时间模块在加载它们时丢失了一微秒。为了测试这一点,让我们创建一个脚本:
test_datetime.py:
from random import randint
from datetime import datetime
now = datetime.now()
for n in range(1000):
d = datetime(year=now.year, month=now.month, day=now.day,
hour=now.hour, minute=now.minute, second=now.second,
microsecond=randint(0,999999))
ts = d.timestamp()
d2 = datetime.fromtimestamp(ts)
assert d == d2, 'failed in pass {}: {} != {}'.format(n, d, d2)
Run Code Online (Sandbox Code Playgroud)
python3 test_datetime.py总是会失败一微秒:
Traceback (most recent call last):
File "test_datetime.py", line 14, in <module>
assert d == d2, 'failed in pass {}: {} != {}'.format(n, d, d2)
AssertionError: failed in pass 4: 2014-07-02 11:51:46.984716 != 2014-07-02 11:51:46.984715
Run Code Online (Sandbox Code Playgroud)
这种行为值得接受吗?如果我们想要微秒分辨率,我们不应该依赖 datetime.fromtimestamp 吗?
时间戳是一个 POSIX 时间,本质上被概念化为自任意“纪元”以来的整数秒数。datetime.fromtimestamp()返回“与 POSIX 时间戳相对应的本地日期和时间,例如由time.time()”返回,其文档告诉我们“以浮点数形式返回自纪元以来的秒数时间。请注意,即使时间始终是作为浮点数返回,并非所有系统都提供比 1 秒更好的时间精度。”
当中间数据类型实际上不能保证亚秒级精度时,期望通过与时间戳的转换来保留六位十进制数字的精度似乎有点不合理。浮点数无法准确表示所有十进制值。
编辑:以下代码测试程序运行时哪些微秒值对于任意日期时间无效。
from datetime import datetime
baset = datetime.now()
dodgy = []
for i in range(1000000):
d = baset.replace(microsecond=i)
ts = d.timestamp()
if d != datetime.fromtimestamp(ts):
dodgy.append(i)
print(len(dodgy))
Run Code Online (Sandbox Code Playgroud)
我得到了 499,968 次“狡猾”的次数,但我还没有检查过它们。