Python datetime 的坑以及时间处理的经验 😇
最近遇到一个"bug",就是本地 datetime 的时间上传到数据库,总发现时间显示不对…… 经过一番痛苦的排查之后,我发现原来是 datetime.now() 在获取事件信息时,不会添加当前的时区信息。也就是说,获得的结果虽然时分秒和电脑显示一致,但是时区信息为默认的 UTC 而非我们真正的 UTC+8,因此这个时间是不对的……
如果在代码中只是用 datetime 处理以下还好,不会出什么问题,timestamp 是正确的,但是当用没有时区信息的 datetime 对象与外部进行交互时,外部会默认认为是 UTC 时间,因此发生错误!
下面用 arrow 库和 datetime 库作一下演示:
from datetime import datetime
import arrow
dt = datetime.now()
at = arrow.now()
print(dt) # 2023-09-27 20:35:46.652639
print(dt.timestamp()) # 1695818146.652639
print(dt.tzinfo) # None, 无时区信息
print(at) # 2023-09-27T20:35:46.652693+08:00
print(at.tzinfo) # tzlocal()
print(at.datetime) # 2023-09-27 20:35:46.652693+08:00, 可获得有时区信息的 datetime
print(at.timestamp()) # 1695818146.652693
print(at.datetime.timestamp()) # 1695818146.652693
print(datetime.fromtimestamp(dt.timestamp())) # 2023-09-27 20:35:46.652639 datetime 内部转化,时间正确
print(arrow.Arrow.fromdatetime(dt).timestamp()) # 1695846946.652639 跨库转化后,时间错误
添加时区信息有一些方法,但是很复杂:
python 关于为datatime 对象添加时区信息以及时区转换问题 - CSDN
教训就是,还是尽量使用时间戳来表示唯一的时间,但是由于我使用的数据库接口需要上传 datetime 类型,我选择使用 arrow 库,简化时间操作,arrow.now() 获得的时间带有时区信息!
Getting started — Arrow 🏹 1.2.3 documentation
另外,有很多库,时间的类都是基于 datetime,可以通过 isinstance(obj, datetime)
判断对象的类是否为 datetime 及其子类,如果是的话, obj.timestamp()
转化为时间戳后,再进行处理,会方便很多!