Python 2和3

时间:2017-02-08 16:18:28

标签: python-2.7 python-3.x python-datetime

在将一些代码从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构造函数中发生了一些不可思议的事情!

2 个答案:

答案 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)的另一个日期,翻转最终结果的奇偶校验!