Python:如何将日期时间/时间戳从一个时区转换为另一个时区?

kfa*_*fan 18 python timezone datetime pytz timedelta

具体来说,考虑到我的服务器的时区(系统时间透视图)和时区输入,如何计算系统时间,就像它在新时区(无论夏令时等)一样?

import datetime
current_time = datetime.datetime.now() #system time

server_timezone = "US/Eastern"
new_timezone = "US/Pacific"

current_time_in_new_timezone = ???
Run Code Online (Sandbox Code Playgroud)

MrF*_*pes 30

在 Python 3.9 中,标准库拥有您所需的一切:zoneinfo。不再需要 pytz (已弃用;-> pytz 弃用 shim)。

前任:

from datetime import datetime
from zoneinfo import ZoneInfo

server_timezone = "US/Eastern"
new_timezone = "US/Pacific"

current_time = datetime.now(ZoneInfo(server_timezone)) 

# current_time_in_new_timezone = ???
current_time_in_new_timezone = current_time.astimezone(ZoneInfo(new_timezone))
Run Code Online (Sandbox Code Playgroud)

例如,这给了你

print(current_time.isoformat(timespec='seconds'))
# 2021-10-04T02:42:54-04:00

print(repr(current_time))
# datetime.datetime(2021, 10, 4, 2, 42, 54, 40600, tzinfo=zoneinfo.ZoneInfo(key='US/Eastern'))

print(current_time_in_new_timezone.isoformat(timespec='seconds'))
# 2021-10-03T23:42:54-07:00

print(repr(current_time_in_new_timezone))
# datetime.datetime(2021, 10, 3, 23, 42, 54, 40600, tzinfo=zoneinfo.ZoneInfo(key='US/Pacific'))
Run Code Online (Sandbox Code Playgroud)

  • 对于使用 python <3.9 的任何人,您可以安装 zoneinfo 的向后移植 https://pypi.org/project/backports.zoneinfo/ (2认同)

kfa*_*fan 27

如果您知道要将其转换为原始时区和新时区,请先使用它pytz.localize来处理任何本地化(例如夏令时等),然后使用pytz.timezone创建时区对象,最后datetime.astimezone(timezone)用于简单计算.例如:

import datetime
import pytz # new import

my_timestamp = datetime.datetime.now() # some timestamp
old_timezone = pytz.timezone("US/Eastern")
new_timezone = pytz.timezone("US/Pacific")

# returns datetime in the new timezone
my_timestamp_in_new_timezone = old_timezone.localize(my_timestamp).astimezone(new_timezone) 
Run Code Online (Sandbox Code Playgroud)

当然,如果您想要的只是特定时区的当前时间,您可以将该时区直接传递到datetime.now()以获取时间戳.像这样:

datetime.datetime.now(new_timezone)
Run Code Online (Sandbox Code Playgroud)

尽管如此,我强烈建议将所有时间戳以UTC格式存储为系统标准,并避免整个DST问题.有关此内容,请参阅:http://lucumr.pocoo.org/2011/7/15/eppur-si-muove/

并且要知道处理时间计算有多么困难:http://yourcalendricalfallacyis.com

  • 由于这个问题/答案是最佳结果,我想通知您不再推荐“pytz”。请参阅:https://blog.ganssle.io/articles/2018/03/pytz-fastest-footgun.html 和 https://talkpython.fm/episodes/show/271/unlock-the-mysteries-of-time- python 日期时间即 (2认同)

jfs*_*jfs 8

如何将日期时间/时间戳从一个时区转换为另一个时区?

有两个步骤:

  1. 从系统时间和时区创建一个感知日期时间对象,例如,获取给定时区中的当前系统时间:

    #!/usr/bin/env python
    from datetime import datetime
    import pytz
    
    server_timezone = pytz.timezone("US/Eastern")
    server_time = datetime.now(server_timezone) # you could pass *tz* directly
    
    Run Code Online (Sandbox Code Playgroud)

    注意:datetime.now(server_timezone)即使在不明确的时间也能工作,例如在 DST 转换期间,但server_timezone.localize(datetime.now())可能会失败(50% 的几率)。

    如果您确定您的输入时间存在于服务器的时区中并且它是唯一的,那么您可以通过is_dst=None断言:

    server_time = server_timezone.localize(naive_time, is_dst=None)
    
    Run Code Online (Sandbox Code Playgroud)

    它引发无效时间的异常。
    如果可以忽略最多一天的错误(尽管通常由于 DST 导致的错误大约是一个小时),那么您可以删除is_dst参数:

    server_time = server_timezone.normalize(server_timezone.localize(naive_time))
    
    Run Code Online (Sandbox Code Playgroud)

    .normalize()被调用来调整不存在的时间(间隙中的本地时间,在“spring forward”转换期间)。如果时区规则没有改变;您的服务器不应生成不存在的时间。请参阅“我可以始终设置 is_dst=True 吗?”

  2. 将感知日期时间对象转换为目标时区tz

    tz = pytz.timezone("US/Pacific")
    server_time_in_new_timezone = server_time.astimezone(tz)
    
    Run Code Online (Sandbox Code Playgroud)