具体来说,给定我的服务器的时区(系统时间角度)和时区输入,我如何计算系统时间,就好像它处于新时区一样(无论夏令时等)?
import datetime
current_time = datetime.datetime.now() #system time
server_timezone = "US/Eastern"
new_timezone = "US/Pacific"
current_time_in_new_timezone = ???
如果您知道您的原始时区和要将其转换到的新时区,结果非常简单:
创建两个
pytz.timezone
对象,一个用于当前时区,一个用于新时区,例如pytz.timezone("US/Pacific")
。您可以在 pytz
库中找到所有官方时区的列表:import pytz; pytz.all_timezones
将感兴趣的日期时间/时间戳本地化为当前时区,例如
current_timezone = pytz.timezone("US/Eastern")
localized_timestamp = current_timezone.localize(timestamp)
.astimezone()
转换为新时区,并使用所需时区的 pytz 对象作为输入,例如localized_timestamp.astimezone(new_timezone)
。完成!
作为一个完整的例子:
import datetime
import pytz
# a timestamp I'd like to convert
my_timestamp = datetime.datetime.now()
# create both timezone objects
old_timezone = pytz.timezone("US/Eastern")
new_timezone = pytz.timezone("US/Pacific")
# two-step process
localized_timestamp = old_timezone.localize(my_timestamp)
new_timezone_timestamp = localized_timestamp.astimezone(new_timezone)
# or alternatively, as an one-liner
new_timezone_timestamp = old_timezone.localize(my_timestamp).astimezone(new_timezone)
奖励:但如果您需要的只是特定时区的当前时间,您可以方便地将该时区直接传递到 datetime.now() 以直接获取当前时间:
datetime.datetime.now(new_timezone)
当涉及到一般需要时区转换时,我强烈建议您应该以 UTC 格式存储数据库中的所有时间戳,因为它没有夏令时 (DST) 转换。作为一种良好的做法,人们应该始终选择启用时区支持(即使您的用户都位于同一个时区!)。这将帮助您避免当今困扰众多软件的 DST 转换问题。
除了夏令时之外,软件中的时间通常非常棘手。为了了解在一般软件中处理时间有多么困难,这里有一个可能具有启发性的资源:http://yourcalendricalfallacyis.com
即使将日期时间/时间戳转换为日期这样看似简单的操作也可能变得不明显。正如这个有用的文档指出的:
日期时间代表时间点。这是绝对的:它不依赖于任何东西。相反,日期是一个“日历概念”。这是一段时间,其范围取决于考虑日期的时区。正如您所看到的,这两个概念本质上是不同的。
了解这种差异是避免基于时间的错误的关键一步。祝你好运。
。不再需要 pytz(已弃用;-> pytz 弃用垫片)。 例如:
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))
这给了你例子
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'))
有两个步骤:
,例如,获取给定时区的当前系统时间:
#!/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)
即使在不明确的时间
也能工作,例如,在夏令时转换期间,而
server_timezone.localize(datetime.now())
可能会失败(50%的机会)。如果您确定您的输入时间存在于服务器的时区中并且是唯一的,那么您可以通过
is_dst=None
来断言:
server_time = server_timezone.localize(naive_time, is_dst=None)
它会引发无效时间的异常。如果可以忽略最多
一天
错误(尽管通常由于夏令时而导致的错误大约是一个小时),那么您可以删除is_dst
参数:
server_time = server_timezone.normalize(server_timezone.localize(naive_time))
调用 .normalize()
来调整不存在的时间(间隙中的本地时间,在“向前弹簧”转换期间)。如果时区规则没有改变;您的服务器不应生成不存在的时间。请参阅
“我可以始终设置 is_dst=True 吗?”
tz
:
tz = pytz.timezone("US/Pacific")
server_time_in_new_timezone = server_time.astimezone(tz)
from datetime import datetime
from zoneinfo import ZoneInfo
from_timezone = ZoneInfo('Europe/Moscow') # UTC-3
to_timezone = ZoneInfo('Asia/Tbilisi') # UTC-4
dt = datetime.fromtimestamp(timestamp, to_timezone)
result_timestamp = int(dt.replace(tzinfo=from_timezone).timestamp())
例如,如果您采用时间戳 = 529635600(莫斯科 1986-14-10 04:00:00)并运行此代码,您将得到 result_timestamp = 529639200(第比利斯 1986-14-10 05:00:00)。
从 python 3.9 开始,代码可以简化:
from datetime import datetime
from zoneinfo import ZoneInfo
current_time = datetime.datetime.now() #system time
# server_timezone = "US/Eastern"
new_timezone = ZoneInfo("US/Pacific")
current_time_in_new_timezone = new_timezone.fromutc(current_time.astimezone(new_timezone))
就我个人的观点而言,在 python 中使用本地日期时间仍然相当模糊,但比前段时间好多了。