首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何仅使用标准库将UTC日期时间转换为本地日期时间?

如何仅使用标准库将UTC日期时间转换为本地日期时间?
EN

Stack Overflow用户
提问于 2010-12-30 22:14:42
回答 11查看 339.6K关注 0票数 254

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

为了便于显示,我想将从数据库检索到的datetime实例转换为使用默认本地时区的本地datetime (即,就好像datetime是使用datetime.now()创建的一样)。

如何仅使用python标准库(例如,无pytz依赖)将UTC datetime转换为本地datetime

似乎一种解决方案是使用datetime.astimezone(tz),但是如何获得默认的本地时区呢?

EN

回答 11

Stack Overflow用户

回答已采纳

发布于 2010-12-30 23:02:47

我想我弄明白了:计算从纪元开始的秒数,然后使用time.localtime转换为本地时间,然后将时间结构转换回datetime……

代码语言:javascript
复制
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:

代码语言:javascript
复制
>>> 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)
票数 7
EN

Stack Overflow用户

发布于 2012-11-08 18:22:27

在Python 3.3+中:

代码语言:javascript
复制
from datetime import datetime, timezone

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

在Python 2/3中:

代码语言:javascript
复制
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 (都是Python2/3):

代码语言:javascript
复制
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

示例

代码语言:javascript
复制
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

代码语言:javascript
复制
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

代码语言:javascript
复制
2010-06-06 21:29:07.730000 
2010-12-06 20:29:07.730000 
2012-11-08 14:19:50.093911 

pytz

代码语言:javascript
复制
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解决方案是否适用于Windows。

票数 368
EN

Stack Overflow用户

发布于 2010-12-30 22:42:24

从Python3.9开始,您可以使用zoneinfo模块。

首先,让我们使用utcnow()来获得时间

代码语言:javascript
复制
>>> from datetime import datetime
>>> database_time = datetime.utcnow()
>>> database_time
datetime.datetime(2021, 9, 24, 4, 18, 27, 706532)

然后创建时区:

代码语言:javascript
复制
>>> from zoneinfo import ZoneInfo
>>> utc = ZoneInfo('UTC')
>>> localtz = ZoneInfo('localtime')

然后转换。要在时区之间转换,datetime必须知道它所在的时区,然后我们只需使用astimezone()

代码语言:javascript
复制
>>> utctime = database_time.replace(tzinfo=utc)
>>> localtime = utctime.astimezone(localtz)
>>> localtime
datetime.datetime(2021, 9, 24, 6, 18, 27, 706532, tzinfo=zoneinfo.ZoneInfo(key='localtime'))

对于Python3.6到3.8,您需要backports.zoneinfo模块:

代码语言:javascript
复制
>>> try:
>>>     from zoneinfo import ZoneInfo
>>> except ImportError:
>>>     from backports.zoneinfo import ZoneInfo

其余的都是一样的。

对于早于此的版本,则需要pytzdateutil。datutil的工作原理类似于zoneinfo:

代码语言:javascript
复制
>>> from dateutil import tz
>>> utc = tz.gettz('UTC')
>>> localtz = tz.tzlocal()

The Conversion:
>>> utctime = now.replace(tzinfo=UTC)
>>> localtime = utctime.astimezone(localtz)
>>> localtime
datetime.datetime(2010, 12, 30, 15, 51, 22, 114668, tzinfo=tzlocal())

pytz有一个不同的接口,这是由于Python的时区处理不能处理不明确的时间:

代码语言:javascript
复制
>>> import pytz
>>> utc = pytz.timezone('UTC')
# There is no local timezone support, you need to know your timezone
>>> localtz = pytz.timezone('Europe/Paris')

>>> utctime = utc.localize(database_time)
>>> localtime = localtz.normalize(utctime.astimezone(localtz))
>>> localtime
票数 66
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4563272

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档