在将一些代码从Python 2移植到Python 3时,测试时突出显示了使用datetime.datetime
计算日期的数字回归,我很难解释。
如何重现
date_max = datetime.datetime(2016, 9, 28, 4, 21, 5, 228000)
date_min = datetime.datetime(2016, 9, 28, 4, 21, 4, 460315)
date_futur = date_min + datetime.timedelta(seconds=((date_max - date_min).total_seconds() / 2))
输出
Python 2.7.12中print date_futur
的输出:
2016-09-28 04:21:04.844158
Python 3.5.2中print(date_futur)
的输出:
2016-09-28 04:21:04.844157
问题
这只是一微秒的差异,但它让我感到困惑,因为我无法解释它,所以我不知道我是否可以使用新的Python 3行为更新我的测试结果,或者是否有更复杂的东西。
可能的线索
也许是因为Python 3如何将0.5舍入到最接近的偶数,而不是像Python 2那样?
更新
两种情况下(date_max - date_min).total_seconds() / 2
的结果均为0.8441575秒。但是,一旦交给datetime.timedelta
构造函数:
Python 2:
datetime.timedelta(0, 0, 383843)
Python 3:
datetime.timedelta(0, 0, 383842)
所以在timedelta
构造函数中发生了一些不可思议的事情!
答案 0 :(得分:2)
造成这种差异的原因是Python 2和3的不同划分行为.Python 2使用整数除法,而Python 3使用浮点除法。
3 / 2
在Python 2中输出1
,在Python 3中输出1.5
。
因此,罪魁祸首就是你的代码的一部分:
(date_max - date_min).total_seconds() / 2
使用from __future__ import division
将导致Python 2使用浮点除法。将2
更改为2.0
也会使Python使用浮动除法。
答案 1 :(得分:0)
从datetime官方Python 3文档:
如果任何参数是浮点数并且存在小数微秒,则将所有参数遗留的小数微秒组合在一起,并使用圆形半到偶数决胜局将它们的总和四舍五入到最接近的微秒。如果没有参数是浮点数,则转换和规范化过程是准确的(没有信息丢失)。
用数值替换,我们正在做:
datetime.timedelta(seconds=0.3838425)
然后将浮点值0.3838425转换为微秒,产生383842.5微秒。然后在Python 2中将其四舍五入为383843(.5总是向上舍入),在Python 3中舍入到383842(舍入到最接近的偶数)。误导的是这个值然后被添加到具有奇数微秒(460315)的另一个日期,翻转最终结果的奇偶校验!