当减去从字符串转换的日期时间时,total_seconds() 是错误的

When subtracting a datetime that was converted from string, total_seconds() is wrong

我这样做时 total_seconds() 不正确:

from datetime import timedelta, datetime
from pytz import timezone

timezone = timezone('Australia/Sydney')
startDate = datetime.now(timezone)
dateStr = '2020-05-18 20:12:30' # In our brain we know this time is in Sydney Time
endDate = datetime.strptime(dateStr, '%Y-%m-%d %H:%M:%S').replace(tzinfo=timezone)

diff = endDate - startDate
print(diff.total_seconds()) # incorrect answer

两个datetime对象原本都是datetime对象,你减去它们就对了

from datetime import timedelta, datetime
from pytz import timezone

timezone = timezone('Australia/Sydney')
startDate = datetime.now(timezone)
endDate = datetime.now(timezone) + timedelta(hours=2, seconds=32)

diff = endDate - startDate
print(diff.total_seconds()) # correct answer

我该如何解决我的问题?

因此,在日期时间、时区和偏移量的可怕世界中,似乎所有事物都是这些奇怪而美妙的事物之一。该问题似乎源于 pytz.timezone 将 return 具有多个时区的时区对象这一事实。

{
(datetime.timedelta(seconds=36300), datetime.timedelta(0), 'LMT'): <DstTzInfo 'Australia/Sydney' LMT+10:05:00 STD>, 
(datetime.timedelta(seconds=36000), datetime.timedelta(0), 'AEST'): <DstTzInfo 'Australia/Sydney' AEST+10:00:00 STD>, 
(datetime.timedelta(seconds=39600), datetime.timedelta(seconds=3600), 'AEDT'): <DstTzInfo 'Australia/Sydney' AEDT+11:00:00 DST>
}

似乎当您将时区传递给 now 方法时,它可能会根据您设置中的某些本地 TZINFO 从您选择的 3 中选择时区。但是,当通过时区进行替换时,它只是选择了相差 300 的 LMT。关于 LMT 的快速提及:

Local Mean Time Today: While Local Mean Time does not directly determine civil time these days, it is still used to make sure our clocks follow the Sun as closely as possible. UT1, a version of Universal Time is the Local Mean Time at the prime meridian in Greenwich, London. It is one of the components used to calculate Coordinated Universal Time (UTC), the time scale used to determine local times worldwide.

LMT is also used by astronomers around the world to time their observations.

本质上,您的问题涉及 datetime.now() 作用于本地时区和 datetime.replace() 作用于 LMT 时区。因此,正如我在 post 中提到的,始终如一地创建您的日期,或者通过替换同时创建它们(尽管就实际时间而言,您仍然会延迟 5 分钟,但差异将是正确的。)

更新

如果您希望两个 datetime 天体都采用悉尼本地时间,那么您可以像使用 datetime.now() 之前一样创建星历。但是您应该根据您的时区对象创建结束日期,要求它根据您的喜好对其进行本地化。

from datetime import datetime
from pytz import timezone

timezone = timezone('Australia/Sydney')
startDate = datetime.now(timezone)
dateStr = '2020-05-18 18:52:30' # In our brain we know this time is in Sydney Time
endDate = timezone.localize(datetime.strptime(dateStr, '%Y-%m-%d %H:%M:%S'))
print(startDate, endDate, sep="\n")
diff = endDate - startDate
print(diff.total_seconds())

输出

2020-05-18 18:51:24.722614+10:00
2020-05-18 18:52:30+10:00
65.277386