Python 将UTC日期时间字符串转换为本地日期时间
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4770297/
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 UTC datetime string to local datetime
提问by MattoTodd
I've never had to convert time to and from UTC. Recently had a request to have my app be timezone aware, and I've been running myself in circles. Lots of information on converting local time to UTC, which I found fairly elementary (maybe I'm doing that wrong as well), but I can not find any information on easily converting the UTC time to the end-users timezone.
我从未需要将时间与 UTC 相互转换。最近有一个要求让我的应用程序具有时区意识,我一直在兜圈子。很多关于将本地时间转换为 UTC 的信息,我发现这些信息相当基本(也许我也做错了),但我找不到任何关于轻松将 UTC 时间转换为最终用户时区的信息。
In a nutshell, and android app sends me (appengine app) data and within that data is a timestamp. To store that timestamp to utc time I am using:
简而言之,Android 应用程序向我发送(appengine 应用程序)数据,并且在该数据中包含一个时间戳。要将时间戳存储到 UTC 时间,我正在使用:
datetime.utcfromtimestamp(timestamp)
That seems to be working. When my app stores the data, it is being store as 5 hours ahead (I am EST -5)
这似乎奏效了。当我的应用程序存储数据时,它会提前 5 小时存储(我是 EST -5)
The data is being stored on appengine's BigTable, and when retrieved it comes out as a string like so:
数据被存储在 appengine 的 BigTable 上,当检索到它时,它会作为一个字符串出现,如下所示:
"2011-01-21 02:37:21"
How do I convert this string to a DateTime in the users correct time zone?
如何将此字符串转换为用户正确时区中的 DateTime?
Also, what is the recommended storage for a users timezone information? (How do you typically store tz info ie: "-5:00" or "EST" etc etc ?) I'm sure the answer to my first question might contain a parameter the answers the second.
另外,用户时区信息的推荐存储是什么?(您通常如何存储 tz 信息,即:“-5:00”或“EST”等?)我确定我的第一个问题的答案可能包含第二个答案的参数。
采纳答案by Joe Holloway
If you don't want to provide your own tzinfoobjects, check out the python-dateutillibrary. It provides tzinfoimplementations on top of a zoneinfo (Olson) databasesuch that you can refer to time zone rules by a somewhat canonical name.
如果您不想提供自己的tzinfo对象,请查看python-dateutil库。它tzinfo在zoneinfo (Olson) 数据库之上提供实现,以便您可以通过某种规范的名称来引用时区规则。
from datetime import datetime
from dateutil import tz
# METHOD 1: Hardcode zones:
from_zone = tz.gettz('UTC')
to_zone = tz.gettz('America/New_York')
# METHOD 2: Auto-detect zones:
from_zone = tz.tzutc()
to_zone = tz.tzlocal()
# utc = datetime.utcnow()
utc = datetime.strptime('2011-01-21 02:37:21', '%Y-%m-%d %H:%M:%S')
# Tell the datetime object that it's in UTC time zone since
# datetime objects are 'naive' by default
utc = utc.replace(tzinfo=from_zone)
# Convert time zone
central = utc.astimezone(to_zone)
EditExpanded example to show strptimeusage
编辑扩展示例以显示strptime用法
Edit 2Fixed API usage to show better entry point method
编辑 2固定 API 用法以显示更好的入口点方法
Edit 3Included auto-detect methods for timezones (Yarin)
编辑 3包含的时区自动检测方法(Yarin)
回答by Mark Tolonen
See the datetimedocumentation on tzinfoobjects. You have to implement the timezones you want to support yourself. The are examples at the bottom of the documentation.
请参阅有关tzinfo对象的日期时间文档。您必须实施您想要支持自己的时区。这些是文档底部的示例。
Here's a simple example:
这是一个简单的例子:
from datetime import datetime,tzinfo,timedelta
class Zone(tzinfo):
def __init__(self,offset,isdst,name):
self.offset = offset
self.isdst = isdst
self.name = name
def utcoffset(self, dt):
return timedelta(hours=self.offset) + self.dst(dt)
def dst(self, dt):
return timedelta(hours=1) if self.isdst else timedelta(0)
def tzname(self,dt):
return self.name
GMT = Zone(0,False,'GMT')
EST = Zone(-5,False,'EST')
print datetime.utcnow().strftime('%m/%d/%Y %H:%M:%S %Z')
print datetime.now(GMT).strftime('%m/%d/%Y %H:%M:%S %Z')
print datetime.now(EST).strftime('%m/%d/%Y %H:%M:%S %Z')
t = datetime.strptime('2011-01-21 02:37:21','%Y-%m-%d %H:%M:%S')
t = t.replace(tzinfo=GMT)
print t
print t.astimezone(EST)
Output
输出
01/22/2011 21:52:09
01/22/2011 21:52:09 GMT
01/22/2011 16:52:09 EST
2011-01-21 02:37:21+00:00
2011-01-20 21:37:21-05:00a
回答by Matt Billenstein
I traditionally defer this to the frontend -- send times from the backend as timestamps or some other datetime format in UTC, then let the client figure out the timezone offset and render this data in the proper timezone.
我传统上将此推迟到前端 - 从后端发送时间作为时间戳或其他一些 UTC 日期时间格式,然后让客户端计算出时区偏移量并在正确的时区中呈现这些数据。
For a webapp, this is pretty easy to do in javascript -- you can figure out the browser's timezone offset pretty easily using builtin methods and then render the data from the backend properly.
对于 web 应用程序,这在 javascript 中很容易做到——您可以使用内置方法很容易地找出浏览器的时区偏移量,然后从后端正确呈现数据。
回答by DelboyJay
Here is a quick and dirty version that uses the local systems settings to work out the time difference. NOTE: This will not work if you need to convert to a timezone that your current system is not running in. I have tested this with UK settings under BST timezone
这是一个快速而肮脏的版本,它使用本地系统设置来计算时差。注意:如果您需要转换为当前系统未运行的时区,这将不起作用。我已在 BST 时区下使用英国设置对此进行了测试
from datetime import datetime
def ConvertP4DateTimeToLocal(timestampValue):
assert isinstance(timestampValue, int)
# get the UTC time from the timestamp integer value.
d = datetime.utcfromtimestamp( timestampValue )
# calculate time difference from utcnow and the local system time reported by OS
offset = datetime.now() - datetime.utcnow()
# Add offset to UTC time and return it
return d + offset
回答by David Foster
Here's a resilient method that doesn't depend on any external libraries:
这是一个不依赖任何外部库的弹性方法:
from datetime import datetime
import time
def datetime_from_utc_to_local(utc_datetime):
now_timestamp = time.time()
offset = datetime.fromtimestamp(now_timestamp) - datetime.utcfromtimestamp(now_timestamp)
return utc_datetime + offset
This avoids the timing issues in DelboyJay's example. And the lesser timing issues in Erik van Oosten's amendment.
这避免了 DelboyJay 示例中的计时问题。以及 Erik van Oosten 修正案中较少的时间问题。
As an interesting footnote, the timezone offset computed above can differ from the following seemingly equivalent expression, probably due to daylight savings rule changes:
作为一个有趣的脚注,上面计算的时区偏移量可能与以下看似等效的表达式不同,可能是由于夏令时规则的变化:
offset = datetime.fromtimestamp(0) - datetime.utcfromtimestamp(0) # NO!
Update:This snippet has the weakness of using the UTC offset of the present time, which may differ from the UTC offset of the input datetime. See comments on this answer for another solution.
更新:此代码段的弱点是使用当前时间的 UTC 偏移量,这可能与输入日期时间的 UTC 偏移量不同。有关另一个解决方案,请参阅对此答案的评论。
To get around the different times, grab the epoch time from the time passed in. Here's what I do:
为了绕过不同的时间,从过去的时间中获取纪元时间。这就是我所做的:
def utc2local (utc):
epoch = time.mktime(utc.timetuple())
offset = datetime.fromtimestamp (epoch) - datetime.utcfromtimestamp (epoch)
return utc + offset
回答by frmdstryr
If using Django, you can use the timezone.localtimemethod:
如果使用 Django,则可以使用以下timezone.localtime方法:
from django.utils import timezone
date
# datetime.datetime(2014, 8, 1, 20, 15, 0, 513000, tzinfo=<UTC>)
timezone.localtime(date)
# datetime.datetime(2014, 8, 1, 16, 15, 0, 513000, tzinfo=<DstTzInfo 'America/New_York' EDT-1 day, 20:00:00 DST>)
回答by jfs
If you want to get the correct result even for the time that corresponds to an ambiguous local time (e.g., during a DST transition) and/or the local utc offset is different at different times in your local time zone then use pytztimezones:
如果您想获得正确的结果,即使在对应于不明确的本地时间(例如,在 DST 转换期间)和/或本地时区不同时间的本地 utc 偏移量不同,请使用pytz时区:
#!/usr/bin/env python
from datetime import datetime
import pytz # $ pip install pytz
import tzlocal # $ pip install tzlocal
local_timezone = tzlocal.get_localzone() # get pytz tzinfo
utc_time = datetime.strptime("2011-01-21 02:37:21", "%Y-%m-%d %H:%M:%S")
local_time = utc_time.replace(tzinfo=pytz.utc).astimezone(local_timezone)
回答by myaut
You can use calendar.timegmto convert your time to seconds since Unix epoch and time.localtimeto convert back:
您可以使用calendar.timegm将您的时间转换为自 Unix 纪元以来的秒数并time.localtime转换回来:
import calendar
import time
time_tuple = time.strptime("2011-01-21 02:37:21", "%Y-%m-%d %H:%M:%S")
t = calendar.timegm(time_tuple)
print time.ctime(t)
Gives Fri Jan 21 05:37:21 2011(because I'm in UTC+03:00 timezone).
给出Fri Jan 21 05:37:21 2011(因为我在 UTC+03:00 时区)。
回答by Brōtsyorfuzthrāx
This answer should be helpful if you don't want to use any other modules besides datetime.
如果您不想使用除datetime.
datetime.utcfromtimestamp(timestamp)returns a naive datetimeobject (not an aware one). Aware ones are timezone aware, and naive are not. You want an aware one if you want to convert between timezones (e.g. between UTC and local time).
datetime.utcfromtimestamp(timestamp)返回一个天真的datetime对象(不是一个有意识的对象)。有意识的人是时区意识的,而幼稚的则不是。如果您想在时区之间进行转换(例如在 UTC 和本地时间之间),您需要一个有意识的。
If you aren't the one instantiating the date to start with, but you can still create a naive datetimeobject in UTC time, you might want to try this Python 3.x code to convert it:
如果您不是实例化开始日期的人,但您仍然可以datetime在 UTC 时间创建一个简单的对象,您可能想尝试使用这个 Python 3.x 代码来转换它:
import datetime
d=datetime.datetime.strptime("2011-01-21 02:37:21", "%Y-%m-%d %H:%M:%S") #Get your naive datetime object
d=d.replace(tzinfo=datetime.timezone.utc) #Convert it to an aware datetime object in UTC time.
d=d.astimezone() #Convert it to your local timezone (still aware)
print(d.strftime("%d %b %Y (%I:%M:%S:%f %p) %Z")) #Print it with a directive of choice
Be careful not to mistakenly assume that if your timezone is currently MDT that daylight savings doesn't work with the above code since it prints MST. You'll note that if you change the month to August, it'll print MDT.
注意不要错误地假设,如果您的时区当前是 MDT,那么夏令时不适用于上述代码,因为它打印 MST。您会注意到,如果将月份更改为八月,它将打印 MDT。
Another easy way to get an aware datetimeobject (also in Python 3.x) is to create it with a timezone specified to start with. Here's an example, using UTC:
获取感知datetime对象(也在 Python 3.x 中)的另一种简单方法是使用指定的时区开始创建它。这是一个使用 UTC 的示例:
import datetime, sys
aware_utc_dt_obj=datetime.datetime.now(datetime.timezone.utc) #create an aware datetime object
dt_obj_local=aware_utc_dt_obj.astimezone() #convert it to local time
#The following section is just code for a directive I made that I liked.
if sys.platform=="win32":
directive="%#d %b %Y (%#I:%M:%S:%f %p) %Z"
else:
directive="%-d %b %Y (%-I:%M:%S:%f %p) %Z"
print(dt_obj_local.strftime(directive))
If you use Python 2.x, you'll probably have to subclass datetime.tzinfoand use that to help you create an aware datetimeobject, since datetime.timezonedoesn't exist in Python 2.x.
如果您使用 Python 2.x,您可能必须datetime.tzinfo创建子类并使用它来帮助您创建一个感知datetime对象,因为datetime.timezonePython 2.x 中不存在。

