将python UTCdate时间转换为只使用python标准库的本地date时间?

我有一个使用datetime.utcnow()创build并保存在数据库中的python datetime实例。

为了显示,我想使用默认的本地时区将date时间实例从数据库中检索到本地date时间(即,如果date时间是使用datetime.now()创build的)。

如何将UTCdate时间转换为本地date时间只使用Python标准库(例如,无pytz依赖)?

看来有一个解决scheme是使用datetime.astimezone(tz),但是如何获得默认的本地时区?

在Python 3.3+中:

from datetime import timezone def utc_to_local(utc_dt): return utc_dt.replace(tzinfo=timezone.utc).astimezone(tz=None) 

在Python 2/3:

 import calendar from datetime import datetime, timedelta def utc_to_local(utc_dt): # get integer timestamp to avoid precision lost timestamp = calendar.timegm(utc_dt.timetuple()) local_dt = datetime.fromtimestamp(timestamp) assert utc_dt.resolution >= timedelta(microseconds=1) return local_dt.replace(microsecond=utc_dt.microsecond) 

使用pytz (Python 2/3):

 import pytz local_tz = pytz.timezone('Europe/Moscow') # use your local timezone name here # NOTE: pytz.reference.LocalTimezone() would produce wrong result here ## You could use `tzlocal` module to get local timezone on Unix and Win32 # from tzlocal import get_localzone # $ pip install tzlocal # # get local timezone # local_tz = get_localzone() def utc_to_local(utc_dt): local_dt = utc_dt.replace(tzinfo=pytz.utc).astimezone(local_tz) return local_tz.normalize(local_dt) # .normalize might be unnecessary 

 def aslocaltimestr(utc_dt): return utc_to_local(utc_dt).strftime('%Y-%m-%d %H:%M:%S.%f %Z%z') print(aslocaltimestr(datetime(2010, 6, 6, 17, 29, 7, 730000))) print(aslocaltimestr(datetime(2010, 12, 6, 17, 29, 7, 730000))) print(aslocaltimestr(datetime.utcnow())) 

产量

Python 3.3

 2010-06-06 21:29:07.730000 MSD+0400 2010-12-06 20:29:07.730000 MSK+0300 2012-11-08 14:19:50.093745 MSK+0400 

Python 2

 2010-06-06 21:29:07.730000 2010-12-06 20:29:07.730000 2012-11-08 14:19:50.093911 

pytz

 2010-06-06 21:29:07.730000 MSD+0400 2010-12-06 20:29:07.730000 MSK+0300 2012-11-08 14:19:50.146917 MSK+0400 

注意:它考虑了DST和MSK时区的utc偏移量的最近更改。

我不知道非pytz解决scheme是否在Windows上工作。

由于标准库没有任何时区,因此只能使用标准库。 你需要pytz或dateutil 。

 >>> from datetime import datetime >>> now = datetime.utcnow() >>> from dateutil import tz >>> HERE = tz.tzlocal() >>> UTC = tz.gettz('UTC') The Conversion: >>> gmt = now.replace(tzinfo=UTC) >>> gmt.astimezone(HERE) datetime.datetime(2010, 12, 30, 15, 51, 22, 114668, tzinfo=tzlocal()) 

或者,你可以通过实现你自己的时区,而不用pytz或dateutil。 但是,这将是愚蠢的。

我想我计算出来:计算自时代以来的秒数,然后使用time.localtime转换为本地timzeone,然后将时间结构转换回date时间…

 EPOCH_DATETIME = datetime.datetime(1970,1,1) SECONDS_PER_DAY = 24*60*60 def utc_to_local_datetime( utc_datetime ): delta = utc_datetime - EPOCH_DATETIME utc_epoch = SECONDS_PER_DAY * delta.days + delta.seconds time_struct = time.localtime( utc_epoch ) dt_args = time_struct[:6] + (delta.microseconds,) return datetime.datetime( *dt_args ) 

它正确地应用夏天/冬天DST:

 >>> utc_to_local_datetime( datetime.datetime(2010, 6, 6, 17, 29, 7, 730000) ) datetime.datetime(2010, 6, 6, 19, 29, 7, 730000) >>> utc_to_local_datetime( datetime.datetime(2010, 12, 6, 17, 29, 7, 730000) ) datetime.datetime(2010, 12, 6, 18, 29, 7, 730000) 

标准的Python库没有任何tzinfo实现。 我一直认为这是datetime模块的一个令人惊讶的缺点。

tzinfo类的文档确实带有一些有用的例子。 在部分末尾查找大码块。

你不能用标准库来做。 使用pytz模块,您可以将任何天真/感知date时间对象转换为任何其他时区。 让我们看看一些使用Python 3的例子。

通过类方法utcnow()创build的天真对象

要将一个天真的对象转换为任何其他时区,首先必须将其转换为有意识的date时间对象。 您可以使用replace方法将朴素的date时间对象转换为知名的date时间对象。 然后将一个知晓的date时间对象转换为任何其他的时区,你可以使用astimezone方法。

variablespytz.all_timezones给出了pytz模块中所有可用时区的列表。

 import datetime,pytz dtobj1=datetime.datetime.utcnow() #utcnow class method print(dtobj1) dtobj3=dtobj1.replace(tzinfo=pytz.UTC) #replace method dtobj_hongkong=dtobj3.astimezone(pytz.timezone("Asia/Hong_Kong")) #astimezone method print(dtobj_hongkong) 

通过类方法创build的朴素对象now()

因为now方法返回当前date和时间,所以你必须首先使date时间对象时区感知。 localize函数将一个天真的date时间对象转换为一个可识别时区的date时间对象。 然后,您可以使用astimezone方法将其转换为另一个时区。

 dtobj2=datetime.datetime.now() mytimezone=pytz.timezone("Europe/Vienna") #my current timezone dtobj4=mytimezone.localize(dtobj2) #localize function dtobj_hongkong=dtobj4.astimezone(pytz.timezone("Asia/Hong_Kong")) #astimezone method print(dtobj_hongkong) 

这个答案显示了使用pytz的简单方法。

在Python 2和Python 3中工作的一个简单(但也许是有缺陷的)方式:

 import time import datetime def utc_to_local(dt): return dt - datetime.timedelta(seconds = time.timezone) 

它的优点是写一个反函数是微不足道的

我发现的最简单的方法是获得在哪里的时间偏移,然后从小时中减去。

 def format_time(ts,offset): if not ts.hour >= offset: ts = ts.replace(day=ts.day-1) ts = ts.replace(hour=ts.hour-offset) else: ts = ts.replace(hour=ts.hour-offset) return ts 

这适用于我,在Python 3.5.2。