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

新手上路,请多包涵

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

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

我如何将 UTC datetime 转换为本地 datetime 仅使用 python 标准库(例如,没有 pytz 依赖)?2—

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

原文由 Nitro Zark 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 253
2 个回答

我想我明白了:计算自纪元以来的秒数,然后使用 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 )

它正确应用夏季/冬季夏令时:

 >>> 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)

原文由 Nitro Zark 发布,翻译遵循 CC BY-SA 2.5 许可协议

在 Python 3.3+ 中:

 from datetime import datetime, timezone

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

在 Python 23 中:

 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

蟒蛇2

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

皮茨

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。

原文由 jfs 发布,翻译遵循 CC BY-SA 4.0 许可协议

推荐问题