Python 时区转换
- 2025-01-17 09:23:00
- admin 原创
- 74
问题描述:
如何在 Python 中将时间转换为另一个时区?
解决方案 1:
我发现最好的方法是将感兴趣的“时刻”转换为可感知 utc 时区的日期时间对象(在 python 中,日期时间对象不需要时区组件)。
然后您可以使用astimezone转换为感兴趣的时区(参考)。
from datetime import datetime
import pytz
utcmoment_naive = datetime.utcnow()
utcmoment = utcmoment_naive.replace(tzinfo=pytz.utc)
# print "utcmoment_naive: {0}".format(utcmoment_naive) # python 2
print("utcmoment_naive: {0}".format(utcmoment_naive))
print("utcmoment: {0}".format(utcmoment))
localFormat = "%Y-%m-%d %H:%M:%S"
timezones = ['America/Los_Angeles', 'Europe/Madrid', 'America/Puerto_Rico']
for tz in timezones:
localDatetime = utcmoment.astimezone(pytz.timezone(tz))
print(localDatetime.strftime(localFormat))
# utcmoment_naive: 2017-05-11 17:43:30.802644
# utcmoment: 2017-05-11 17:43:30.802644+00:00
# 2017-05-11 10:43:30
# 2017-05-11 19:43:30
# 2017-05-11 13:43:30
因此,对于当地时区中感兴趣的时刻(存在的时间),您可以像这样将其转换为 utc(参考)。
localmoment_naive = datetime.strptime('2013-09-06 14:05:10', localFormat)
localtimezone = pytz.timezone('Australia/Adelaide')
try:
localmoment = localtimezone.localize(localmoment_naive, is_dst=None)
print("Time exists")
utcmoment = localmoment.astimezone(pytz.utc)
except pytz.exceptions.NonExistentTimeError as e:
print("NonExistentTimeError")
解决方案 2:
Python 3.9 添加了zoneinfo
模块,因此现在只需要标准库!
>>> from zoneinfo import ZoneInfo
>>> from datetime import datetime
>>> d = datetime(2020, 10, 31, 12, tzinfo=ZoneInfo('America/Los_Angeles'))
>>> d.astimezone(ZoneInfo('Europe/Berlin')) # 12:00 in Cali will be 20:00 in Berlin
datetime.datetime(2020, 10, 31, 20, 0, tzinfo=zoneinfo.ZoneInfo(key='Europe/Berlin'))
维基百科可用时区列表
某些函数(例如now()
和 )utcnow()
会返回不了解时区的日期时间,这意味着它们不包含时区信息。我建议仅使用关键字 向它们请求了解时区的值tz=ZoneInfo('localtime')
。
如果astimezone
获取不了解时区的输入,它会假定它是本地时间,这可能导致错误:
>>> datetime.utcnow() # UTC -- NOT timezone-aware!!
datetime.datetime(2020, 6, 1, 22, 39, 57, 376479)
>>> datetime.now() # Local time -- NOT timezone-aware!!
datetime.datetime(2020, 6, 2, 0, 39, 57, 376675)
>>> datetime.now(tz=ZoneInfo('localtime')) # timezone-aware
datetime.datetime(2020, 6, 2, 0, 39, 57, 376806, tzinfo=zoneinfo.ZoneInfo(key='localtime'))
>>> datetime.now(tz=ZoneInfo('Europe/Berlin')) # timezone-aware
datetime.datetime(2020, 6, 2, 0, 39, 57, 376937, tzinfo=zoneinfo.ZoneInfo(key='Europe/Berlin'))
>>> datetime.utcnow().astimezone(ZoneInfo('Europe/Berlin')) # WRONG!!
datetime.datetime(2020, 6, 1, 22, 39, 57, 377562, tzinfo=zoneinfo.ZoneInfo(key='Europe/Berlin'))
Windows 没有系统时区数据库,所以这里需要一个额外的包:
pip install tzdata
有一个反向移植允许在Python 3.6 到 3.8中使用:
sudo pip install backports.zoneinfo
然后:
from backports.zoneinfo import ZoneInfo
解决方案 3:
使用pytz
from datetime import datetime
from pytz import timezone
fmt = "%Y-%m-%d %H:%M:%S %Z%z"
timezonelist = ['UTC','US/Pacific','Europe/Berlin']
for zone in timezonelist:
now_time = datetime.now(timezone(zone))
print now_time.strftime(fmt)
解决方案 4:
import datetime
import pytz
def convert_datetime_timezone(dt, tz1, tz2):
tz1 = pytz.timezone(tz1)
tz2 = pytz.timezone(tz2)
dt = datetime.datetime.strptime(dt,"%Y-%m-%d %H:%M:%S")
dt = tz1.localize(dt)
dt = dt.astimezone(tz2)
dt = dt.strftime("%Y-%m-%d %H:%M:%S")
return dt
-
dt
:日期时间字符串tz1
:初始时区tz2
:目标时区
-
> convert_datetime_timezone("2017-05-13 14:56:32", "Europe/Berlin", "PST8PDT")
'2017-05-13 05:56:32'
> convert_datetime_timezone("2017-05-13 14:56:32", "Europe/Berlin", "UTC")
'2017-05-13 12:56:32'
-
> pytz.all_timezones[0:10]
['Africa/Abidjan',
'Africa/Accra',
'Africa/Addis_Ababa',
'Africa/Algiers',
'Africa/Asmara',
'Africa/Asmera',
'Africa/Bamako',
'Africa/Bangui',
'Africa/Banjul',
'Africa/Bissau']
解决方案 5:
时间转换
要在 Python 中将一个时区的时间转换为另一个时区,可以使用datetime.astimezone():
因此,下面的代码将本地时间转换为其他时区。
datetime.datetime.today() - 返回当前当地时间
datetime.astimezone() - 转换时区,但我们必须传递时区。
pytz.timezone('Asia/Kolkata') - 将时区传递给 pytz 模块
Strftime——将日期时间转换为字符串
# Time conversion from local time
import datetime
import pytz
dt_today = datetime.datetime.today() # Local time
dt_India = dt_today.astimezone(pytz.timezone('Asia/Kolkata'))
dt_London = dt_today.astimezone(pytz.timezone('Europe/London'))
India = (dt_India.strftime('%m/%d/%Y %H:%M'))
London = (dt_London.strftime('%m/%d/%Y %H:%M'))
print("Indian standard time: "+India+" IST")
print("British Summer Time: "+London+" BST")
列出所有时区
import pytz
for tz in pytz.all_timezones:
print(tz)
解决方案 6:
要在 Python 中将一个时区的时间转换为另一个时区,可以使用datetime.astimezone()
:
time_in_new_timezone = time_in_old_timezone.astimezone(new_timezone)
给定aware_dt
(datetime
某个时区的对象),将其转换为其他时区并以给定的时间格式打印时间:
#!/usr/bin/env python3
import pytz # $ pip install pytz
time_format = "%Y-%m-%d %H:%M:%S%z"
tzids = ['Asia/Shanghai', 'Europe/London', 'America/New_York']
for tz in map(pytz.timezone, tzids):
time_in_tz = aware_dt.astimezone(tz)
print(f"{time_in_tz:{time_format}}")
如果f""
语法不可用,你可以将其替换为"".format(**vars())
您可以在其中设置aware_dt
当地时区的当前时间:
from datetime import datetime
import tzlocal # $ pip install tzlocal
local_timezone = tzlocal.get_localzone()
aware_dt = datetime.now(local_timezone) # the current time
或者从当地时区的输入时间字符串:
naive_dt = datetime.strptime(time_string, time_format)
aware_dt = local_timezone.localize(naive_dt, is_dst=None)
其中time_string
可能看起来像:'2016-11-19 02:21:42'
。它对应于time_format = '%Y-%m-%d %H:%M:%S'
。
is_dst=None
如果输入的时间字符串对应于不存在或不明确的本地时间(例如在 DST 转换期间),则强制异常。您也可以传递is_dst=False
, is_dst=True
。请参阅 Python 中的更多详细信息链接:如何将日期时间/时间戳从一个时区转换为另一个时区?
解决方案 7:
对于 Python 时区转换,我使用了Taavi Burns在 PyCon 2012演示文稿中提供的便捷表格。
解决方案 8:
请注意:此答案的第一部分是钟摆的 1.x 版本。请参阅下文了解 2.x 版本的答案。
我希望我还不算太晚!
钟摆库擅长此项和其他日期时间计算。
>>> import pendulum
>>> some_time_zones = ['Europe/Paris', 'Europe/Moscow', 'America/Toronto', 'UTC', 'Canada/Pacific', 'Asia/Macao']
>>> heres_a_time = '1996-03-25 12:03 -0400'
>>> pendulum_time = pendulum.datetime.strptime(heres_a_time, '%Y-%m-%d %H:%M %z')
>>> for tz in some_time_zones:
... tz, pendulum_time.astimezone(tz)
...
('Europe/Paris', <Pendulum [1996-03-25T17:03:00+01:00]>)
('Europe/Moscow', <Pendulum [1996-03-25T19:03:00+03:00]>)
('America/Toronto', <Pendulum [1996-03-25T11:03:00-05:00]>)
('UTC', <Pendulum [1996-03-25T16:03:00+00:00]>)
('Canada/Pacific', <Pendulum [1996-03-25T08:03:00-08:00]>)
('Asia/Macao', <Pendulum [1996-03-26T00:03:00+08:00]>)
答案列出了可以与 pendulum 一起使用的时区名称。 (它们与 pytz 相同。)
对于版本 2:
some_time_zones
是程序中可能使用的时区名称列表heres_a_time
是一个示例时间,带有“-0400”形式的时区我首先将时间转换为钟摆时间,以便进行后续处理
现在我可以显示每个时区的时间
show_time_zones
...
>>> import pendulum
>>> some_time_zones = ['Europe/Paris', 'Europe/Moscow', 'America/Toronto', 'UTC', 'Canada/Pacific', 'Asia/Macao']
>>> heres_a_time = '1996-03-25 12:03 -0400'
>>> pendulum_time = pendulum.from_format('1996-03-25 12:03 -0400', 'YYYY-MM-DD hh:mm ZZ')
>>> for tz in some_time_zones:
... tz, pendulum_time.in_tz(tz)
...
('Europe/Paris', DateTime(1996, 3, 25, 17, 3, 0, tzinfo=Timezone('Europe/Paris')))
('Europe/Moscow', DateTime(1996, 3, 25, 19, 3, 0, tzinfo=Timezone('Europe/Moscow')))
('America/Toronto', DateTime(1996, 3, 25, 11, 3, 0, tzinfo=Timezone('America/Toronto')))
('UTC', DateTime(1996, 3, 25, 16, 3, 0, tzinfo=Timezone('UTC')))
('Canada/Pacific', DateTime(1996, 3, 25, 8, 3, 0, tzinfo=Timezone('Canada/Pacific')))
('Asia/Macao', DateTime(1996, 3, 26, 0, 3, 0, tzinfo=Timezone('Asia/Macao')))
解决方案 9:
对于 Python 3.2+,simple-date是 pytz 的包装器,它试图简化事情。
如果你有time
那么
SimpleDate(time).convert(tz="...")
可以做你想做的事。但是时区是相当复杂的事情,所以它可能会变得更加复杂 - 请参阅文档。
解决方案 10:
# Program
import time
import os
os.environ['TZ'] = 'US/Eastern'
time.tzset()
print('US/Eastern in string form:',time.asctime())
os.environ['TZ'] = 'Australia/Melbourne'
time.tzset()
print('Australia/Melbourne in string form:',time.asctime())
os.environ['TZ'] = 'Asia/Kolkata'
time.tzset()
print('Asia/Kolkata in string form:',time.asctime())