【问题标题】:Datetime with timezone带时区的日期时间
【发布时间】:2021-08-02 08:51:03
【问题描述】:

据我了解,python 3.9 中的 ZoneInfo 解决了 DST 时间问题的“2038 年”问题。但我可以看到timedelta 是错误的。下面应该是 2 小时,而不是 3 小时。出了什么问题?

from zoneinfo  import ZoneInfo
import datetime
dt = datetime.datetime(2038,3,14,0,0, tzinfo = ZoneInfo(r'America/New_York'))
print(dt)           
dt2 = datetime.datetime(2038,3,14,3,0, tzinfo = ZoneInfo(r'America/New_York'))
print(dt2-dt)

【问题讨论】:

  • timedeltas 在 Python 中显示 墙时差,如果您正在使用感知日期时间。在您的示例日期时间之间,虽然绝对时差只有两个小时(DST 转换),但墙壁时差为三个小时。更多解释可以在 Paul Ganssle 的this blog article 中找到。顺便提一句。这不是特定于 2k38 问题(完全不同的故事,请参阅 int32...)
  • 如何获得绝对时差而不是墙壁时差?
  • 我会转换为 UTC; print(dt2.astimezone(ZoneInfo('UTC')) - dt.astimezone(ZoneInfo('UTC')))(我认为最清晰/可读的选项)。
  • 你能把你的评论作为答案让我接受吗?

标签: python datetime timezone zoneinfo


【解决方案1】:

我认为是 3 小时,从 00(即 12)到 3 绝对是 3 小时。

【讨论】:

  • 请注意,在所示时区中的这些日期/时间实例之间存在 DST 转换。另请参阅我在问题下的评论。
【解决方案2】:
from zoneinfo  import ZoneInfo
import datetime
dt = datetime.datetime(2038,3,14,0,0, tzinfo = ZoneInfo(r'America/New_York'))
print(dt)           # Output: 2038-03-14 00:00:00-05:00
dt2 = datetime.datetime(2038,3,14,3,0, tzinfo = ZoneInfo(r'America/New_York'))
print(dt2)          # Output: 2038-03-14 03:00:00-04:00
timedelta = dt2-dt1
print(timedelta)    # Output: 3:00:00

上面的内容是正确的,因为它知道 DST,也就是在 DST 感知上下文中。 例如,如果您像下面的代码一样将 3 小时添加到 2038-03-14 00:00:00-05:00,您会得到一致的结果:

from zoneinfo  import ZoneInfo
import datetime
dt = datetime.datetime(2038,3,14,0,0, tzinfo = ZoneInfo(r'America/New_York'))
print(dt)                                      # Output: 2038-03-14 00:00:00-05:00
print(dt+datetime.timedelta(hours=3))          # Output: 2038-03-14 03:00:00-04:00

但是,在 NO-DST-AWARE 的情况下,您对 2 小时时差的想法是正确的,如下所示:

from zoneinfo  import ZoneInfo
import datetime
dt = datetime.datetime(2038,3,14,0,0, tzinfo = ZoneInfo(r'America/New_York'))
print(dt)           # Output: 2038-03-14 00:00:00-05:00
dt2 = datetime.datetime(2038,3,14,3,0, tzinfo = ZoneInfo(r'America/New_York'))
print(dt2)          # Output: 2038-03-14 03:00:00-04:00
dt_isoformat = dt.isoformat() 
print(dt_isoformat) # Output: 2038-03-14T00:00:00-05:00
dt2_isoformat = dt2.isoformat() 
print(dt2_isoformat) # Output: 2038-03-14T03:00:00-04:00
print(datetime.datetime.fromisoformat(dt2_isoformat)-datetime.datetime.fromisoformat(dt_isoformat)) # Output: 2:00:00

【讨论】:

  • 我认为“NO-DST-AWARE context”的代码示例有点令人费解;转换为 UTC 更容易(请参阅我在问题下的评论)。
猜你喜欢
  • 1970-01-01
  • 2017-03-28
  • 1970-01-01
  • 2019-01-28
  • 2022-12-17
  • 1970-01-01
  • 2014-11-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多