bson.json_util 日期时间编码和解码最佳实践
Posted
技术标签:
【中文标题】bson.json_util 日期时间编码和解码最佳实践【英文标题】:bson.json_util datetime encode and decode best practice 【发布时间】:2015-04-20 03:30:32 【问题描述】:我正在尝试使用 pymongo 的 bson 工具对 python 日期时间对象进行编码和解码。 这里的最佳做法是什么?
>>> from bson import json_util
>>> import datetime
>>> utcnow = datetime.datetime.utcnow()
>>> x = json_util.dumps('now': utcnow)
>>> json_util.loads(x)['now'] == utcnow
False
>>> json_util.loads(x)['now'] - utcnow
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can't subtract offset-naive and offset-aware datetimes
>>> json_util.loads(x)['now'].replace(tzinfo=None) - utcnow
datetime.timedelta(-1, 86399, 999088)
>>> datetime.datetime.utcfromtimestamp(1424297808578 / 1000) == json_util.loads(x)['now'].replace(tzinfo=None)
True
^ 这真的是最好的方法吗? 或者编写自己的编码/解码并使用 json 库?
【问题讨论】:
【参考方案1】:似乎bson
舍入到毫秒:
>>> from datetime import datetime
>>> import bson # $ pip install bson
>>> d = datetime.utcnow(); d, abs(d - bson.loads(bson.dumps('utcnow': d))['utcnow'].replace(tzinfo=None))
(datetime.datetime(2015, 2, 18, 23, 54, 47, 733092), datetime.timedelta(0, 0, 92))
这是一个documented behavior:
UTC 日期时间 - int64 是自 Unix 纪元以来的 UTC 毫秒数。
如果您需要微秒:您可以存储自 Unix 纪元以来的整数微秒:
from datetime import datetime
td = utc_dt - datetime(1970, 1, 1)
micros = td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6
要将自 Unix 纪元以来的微秒转换回表示 UTC 时间的原始日期时间对象:
from datetime import datetime, timedelta
utc_dt = datetime(1970, 1, 1) + timedelta(microseconds=micros)
int64 ("\x12") 足以以微秒分辨率表示 Unix 时间(无论如何它超过了datetime
范围)。
注意:POSIX 时间戳“忘记”闰秒,例如:
import time
tt = time.strptime("2015-07-01 01:59:60", "%Y-%m-%d %H:%M:%S")
ts_leap = time.mktime(tt)
tt = time.strptime("2015-07-01 02:00:00", "%Y-%m-%d %H:%M:%S")
ts_after = time.mktime(tt)
assert ts_leap == ts_after # assuming "right" timezone is not used
如果您关心微秒;你应该找出你的系统在闰秒前后做了什么。
普通计算机上的时间(hardware clocks, software timers)不是很准确,因此在许多情况下毫秒分辨率应该足够了,例如,如果您使用ntp
来同步机器之间的时间,那么NTP v3 is accurate to 1-2ms in a LAN and 10s of ms in WAN nets。
尽管有时您希望保留输入中的数字,即使它们不准确。
【讨论】:
我不一定“需要”任何东西,我希望能够编码;解码;比较 == 真; @estobbart:您可以与毫秒分辨率进行比较abs(a-b) <= timedelta(microseconds=500)
或存储微秒,如答案所示。它是由你决定。两者都是不同应用程序中的有效选择。
我不介意投反对票,但希望得到解释以上是关于bson.json_util 日期时间编码和解码最佳实践的主要内容,如果未能解决你的问题,请参考以下文章