使用时间戳与使用timedelta的时间添加之间的差异?

geo*_*opy 5 python datetime timedelta

我正在研究Exercism.io gigasecond问题:

"计算一个人活了10 ^ 9秒的时刻."

我的方法是将日期时间输入转换为时间戳,添加10**9,然后转换回来.我的答案非常接近,但测试套件(由Exercism提供)失败了,因为小时arg关闭了一个.所有其他args都是正确的.

经过一番搜索,我找到了一个使用timedelta的答案; 答案的结构几乎与我的相同,但它产生了完整正确的答案.

我的问题是,为什么这两种方法的输出有差异?如下所示,只有当小时的输入arg为默认值0时,才会出现问题.

码:

def add_gigasecond(birth_date):
    gigadate = birth_date.timestamp() + 10**9
    print(datetime.fromtimestamp(gigadate).__repr__())

    gigadate = birth_date + timedelta(seconds=10**9)
    print(gigadate.__repr__())
Run Code Online (Sandbox Code Playgroud)

输入:

tests = [datetime(2011, 4, 25),
         datetime(1977, 6, 13),
         datetime(1959, 7, 19),
         datetime(2015, 1, 24, 22, 0, 0),
         datetime(2015, 1, 24, 23, 59, 59),]
Run Code Online (Sandbox Code Playgroud)

结果:

test 1
datetime.datetime(2043, 1, 1, 0, 46, 40)
datetime.datetime(2043, 1, 1, 1, 46, 40)

test 2
datetime.datetime(2009, 2, 19, 0, 46, 40)
datetime.datetime(2009, 2, 19, 1, 46, 40)

test 3
datetime.datetime(1991, 3, 27, 0, 46, 40)
datetime.datetime(1991, 3, 27, 1, 46, 40)

test 4
datetime.datetime(2046, 10, 2, 23, 46, 40)
datetime.datetime(2046, 10, 2, 23, 46, 40)

test 5
datetime.datetime(2046, 10, 3, 1, 46, 39)
datetime.datetime(2046, 10, 3, 1, 46, 39)
Run Code Online (Sandbox Code Playgroud)

如您所见,对于指定年,月,日的所有输入,每个测试中的最佳答案(使用时间戳)偏差为1.当输入中包含小时,分钟,秒和微秒args时,可以获得正确的答案.

jpp*_*jpp 3

夏令时

一些侦探工作可以阐明这些问题。对于本次调查,我选择列表中的第一个日期,即 2011 年 4 月 25 日。

from datetime import datetime, timedelta

def add_seconds(birth_date, n):
    x = datetime.fromtimestamp(birth_date.timestamp() + n)
    y = birth_date + timedelta(seconds=n)
    return (x, y)

for i in range(365):
    ts, td = add_seconds(datetime(2011, 4, 25), i*60**2*24)  # add i days via seconds
    if ts-td:  # test for difference in timestamp vs timedelta methods
        print(i, ts, td)
        break
Run Code Online (Sandbox Code Playgroud)

结果:

189 2011-10-30 23:00:00 2011-10-31 00:00:00
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,10 月 30 日正好存在差异。对于许多国家/地区来说,这是一年中我们看到夏令时调整的第二个日期。

更新:这里提出了类似的问题:评估时间戳和total_seconds之间的差异。造成差异的根本原因是datetime.timedelta没有考虑 DST,而timestamp确实考虑了 DST。