How to add timezone into a naive datetime instance in python
我有一个没有时区信息的datetime。我现在正在获取时区信息,并希望将时区添加到现有的日期时间实例中,我该怎么做?
1 2
| d = datetime.datetime.now()
tz = pytz.timezone('Asia/Taipei') |
如何将时区信息tz添加到datetime a中
使用tz.localize(d)将实例本地化。从文档中:
The first is to use the localize() method provided by the pytz library. This is used to localize a naive datetime (datetime with no timezone information):
1 2 3
| >>> loc_dt = eastern.localize(datetime(2002, 10, 27, 6, 0, 0))
>>> print(loc_dt.strftime(fmt))
2002-10-27 06:00:00 EST-0500 |
如果不使用tz.localize(),而使用datetime.replace(),则可能使用历史偏移量;tz.localize()将选择给定日期生效的正确偏移量。例如,美国东部时区DST的开始和结束日期随时间而变化。
当您试图本地化日期时间值时,如果该值不明确,因为它跨越了从夏季到冬季的过渡期,或者反之亦然,则将查询时区,以查看生成的日期时间对象是否应使.dst()返回true或false。您可以使用.localize()的is_dst关键字参数覆盖时区的默认值:
1
| dt = tz.localize(naive, is_dst=True) |
甚至可以通过设置is_dst=None完全关闭选择。在这种情况下,或者在极少数情况下,没有为时区设置默认值,不明确的日期时间值将导致引发AmbiguousTimeError异常。仅为不明确的日期时间值咨询is_dst标志,否则将忽略这些值。
要返回到另一个方向,请将时区感知对象返回到原始对象,使用.replace(tzinfo=None):
1
| naivedt = awaredt.replace(tzinfo=None) |
- 完美的解决方案,谢谢。
- 有没有什么方便的方法可以从有TZINFO的datetime中得到幼稚的datetime?
- @waitingkuo:在datetime对象上调用.replace(tzinfo=None)。返回值是一个幼稚的datetime实例。
- 它起作用了,谢谢!
- is_dst参数值得一提,它可以解决不明确的时间,或者断言当时没有DST转换。
- @J.F.Sebastian:在这里,在is_dst上增加了一小段。
- 此外,local_dt = tz.localize(dt)可能会产生一个不存在的时间(在"向前冲刺"DST转换期间)。要修复它,请致电local_dt = tz.normalize(local_dt)。或者使用is_dst=None防止tz.localize()返回模糊或不存在的时间。
- 除格林尼治标准时间/UTC外,其他时区的pytz.timezone.localize(datetime.time, pyzt)将失败(pytz.timezone.tzinfo.timedelta不是零)。localize方法对datetimes很有用,但对times却不管用(因为它可能要绕到新的一天)。对于time,只需使用new_time = old_time.replace(tzinfo=pytz.timezone(timezone_name))。这不会调整时间来解释新时区,只是假设它已经在本地时间"测量"。顺便说一下,如果您不想"移位"日期时间,那么它也可以用于日期时间。
- @霍布斯:我不希望本地化为time对象工作,不,因为本地化需要一个日期来正确地完成它的工作。时区偏移对于一个时间组件没有意义,您缺少DST和历史上下文的信息。
- @马丁·皮耶特就是这样。但是,如果您需要TZ感知时间(这只对同一时区的其他感知时间有用),您可以使用.replace()。我同意这通常是不合理的…但是,如果您通知time一个时区,TZ可以在以后形成日期时间时使用。
- @霍布斯:将.replace()与pytz时区一起使用是错误的,该时区可能有多个UTC偏移(许多时区都有)。默认的Tzinfo对象通常对应于lmt(太阳时间),在大多数情况下这不是您想要的(我认为默认背后的原因是帮助揭示错误的.replace()用法)。
- @J.F.塞巴斯蒂安认为这是"错误的"。但对于我这种情况下的某个人来说可能是可以的(在datetime.time个实例中,还没有日期信息)。这发生在我处理wunderground.com的csv时。TZ信息在列标题中可用(有时在字段字符串中),但日期在其他地方可用。所以我只是用TZINFO标记时间,然后使用该TZINFO将日期本地化。我相信这是错误的,一个黑客,但它对我有用。对我错误的回答投反对票,希望能鼓励其他人认真考虑如何妥善解决这个边缘问题。
- @霍布斯:为什么不把时区和时间分开存储,当你把它和日期结合起来,然后应用时区呢?
- @MartjinPieters同意,从时区准确性/混淆/模糊性的角度来看,这可能更安全,但增加了复杂性,并可能引入簿记(索引)错误…我更喜欢为每个csv"cell"创建一个对象,并在周围传递对象列表,而不是2个对象元组列表。
如果您知道您的原始日期时间是在您试图添加的时区中"测量"的,那么您可以(但可能不应该)使用replace,而不是localize。
1 2 3
| # d = datetime.datetime.now()
# tz = pytz.timezone('Asia/Taipei')
d = d.replace(tzinfo=tz) |
我可以想象两次这可能有意义(第二次发生在我身上):
您的服务器区域设置为不正确的时区,您正试图通过使datetime实例意识到这个不正确的时区来更正它(并可能在以后将其本地化为"正确"时区,以便now()的值与您将其与(可能是您的手表)进行比较的其他时间相匹配)。
您希望用时区(TZINFO)属性"标记"一个time实例(不是datetime),以便该属性以后可以用于形成完整的datetime实例。