【问题标题】:Python datetime and tzinfo objects (changing minutes instead of hours)Python datetime 和 tzinfo 对象(更改分钟而不是小时)
【发布时间】:2017-04-06 00:53:39
【问题描述】:

我正在尝试将 tzinfo 应用于日期时间对象。

In [1]: from datetime import datetime
In [2]: import pytz

In [3]: london = pytz.timezone("Europe/London")
In [4]: london
Out[5]: <DstTzInfo 'Europe/London' LMT-1 day, 23:59:00 STD>

In [6]: localized_date_object = datetime(2016, 1, 1, 11, 30, 0, 5000, london)
In [7]: localized_date_object
Out[8]: datetime.datetime(2016, 1, 1, 11, 30, 0, 5000, tzinfo=<DstTzInfo 'Europe/London' LMT-1 day, 23:59:00 STD>)

In [9]: utc_date_object = localized_date_object.astimezone(pytz.utc)
In [10]: utc_date_object
Out[11]: datetime.datetime(2016, 1, 1, 11, 31, 0, 5000, tzinfo=<UTC>)

In [16]: paris = pytz.timezone("Europe/Paris")
In [17]: localized_date_object = datetime(2016, 1, 1, 11, 30, 0, 5000, paris)
In [18]: utc_date_object = localized_date_object.astimezone(pytz.utc)
In [19]: utc_date_object
Out[19]: datetime.datetime(2016, 1, 1, 11, 21, 0, 5000, tzinfo=<UTC>)

如您所见,它将增量应用于分钟而不是小时。
有人可以解释一下我在这里做错了什么。

【问题讨论】:

    标签: python datetime pytz


    【解决方案1】:

    在第 5 行,它显示了一个奇怪的输出 - &lt;DstTzInfo 'Europe/London' LMT-1 day, 23:59:00 STD&gt;,这似乎是一分钟的班次(减去 1 天 + 23:59:00 小时)。

    我建议您在 pytz 中尝试一些其他时区定义来查看它们的声明。

    【讨论】:

      【解决方案2】:

      欧洲/伦敦时区在 UTC 1 分钟之后。欧洲/巴黎时区比 UTC 早 9 分钟。伦敦和巴黎在地理上靠近格林威治,因此时区偏移很小。

      如果你尝试

      pytz.timezone("Asia/Shanghai")
      

      ,你会看到小时的变化。

      【讨论】:

      • 好吧,所以我没有找对地方,我正在寻找传统的时区转换,+1H,-1H,比如英国夏令时 (BST)。但是我将您的答案标记为正确;)
      【解决方案3】:

      我认为巴黎时间应该使用 CET,伦敦时间应该使用 UTC。 我使用了一些不同的方法,但它对我有用:

      from datetime import datetime
      from pytz import timezone
      
      ldo = datetime(2016, 1, 1, 11, 30, 0, 5000)
      ldo = ldo.replace(tzinfo=timezone('Europe/London'))
      
      udo = ldo.astimezone(timezone('UTC'))
      print ldo
      print udo
      
      ldo = datetime(2016, 1, 1, 11, 30, 0, 5000)
      ldo = ldo.replace(tzinfo=timezone('CET'))
      
      udo = ldo.astimezone(timezone('UTC'))
      print ldo
      print udo
      

      更新:

      当您存储时间值时,还应该存储相关的时区信息。 IMO 最佳做法是以 UTC 存储所有内容并转换为“用户”时区以供查看。顺便说一句,从 UTC 转换到欧洲/巴黎完美无缺,试试这个:

      winter = datetime(2016, 1, 1, 11, 30, 0, 5000, tzinfo=timezone("UTC"))
      paris =  winter.astimezone(timezone("Europe/Paris"))
      print paris
      # 2016-01-01 12:30:00.005000+01:00
      
      summer = datetime(2016, 6, 1, 11, 30, 0, 5000, tzinfo=timezone("UTC"))
      paris = summer.astimezone(timezone("Europe/Paris"))
      print paris
      # 2016-06-01 13:30:00.005000+02:00
      

      【讨论】:

      • 谢谢吉里。所以对于伦敦来说,冬天是UTC,夏天是BST。
      • 法国夏季的 CEST ;)
      • @Sebabouche 这不是为您的城市识别正确时区的问题;-) 当您在某处存储时间时,还应该存储相关的时区信息(CET 或 CEST)。 IMO 最佳做法是以 UTC 存储所有内容并转换为“用户”时区以供查看。顺便说一句,从 UTC 转换到欧洲/巴黎完美无缺,请参阅答案更新。
      【解决方案4】:

      pytz 文档说:

      该库仅支持两种构建本地化时间的方法。第一种是使用pytz库提供的localize()方法。这用于本地化一个简单的日期时间(没有时区信息的日期时间):

      构建本地化时间的第二种方法是使用标准 astimezone() 方法转换现有本地化时间:

      不幸的是,在许多时区使用标准日期时间构造函数的 tzinfo 参数“不起作用”。

      在提供的代码示例中,您尝试使用tzinfo 参数而不是localize()

      >>> london = pytz.timezone("Europe/London")
      
      >>> datetime.datetime(2016, 1, 1, 11, 30, 0, 5000, london) # This is incorrect
      datetime.datetime(2016, 1, 1, 11, 30, 0, 5000, tzinfo=<DstTzInfo 'Europe/London' LMT-1 day, 23:59:00 STD>)
      
      >>> london.localize(datetime.datetime(2016, 1, 1, 11, 30, 0, 5000)) # This is correct
      datetime.datetime(2016, 1, 1, 11, 30, 0, 5000, tzinfo=<DstTzInfo 'Europe/London' GMT0:00:00 STD>)
      

      【讨论】:

      • 是的。接受的答案并不能解决问题,但这个答案可以。
      【解决方案5】:

      根据当时商定的标准化,与 UTC 的偏移量通常有多个定义。

      当使用带有时区的 datatime 函数来构造日期时间时,使用哪种转换并不是很聪明,并且倾向于默认为旧的历史偏移量,在您的示例中,它是一分钟的偏移量。这样做是因为它会在考虑转换日期之前选择时区增量。

      这种替代方法解决了提供更可靠(现代标准)的结果:

      dt = mytz.localize(datetime(2020, 4, 7, 16, 30))

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-11-14
        • 1970-01-01
        • 1970-01-01
        • 2019-03-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-07-10
        相关资源
        最近更新 更多