python:跨夏令时更改的“datetime”对象之间的时间差不正确(?)

问题描述 投票:0回答:1
我有两个

datetimes

,一个代表时间更改之前的某个时间,另一个代表第一个 
datetime
 之后一个日历日的同一时间。我预计这两个对象之间的时间差不会正好是一天,但这就是我所看到的(使用 python3.8,这是我必须使用的所有内容)。

取与

datetimes 关联的 timestamps

 的差异,返回的正是我期望看到的内容。在我看来,当 
datetime
 对象跨越时间变化时,它们的差异看起来完全是错误的。

这是预期的行为吗?

from datetime import datetime, timedelta from dateutil.tz import gettz # pip install dateutil def iso(dt): return dt.strftime('%FT%T%z') # Daylight saving time begins at 2 a.m. local time on Sunday, March 10, 2024 us_central = gettz('US/Central') before = datetime(2024, 3, 9, 15, 22, 1, tzinfo=us_central) after = datetime(2024, 3, 10, 15, 22, 1, tzinfo=us_central) print() print(f'before time change: {iso(before)}') print(f' after time change: {iso(after)}') naive = after - before by_timestamps = timedelta(seconds = after.timestamp() - before.timestamp()) difference_difference = naive.total_seconds() - by_timestamps.total_seconds() print() print('Differences:') print(f' naive: {repr(naive)}') print(f'by timestamps: {repr(by_timestamps)}') print(f' error: {difference_difference}s')
输出(python3.8)

before time change: 2024-03-09T15:22:01-0600 after time change: 2024-03-10T15:22:01-0500 Differences: naive: datetime.timedelta(days=1) by timestamps: datetime.timedelta(seconds=82800) error: 3600.0s
    
python datetime dst
1个回答
0
投票
来自

cpython 的源代码(纯 Python 后备模块,尽管我希望结果与 C 代码相同):

class datetime: ... def __sub__(self, other): "Subtract two datetimes, or a datetime and a timedelta." if not isinstance(other, datetime): if isinstance(other, timedelta): return self + -other return NotImplemented days1 = self.toordinal() days2 = other.toordinal() secs1 = self._second + self._minute * 60 + self._hour * 3600 secs2 = other._second + other._minute * 60 + other._hour * 3600 base = timedelta(days1 - days2, secs1 - secs2, self._microsecond - other._microsecond) if self._tzinfo is other._tzinfo: return base myoff = self.utcoffset() otoff = other.utcoffset() if myoff == otoff: return base if myoff is None or otoff is None: raise TypeError("cannot mix naive and timezone-aware time") return base + otoff - myoff

请注意,没有代码可以解释夏令时的变化。

因此,我建议在执行任何 timedelta 计算之前将日期时间对象本地化为 UTC。

如果你的代码需要精确到秒,请注意 Python 也会忽略闰秒,甚至 Unix 时间(由

.timestamp()

 生成)也会做出错误的选择。在闰秒周围减去两个 Unix 时间戳将会减少一,因为即使时间戳
看起来独立于日历,它们也被修补以向后兼容假设每天固定秒数的代码。

© www.soinside.com 2019 - 2024. All rights reserved.