我正在研究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__())
输入:
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),]
结果:
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)
正如您所看到的,对于指定年,月,日的所有输入,每个测试中的最佳答案(使用时间戳)为1。当输入中包含小时,分钟,秒和微秒args时,可以获得正确的答案。
答案 0 :(得分: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
结果:
189 2011-10-30 23:00:00 2011-10-31 00:00:00
如您所见,10月30日存在差异。这是for many countries,是我们看到夏令时调整的第二个日期。
更新:此处提出类似问题:Difference between evaluating timestamp and total_seconds。造成差异的根本原因是datetime.timedelta
没有考虑DST,而timestamp
确实考虑到了这一点。
答案 1 :(得分:1)
这很可能是由时区问题引起的。我怀疑当你转换为时间戳并回到日期时间时,时区信息会丢失。