仅使用python标准库将python UTC日期时间转换为本地日期时间?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4563272/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Convert a python UTC datetime to a local datetime using only python standard library?
提问by Nitro Zark
I have a python datetime instance that was created using datetime.utcnow() and persisted in database.
我有一个使用 datetime.utcnow() 创建并保存在数据库中的 python datetime 实例。
For display, I would like to convert the datetime instance retrieved from the database to local datetime using the default local timezone (i.e., as if the datetime was created using datetime.now()).
为了显示,我想将从数据库中检索到的日期时间实例转换为使用默认本地时区的本地日期时间(即,就好像日期时间是使用 datetime.now() 创建的一样)。
How can I convert the UTC datetime to a local datetime using only python standard library (e.g., no pytz dependency)?
如何仅使用 python 标准库(例如,没有 pytz 依赖项)将 UTC 日期时间转换为本地日期时间?
It seems one solution would be to use datetime.astimezone( tz ), but how would you get the default local timezone?
似乎一种解决方案是使用 datetime.astimezone( tz ),但是如何获得默认的本地时区?
采纳答案by Nitro Zark
I think I figured it out: computes number of seconds since epoch, then converts to a local timzeone using time.localtime, and then converts the time struct back into a datetime...
我想我想通了:计算自纪元以来的秒数,然后使用 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 )
It applies the summer/winter DST correctly:
它正确应用夏季/冬季 DST:
>>> 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)
回答by Lennart Regebro
You can't do it with only the standard library as the standard library doesn't have any timezones. You need pytzor dateutil.
你不能只用标准库来做,因为标准库没有任何时区。您需要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())
Or well, you can do it without pytz or dateutil by implementing your own timezones. But that would be silly.
或者,您可以通过实现您自己的时区来在没有 pytz 或 dateutil 的情况下完成它。但那将是愚蠢的。
回答by Mark Ransom
The standard Python library does not come with any tzinfoimplementations at all. I've always considered this a surprising shortcoming of the datetime module.
标准 Python 库根本没有任何tzinfo实现。我一直认为这是 datetime 模块的一个令人惊讶的缺点。
The documentation for the tzinfo classdoes come with some useful examples. Look for the large code block at the end of the section.
回答by jfs
In Python 3.3+:
在 Python 3.3+ 中:
from datetime import datetime, timezone
def utc_to_local(utc_dt):
return utc_dt.replace(tzinfo=timezone.utc).astimezone(tz=None)
In Python 2/3:
在 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)
Using pytz(both Python 2/3):
使用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
Example
例子
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()))
Output
输出
蟒蛇 3.32010-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
Note: it takes into account DST and the recent change of utc offset for MSK timezone.
注意:它考虑了夏令时和最近 MSK 时区的 utc 偏移量变化。
I don't know whether non-pytz solutions work on Windows.
我不知道非 pytz 解决方案是否适用于 Windows。
回答by Alexei Averchenko
A simple (but maybe flawed) way that works in Python 2 and 3:
一种适用于 Python 2 和 3 的简单(但可能有缺陷)方式:
import time
import datetime
def utc_to_local(dt):
return dt - datetime.timedelta(seconds = time.timezone)
Its advantage is that it's trivial to write an inverse function
它的优点是写反函数很简单
回答by N Randhawa
You can't do it with standard library. Using pytzmodule you can convert any naive/aware datetime object to any other time zone. Lets see some examples using Python 3.
你不能用标准库来做到这一点。使用 pytz模块,您可以将任何原始/感知日期时间对象转换为任何其他时区。让我们看一些使用 Python 3 的例子。
Naive objects created through class method
utcnow()
通过类方法创建的朴素对象
utcnow()
To convert a naiveobject to any other time zone, first you have to convert it into awaredatetime object. You can use the replacemethod for converting a naivedatetime object to an awaredatetime object. Then to convert an awaredatetime object to any other timezone you can use astimezonemethod.
要将原始对象转换为任何其他时区,首先必须将其转换为可感知的日期时间对象。您可以使用该replace方法将原始日期时间对象转换为感知日期时间对象。然后将有意识的日期时间对象转换为任何其他时区,您可以使用astimezone方法。
The variable pytz.all_timezonesgives you the list of all available time zones in pytz module.
该变量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)
Naive objects created through class method
now()
通过类方法创建的朴素对象
now()
Because nowmethod returns current date and time, so you have to make the datetime object timezone aware first. The localizefunction converts a naivedatetime object into a timezone-aware datetime object. Then you can use the astimezonemethod to convert it into another timezone.
因为now方法返回当前日期和时间,所以你必须先让 datetime 对象时区知道。该localize功能的转换天真的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)
回答by Zld Productions
The easiest way I have found is to get the time offset of where youare, then subtract that from the hour.
我发现的最简单的方法是获取您所在位置的时间偏移,然后从小时中减去它。
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
This works for me, in Python 3.5.2.
这对我有用,在 Python 3.5.2 中。
回答by John Kerns
Building on Alexei's comment. This should work for DST too.
以阿列克谢的评论为基础。这也适用于 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)
回答by Guest
Here is another way to change timezone in datetime format (I know I wasted my energy on this but I didn't see this page so I don't know how) without min. and sec. cause I don't need it for my project:
这是另一种以日期时间格式更改时区的方法(我知道我浪费了我的精力,但我没有看到这个页面,所以我不知道如何)没有分钟。和秒。因为我的项目不需要它:
def change_time_zone(year, month, day, hour):
hour = hour + 7 #<-- difference
if hour >= 24:
difference = hour - 24
hour = difference
day += 1
long_months = [1, 3, 5, 7, 8, 10, 12]
short_months = [4, 6, 9, 11]
if month in short_months:
if day >= 30:
day = 1
month += 1
if month > 12:
year += 1
elif month in long_months:
if day >= 31:
day = 1
month += 1
if month > 12:
year += 1
elif month == 2:
if not year%4==0:
if day >= 29:
day = 1
month += 1
if month > 12:
year += 1
else:
if day >= 28:
day = 1
month += 1
if month > 12:
year += 1
return datetime(int(year), int(month), int(day), int(hour), 00)
回答by Arthur D. Howland
This is a terrible way to do it but it avoids creating a definition. It fulfills the requirement to stick with the basic Python3 library.
这是一种糟糕的方法,但它避免了创建定义。它满足了坚持使用基本 Python3 库的要求。
# Adjust from UST to Eastern Standard Time (dynamic)
# df.my_localtime should already be in datetime format, so just in case
df['my_localtime'] = pd.to_datetime.df['my_localtime']
df['my_localtime'] = df['my_localtime'].dt.tz_localize('UTC').dt.tz_convert('America/New_York').astype(str)
df['my_localtime'] = pd.to_datetime(df.my_localtime.str[:-6])

