Python时区转换


76

我正在寻找一种快速输入时间的方式,然后将其转换为其他时区(可能多达10个不同的时区)

抱歉。我完全不熟悉python的时间,如果有人可以让我朝正确的方向前进,我将非常感激。


Python 3.9:zoneinfo
MrFuppes

Answers:


97

我发现最好的方法是将感兴趣的“时刻”转换为可识别utc-timezone的datetime对象(在python中,datetime对象不需要时区组件)。

然后,您可以使用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")

6
请注意,本地时间可能不明确,并且给定的字符串可能不对应于任何现有时间,例如由于DST转换。localize(is_dst=None)在这种情况下提供是否要引发例外。
jfs 2014年

52

使用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)

10
注意:它将在不同的时区中打印不同的时刻。OP在不同时区询问大约相同的时刻。
jfs 2014年

@jfs没有它不-我只是跑这个和它的打印2018-07-12 13:46:17 UTC+00002018-07-12 06:46:17 PDT-0700以及2018-07-12 15:46:17 CEST+0200,所有这些都代表同一时刻。
Mark Amery

@MarkAmery:尝试在fmt"%f")上添加微秒,以查看时间实例是否不同。
jfs

1
@jfs啊,我误会了你的评论!我以为您断言这些时刻代表的是时间上完全不同的时刻(即相隔数小时),而不仅仅是datetime.now(...)通话之间间隔了几微秒。
Mark Amery

17
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']

8

要将一个时区中的时间转换为Python中的另一个时区,可以使用datetime.astimezone()

time_in_new_timezone = time_in_old_timezone.astimezone(new_timezone)

给定aware_dtdatetime某个时区中的对象),将其转换为其他时区并以给定的时间格式打印时间:

#!/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=Falseis_dst=True。在Python上查看具有更多详细信息的链接:如何将日期时间/时间戳从一个时区转换为另一个时区?



5

请注意:答案的第一部分是摆锤的版本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]>)

答案列出了可能与钟摆一起使用的时区的名称。(它们与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')))

AttributeError:“函数”对象没有属性“ strptime”
赛斯·康奈尔

1
Pendulum很棒,但是请记住,输出可能与下一步要执行的操作(例如Pandas数据帧)不兼容。
Turanga19年

4

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  

有一个backport允许在Python 3.6至3.8中使用

sudo pip install backports.zoneinfo

然后:

from backports.zoneinfo import ZoneInfo

3

时间转换

要将一个时区中的时间转换为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)

2

对于Python 3.2+,simple-date是pytz的包装,它试图简化事情。

如果你有一time

SimpleDate(time).convert(tz="...")

可以做你想要的。但是时区是相当复杂的事情,因此时区会变得更加复杂-请参阅文档


0
# 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()) 

2
嗨,欢迎来到Stack Overflow!请阅读“如何回答”,并始终记住,您不仅要回答该操作规范,而且还要回答此问题的任何未来读者,尤其是考虑到该问题已经有8年历史了。请编辑您的帖子,以包含有关为何可行的解释。
阿德里亚

@Sahil Soni-请提供正确说明和解释的答案
Saikat Saha
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.