日期时间错误扣除
Datetime wrong deduction
问题陈述
似乎 python datetime
模块中存在错误,以下代码片段应该是不言自明的:
import datetime
dep = datetime.datetime(2021, 9, 11, 7, 25)
arr = datetime.datetime(2021, 9, 11, 12, 35)
print(f"expected: -5h10m, real: {dep - arr}")
print(f"expected: 5h10m, real: {arr - dep}")
我从 python 3.10 得到了什么:
expected: -5h10m, real: -1 day, 18:50:00
expected: 5h10m, real: 5:10:00
问题
这是错误还是功能?如果是错误,我该如何修复它?
我会称之为效果
expected: -5h10m, real: -1 day, 18:50:00
expected: 5h10m, real: 5:10:00
故障,因为它仅限于查看,而两个增量保持相同的秒数并且等于它们的对立面,可以按如下方式检查
import datetime
dep = datetime.datetime(2021, 9, 11, 7, 25)
arr = datetime.datetime(2021, 9, 11, 12, 35)
delta1 = dep - arr
delta2 = arr - dep
print(delta1.total_seconds()) # -18600.0
print(delta2.total_seconds()) # 18600.0
print(delta1 == -delta2) # True
print(delta2 == -delta1) # True
print(delta1 + delta2) # 0:00:00
这是一个特征 - 从 datetime
中减去 datetime
得到一个 timedelta
对象,它被归一化,因此只有负值可以是 days
。
该行为已记录在案,例如。这里:https://pl.python.org/docs/lib/datetime-timedelta.html
您可以查看 datetime 对象中 subtract 的实现,但它基本上与下面的代码做同样的事情。
import datetime
dep = datetime.datetime(2021, 9, 11, 7, 25)
arr = datetime.datetime(2021, 9, 11, 12, 35)
dep_days = dep.toordinal()
arr_days = dep.toordinal()
dep_secs = dep.second + dep.minute * 60 + dep.hour * 3600
arr_secs = arr.second + arr.minute * 60 + arr.hour * 3600
day_diff = dep_days - arr_days
sec_diff = dep_secs - arr_secs
micro_diff = dep.microsecond - arr.microsecond
base = datetime.timedelta(day_diff,sec_diff,micro_diff)
print(base)
timedelta 告诉你时间倒退一天然后前进 18 小时 50 分钟,这实际上意味着倒退 24 小时 + 18 小时 50 = 5 小时 10 分钟
如果您只从字符串表示的角度对此感兴趣,您可以将其包装在一个简单的函数中,该函数将为您提供时差的相对字符串表示形式
import datetime
def relative_time_str(delta: datetime.timedelta):
neutral = datetime.timedelta()
if delta < neutral:
return f"-{neutral - delta}"
return f"{delta}"
dep = datetime.datetime(2021, 9, 11, 7, 25)
arr = datetime.datetime(2021, 9, 11, 12, 35)
print(f"expected: -5h10m, real: {relative_time_str(dep - arr)}")
print(f"expected: 5h10m, real: {relative_time_str(arr - dep)}")
输出
expected: -5h10m, real: -5:10:00
expected: 5h10m, real: 5:10:00
问题陈述
似乎 python datetime
模块中存在错误,以下代码片段应该是不言自明的:
import datetime
dep = datetime.datetime(2021, 9, 11, 7, 25)
arr = datetime.datetime(2021, 9, 11, 12, 35)
print(f"expected: -5h10m, real: {dep - arr}")
print(f"expected: 5h10m, real: {arr - dep}")
我从 python 3.10 得到了什么:
expected: -5h10m, real: -1 day, 18:50:00
expected: 5h10m, real: 5:10:00
问题
这是错误还是功能?如果是错误,我该如何修复它?
我会称之为效果
expected: -5h10m, real: -1 day, 18:50:00
expected: 5h10m, real: 5:10:00
故障,因为它仅限于查看,而两个增量保持相同的秒数并且等于它们的对立面,可以按如下方式检查
import datetime
dep = datetime.datetime(2021, 9, 11, 7, 25)
arr = datetime.datetime(2021, 9, 11, 12, 35)
delta1 = dep - arr
delta2 = arr - dep
print(delta1.total_seconds()) # -18600.0
print(delta2.total_seconds()) # 18600.0
print(delta1 == -delta2) # True
print(delta2 == -delta1) # True
print(delta1 + delta2) # 0:00:00
这是一个特征 - 从 datetime
中减去 datetime
得到一个 timedelta
对象,它被归一化,因此只有负值可以是 days
。
该行为已记录在案,例如。这里:https://pl.python.org/docs/lib/datetime-timedelta.html
您可以查看 datetime 对象中 subtract 的实现,但它基本上与下面的代码做同样的事情。
import datetime
dep = datetime.datetime(2021, 9, 11, 7, 25)
arr = datetime.datetime(2021, 9, 11, 12, 35)
dep_days = dep.toordinal()
arr_days = dep.toordinal()
dep_secs = dep.second + dep.minute * 60 + dep.hour * 3600
arr_secs = arr.second + arr.minute * 60 + arr.hour * 3600
day_diff = dep_days - arr_days
sec_diff = dep_secs - arr_secs
micro_diff = dep.microsecond - arr.microsecond
base = datetime.timedelta(day_diff,sec_diff,micro_diff)
print(base)
timedelta 告诉你时间倒退一天然后前进 18 小时 50 分钟,这实际上意味着倒退 24 小时 + 18 小时 50 = 5 小时 10 分钟
如果您只从字符串表示的角度对此感兴趣,您可以将其包装在一个简单的函数中,该函数将为您提供时差的相对字符串表示形式
import datetime
def relative_time_str(delta: datetime.timedelta):
neutral = datetime.timedelta()
if delta < neutral:
return f"-{neutral - delta}"
return f"{delta}"
dep = datetime.datetime(2021, 9, 11, 7, 25)
arr = datetime.datetime(2021, 9, 11, 12, 35)
print(f"expected: -5h10m, real: {relative_time_str(dep - arr)}")
print(f"expected: 5h10m, real: {relative_time_str(arr - dep)}")
输出
expected: -5h10m, real: -5:10:00
expected: 5h10m, real: 5:10:00