我有一个使用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),但是如何获得默认的本地时区呢?
当前回答
针对特定情况: 输入utc datetime字符串。//通常来自日志 输出区域日期时间字符串。
def utc_to_locale(utc_str):
# from utc to locale
d1=datetime.fromisoformat(utc_str+'-00:00')
return d1.astimezone().strftime('%F %T.%f')[:-3]
测试:
>>> utc_to_locale('2022-02-14 00:49:06')
'2022-02-14 08:49:06.000'
>>> utc_to_locale('2022-02-14 00:49:06.123')
'2022-02-14 08:49:06.123'
>>> utc_to_locale('2022-02-14T00:49:06.123')
'2022-02-14 08:49:06.123'
其他回答
使用时间。timezone,它给出一个“UTC以西秒数”的整数。
例如:
from datetime import datetime, timedelta, timezone
import time
# make datetime from timestamp, thus no timezone info is attached
now = datetime.fromtimestamp(time.time())
# make local timezone with time.timezone
local_tz = timezone(timedelta(seconds=-time.timezone))
# attach different timezones as you wish
utc_time = now.astimezone(timezone.utc)
local_time = now.astimezone(local_tz)
print(utc_time.isoformat(timespec='seconds'))
print(local_time.isoformat(timespec='seconds'))
在我的PC上(Python 3.7.3),它给出:
2021-05-07T12:50:46+00:00
2021-05-07T20:50:46+08:00
非常简单,只使用标准库~
Python 3.9添加了zoneinfo模块,所以现在可以这样做(仅限stdlib):
from zoneinfo import ZoneInfo
from datetime import datetime
utc_unaware = datetime(2020, 10, 31, 12) # loaded from database
utc_aware = utc_unaware.replace(tzinfo=ZoneInfo('UTC')) # make aware
local_aware = utc_aware.astimezone(ZoneInfo('localtime')) # convert
中欧比UTC早1或2小时,因此local_aware为:
datetime.datetime(2020, 10, 31, 13, 0, tzinfo=backports.zoneinfo.ZoneInfo(key='localtime'))
#,只要str:
2020-10-31 13:00:00+01:00
Windows没有系统时区数据库,所以这里需要一个额外的包:
pip install tzdata
在Python 3.6到3.8中允许使用一个backport:
sudo pip install backports.zoneinfo
然后:
from backports.zoneinfo import ZoneInfo
你不能用标准库来做。使用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)
根据阿列克谢的评论。这也适用于DST。
import time
import datetime
def utc_to_local(dt):
if time.localtime().tm_isdst:
return dt - datetime.timedelta(seconds = time.altzone)
else:
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中,这对我来说是可行的。