为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

拉风的咖菲猫 2019-08-16 15:05:30
仅使用python标准库将python UTC日期时间转换为本地日期时间?我有一个使用datetime.utcnow()创建并保存在数据库中的python datetime实例。为了显示,我想使用默认的本地时区将从数据库检索的日期时间实例转换为本地日期时间(即,就像使用datetime.now()创建日期时间一样)。如何仅使用python标准库将UTC日期时间转换为本地日期时间(例如,没有pytz依赖项)?似乎一个解决方案是使用datetime.astimezone(tz),但是如何获得默认的本地时区?
查看完整描述

3 回答

?
慕莱坞森

TA贡献1810条经验 获得超4个赞


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

使用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

Python 2

2010-06-06 21:29:07.730000 

2010-12-06 20:29:07.730000 

2012-11-08 14:19:50.093911 

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

注意:它考虑了DST和最近MSK时区的utc偏移的变化。


我不知道非pytz解决方案是否适用于Windows。


查看完整回答
反对 回复 2019-08-16
?
扬帆大鱼

TA贡献1799条经验 获得超9个赞

您不能只使用标准库,因为标准库没有任何时区。你需要pytzdateutil

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

或者,你可以通过实现自己的时区来实现没有pytz或dateutil。但这很愚蠢。


查看完整回答
反对 回复 2019-08-16
?
慕慕森

TA贡献1856条经验 获得超17个赞

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


查看完整回答
反对 回复 2019-08-16
  • 3 回答
  • 0 关注
  • 811 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信