我有一个使用datetime.utcnow()创建的python datetime实例,并持久化在数据库中。
为了显示,我想使用默认的本地时区将从数据库检索到的datetime实例转换为本地datetime(即,就像使用datetime.now()创建的datetime一样)。
如何将UTC日期时间转换为本地日期时间仅使用python标准库(例如,没有pytz依赖)?
一种解决方案似乎是使用datetime.astimezone(tz),但是如何获得默认的本地时区呢?
我有一个使用datetime.utcnow()创建的python datetime实例,并持久化在数据库中。
为了显示,我想使用默认的本地时区将从数据库检索到的datetime实例转换为本地datetime(即,就像使用datetime.now()创建的datetime一样)。
如何将UTC日期时间转换为本地日期时间仅使用python标准库(例如,没有pytz依赖)?
一种解决方案似乎是使用datetime.astimezone(tz),但是如何获得默认的本地时区呢?
当前回答
你不能用标准库来做。使用pytz模块,您可以将任何naive/aware datetime对象转换为任何其他时区。让我们看一些使用Python 3的例子。
通过类方法utcnow()创建的朴素对象
要将naive对象转换为任何其他时区,首先必须将其转换为感知datetime对象。可以使用replace方法将天真的datetime对象转换为可感知的datetime对象。然后可以使用astimezone方法将一个感知的datetime对象转换为任何其他时区。
变量pytz。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)
通过类方法now()创建的朴素对象
因为now方法返回当前日期和时间,所以您必须首先使datetime对象感知时区。localalize函数的作用是:将原始datetime对象转换为可感知时区的datetime对象。然后可以使用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)
其他回答
我发现的最简单的方法是得到你所处位置的时间偏移量,然后从小时中减去它。
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中,这对我来说是可行的。
使用timedelta在时区之间切换。您所需要的只是时区之间的小时偏移量。不必为datetime对象的所有6个元素设置边界。Timedelta也可以轻松处理闰年、闰世纪等。你必须首先
from datetime import datetime, timedelta
如果offset是时区的delta(以小时为单位):
超时 = 时间 + 时间增量(小时 = 偏移量)
其中timein和timeout是datetime对象。如。
时间 + 时间增量(小时 = -8)
从格林尼治标准时间转换为太平洋标准时间。
那么,如何确定偏移量呢?这里是一个简单的函数,前提是你只有一些转换的可能性,而不使用时区“感知”的datetime对象,而其他一些答案很好地做到了。有点手动,但有时清晰是最好的。
def change_timezone(timein, timezone, timezone_out):
'''
changes timezone between predefined timezone offsets to GMT
timein - datetime object
timezone - 'PST', 'PDT', 'GMT' (can add more as needed)
timezone_out - 'PST', 'PDT', 'GMT' (can add more as needed)
'''
# simple table lookup
tz_offset = {'PST': {'GMT': 8, 'PDT': 1, 'PST': 0}, \
'GMT': {'PST': -8, 'PDT': -7, 'GMT': 0}, \
'PDT': {'GMT': 7, 'PST': -1, 'PDT': 0}}
try:
offset = tz_offset[timezone][timezone_out]
except:
msg = 'Input timezone=' + timezone + ' OR output time zone=' + \
timezone_out + ' not recognized'
raise DateTimeError(msg)
return timein + timedelta(hours = offset)
在看了大量的答案和我能想到的最严格的代码之后(目前),似乎最好的是所有应用程序,其中时间是重要的,混合时区必须考虑在内,应该真正努力使所有datetime对象“感知”。那么,最简单的答案似乎是:
timeout = timein.astimezone(pytz.timezone("GMT"))
例如,转换为格林尼治时间。当然,要转换到或从您希望的任何其他时区(本地或其他时区),只需使用pytz理解的适当的时区字符串(来自pytz.all_timezones)。日光节约时间也被考虑在内。
你不能用标准库来做。使用pytz模块,您可以将任何naive/aware datetime对象转换为任何其他时区。让我们看一些使用Python 3的例子。
通过类方法utcnow()创建的朴素对象
要将naive对象转换为任何其他时区,首先必须将其转换为感知datetime对象。可以使用replace方法将天真的datetime对象转换为可感知的datetime对象。然后可以使用astimezone方法将一个感知的datetime对象转换为任何其他时区。
变量pytz。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)
通过类方法now()创建的朴素对象
因为now方法返回当前日期和时间,所以您必须首先使datetime对象感知时区。localalize函数的作用是:将原始datetime对象转换为可感知时区的datetime对象。然后可以使用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)
下面是另一种在datetime格式中更改时区的方法(我知道我在这上面浪费了精力,但我没有看到这个页面,所以我不知道怎么做),没有min.和sec.因为我的项目不需要它:
def change_time_zone(year, month, day, hour):
hour = hour + 7 #<-- difference
if hour >= 24:
difference = hour - 24
hour = difference
day += 1
long_months = [1, 3, 5, 7, 8, 10, 12]
short_months = [4, 6, 9, 11]
if month in short_months:
if day >= 30:
day = 1
month += 1
if month > 12:
year += 1
elif month in long_months:
if day >= 31:
day = 1
month += 1
if month > 12:
year += 1
elif month == 2:
if not year%4==0:
if day >= 29:
day = 1
month += 1
if month > 12:
year += 1
else:
if day >= 28:
day = 1
month += 1
if month > 12:
year += 1
return datetime(int(year), int(month), int(day), int(hour), 00)
在Python 2和3中工作的简单(但可能有缺陷)方法:
import time
import datetime
def utc_to_local(dt):
return dt - datetime.timedelta(seconds = time.timezone)
它的优点是写一个逆函数很简单