Python中datetime对象不等问题:过期检测程序未触发终止
嘿,我来帮你把这两个Python datetime相关的问题讲明白,都是日常开发里容易踩的小坑~
问题1:为什么Python的datetime对象会不等于自身?
这种情况并不常见,但通常出现在这几个场景里:
- 浮点数精度问题:当你通过时间戳(比如
datetime.datetime.fromtimestamp(timestamp))创建datetime对象时,时间戳是浮点数,而浮点数本身存在精度限制,可能导致生成的datetime对象在微秒级有细微差异。比如两个看似完全相同的datetime,实际微秒部分差了1,这时候用==比较就会返回False。 - 时区对象的实例差异:如果你的datetime是带时区(tzinfo)的,即使两个datetime的时间和时区逻辑上完全一致,但如果tzinfo是不同的实例(比如用pytz创建的时区,多次调用可能生成不同实例),
==比较会返回False。因为datetime的__eq__方法会严格检查tzinfo的身份,而不仅仅是时区信息是否一致。 - 序列化/反序列化后的对象:比如把datetime对象存入数据库再读出来,或者用JSON序列化后反序列化,可能会丢失部分精度(比如数据库只存储到秒,而Python的datetime保留微秒),导致对象和原来的自身不相等。
举个浮点数精度导致问题的小例子:
import datetime ts = 1620000000.123456789 dt1 = datetime.datetime.fromtimestamp(ts) dt2 = datetime.datetime.fromtimestamp(ts) # 看起来是同一个时间,但实际微秒可能有差异 print(dt1 == dt2) # 大概率输出False
问题2:检测过期的程序为何运行20秒后不终止?
你的代码逻辑的核心问题在于用==精确匹配两个datetime对象,这几乎是不可能命中的!
原因很简单:datetime.datetime.now()会返回精确到微秒的当前时间。你设置的expired_on是当前时间加20秒,比如假设此刻是2024-05-20 12:00:00.123456,那么expired_on就是2024-05-20 12:00:20.123456。而循环里每次调用datetime.datetime.now()得到的X,只有在精确到微秒完全重合的时候才会触发break——但循环执行需要时间,系统时钟的精度也不会让你刚好在那个微秒点执行判断语句,所以这个条件几乎永远不会满足。
正确的做法是用大于等于来判断,只要当前时间超过或等于过期时间就终止循环:
import datetime expired_on = datetime.datetime.now() + datetime.timedelta(seconds=20) while True: X = datetime.datetime.now() if X >= expired_on: print(f"{X} is expired.") break
内容的提问来源于stack exchange,提问作者John Albert Flores
相关产品推荐
相关产品推荐

