Nit*_*ark 150 python timezone datetime python-datetime
我有一个使用datetime.utcnow()创建并保存在数据库中的python datetime实例.
为了显示,我想使用默认的本地时区将从数据库检索的日期时间实例转换为本地日期时间(即,就像使用datetime.now()创建日期时间一样).
如何仅使用python标准库将UTC日期时间转换为本地日期时间(例如,没有pytz依赖项)?
似乎一个解决方案是使用datetime.astimezone(tz),但是如何获得默认的本地时区?
jfs*_*jfs 222
在Python 3.3+中:
from datetime import datetime, timezone
def utc_to_local(utc_dt):
return utc_dt.replace(tzinfo=timezone.utc).astimezone(tz=None)
Run Code Online (Sandbox Code Playgroud)
在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)
Run Code Online (Sandbox Code Playgroud)
使用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
Run Code Online (Sandbox Code Playgroud)
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()))
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
Python 2
2010-06-06 21:29:07.730000
2010-12-06 20:29:07.730000
2012-11-08 14:19:50.093911
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
注意:它考虑了DST和最近MSK时区的utc偏移的变化.
我不知道非pytz解决方案是否适用于Windows.
Len*_*bro 40
您不能只使用标准库,因为标准库没有任何时区.你需要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())
Run Code Online (Sandbox Code Playgroud)
或者,你可以通过实现自己的时区来实现没有pytz或dateutil.但这很愚蠢.
xjc*_*jcl 16
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
Run Code Online (Sandbox Code Playgroud)
中欧比 UTC 早 1 或 2 小时,因此local_aware:
datetime.datetime(2020, 10, 31, 13, 0, tzinfo=backports.zoneinfo.ZoneInfo(key='localtime'))
Run Code Online (Sandbox Code Playgroud)
如str:
2020-10-31 13:00:00+01:00
Run Code Online (Sandbox Code Playgroud)
Windows 没有系统时区数据库,所以这里需要一个额外的包:
pip install tzdata
Run Code Online (Sandbox Code Playgroud)
有一个 backport 允许在Python 3.6 到 3.8 中使用:
sudo pip install backports.zoneinfo
Run Code Online (Sandbox Code Playgroud)
然后:
from backports.zoneinfo import ZoneInfo
Run Code Online (Sandbox Code Playgroud)
小智 8
以阿列克谢的评论为基础。这也适用于 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)
Run Code Online (Sandbox Code Playgroud)
我想我想出来了:计算自纪元以来的秒数,然后使用time.localtime转换为本地timzeone,然后将时间结构转换回日期时间......
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 )
Run Code Online (Sandbox Code Playgroud)
它正确应用夏季/冬季夏令时:
>>> 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)
Run Code Online (Sandbox Code Playgroud)
你不能用标准库来做.使用 pytz模块,您可以将任何天真/感知日期时间对象转换为任何其他时区.让我们看一些使用Python 3的例子.
通过类方法创建的朴素对象
utcnow()
要将天真对象转换为任何其他时区,首先必须将其转换为知晓日期时间对象.您可以使用该replace方法将天真的日期时间对象转换为知晓的日期时间对象.然后,要将感知日期时间对象转换为任何其他时区,您可以使用astimezone方法.
该变量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)
Run Code Online (Sandbox Code Playgroud)
通过类方法创建的朴素对象
now()
因为now方法返回当前日期和时间,所以您必须首先知道datetime对象时区.该localize 函数将一个天真的日期时间对象转换为一个时区感知的日期时间对象.然后,您可以使用该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)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
179281 次 |
| 最近记录: |