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

Python: How do you convert datetime/timestamp from one timezone to another timezone?

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

1
2
3
4
5
6
7
import datetime
current_time = datetime.datetime.now() #system time

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

current_time_in_new_timezone = ???


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

1
2
3
4
5
6
7
8
9
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)

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

1
datetime.datetime.now(new_timezone)

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

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


How do you convert datetime/timestamp from one timezone to another timezone?

有两个步骤:

  • 从系统时间和时区创建一个有意识的日期时间对象,例如,获取给定时区的当前系统时间:

    1
    2
    3
    4
    5
    6
    #!/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

    注意:datetime.now(server_timezone)即使在模糊时间内也可以工作,例如,在DST过渡期间,server_timezone.localize(datetime.now())可能会失败(50%几率)。

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

    1
    server_time = server_timezone.localize(naive_time, is_dst=None)

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

    1
    server_time = server_timezone.normalize(server_timezone.localize(naive_time))

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

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

    1
    2
    tz = pytz.timezone("US/Pacific")
    server_time_in_new_timezone = server_time.astimezone(tz)