将 UTC 日期时间字符串转换为本地日期时间
我从来没有需要在 UTC 和 UTC 之间进行时间转换。最近有人请求让我的应用程序了解时区,但我一直在兜圈子。有关将本地时间转换为 UTC 的大量信息,我发现这些信息相当简单(也许我也做错了),但我找不到任何有关轻松将 UTC 时间转换为最终用户时区的信息。
简而言之,Android 应用程序向我(appengine 应用程序)发送数据,并且该数据中包含时间戳。为了将该时间戳存储为 utc 时间,我正在使用:
datetime.utcfromtimestamp(timestamp)
这似乎有效。当我的应用程序存储数据时,它被存储为提前 5 小时(我是 EST -5)
数据被存储在 appengine 的 BigTable 上,当检索时,它会以字符串形式出现,如下所示:
"2011-01-21 02:37:21"
如何将此字符串转换为用户正确时区的日期时间?
另外,用户时区信息的建议存储是什么? (你通常如何存储 tz 信息,即:“-5:00”或“EST”等?)我确信我的第一个问题的答案可能包含一个参数,第二个问题的答案。
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.
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:
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)
The data is being stored on appengine's BigTable, and when retrieved it comes out as a string like so:
"2011-01-21 02:37:21"
How do I convert this string to a DateTime in the users correct time zone?
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(16)
如果您不想提供自己的
tzinfo
对象,请查看 python-dateutil< /a> 库。它在 zoneinfo (Olson) 数据库 之上提供tzinfo
实现,例如您可以通过有点规范的名称来引用时区规则。编辑 扩展示例以显示
strptime
用法编辑 2 修复 API 用法以显示更好的入口点方法
编辑 3 包含自动-时区检测方法(Yarin)
If you don't want to provide your own
tzinfo
objects, check out the python-dateutil library. It providestzinfo
implementations on top of a zoneinfo (Olson) database such that you can refer to time zone rules by a somewhat canonical name.Edit Expanded example to show
strptime
usageEdit 2 Fixed API usage to show better entry point method
Edit 3 Included auto-detect methods for timezones (Yarin)
这是一种不依赖于任何外部库的弹性方法:
这避免了 DelboyJay 示例中的计时问题。以及埃里克·范·奥斯滕修正案中较小的时机问题。
作为一个有趣的脚注,上面计算的时区偏移量可能与以下看似等效的表达式不同,这可能是由于夏令时规则的更改:
更新: 此代码段的缺点是使用当前时间的 UTC 偏移量,这可能与输入日期时间的 UTC 偏移量不同。请参阅对此答案的评论以获取其他解决方案。
为了绕过不同的时间,请从传入的时间中获取纪元时间。这就是我所做的:
Here's a resilient method that doesn't depend on any external libraries:
This avoids the timing issues in DelboyJay's example. And the lesser timing issues in Erik van Oosten's amendment.
As an interesting footnote, the timezone offset computed above can differ from the following seemingly equivalent expression, probably due to daylight savings rule changes:
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.
To get around the different times, grab the epoch time from the time passed in. Here's what I do:
更新了最新的 Python 3 支持(请参阅旧答案的编辑历史记录):
从 Python 3.9 开始,内置的
zoneinfo
库:请参阅
zoneinfo.available_timezones()
获取时区名称列表。这是一个简单的例子:
输出:
Updated for latest Python 3 support (see edit history for old answer):
As of Python 3.9 time zone information is provided in the built-in
zoneinfo
library:See
zoneinfo.available_timezones()
for a list of time zone names.Here's a simple example:
Output:
如果您想获得正确的结果,即使是与不明确的本地时间相对应的时间(例如,在 DST 转换期间)和/或本地 utc 偏移量在本地时区的不同时间不同,请使用 pytz时区:
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
pytz
timezones:如果您不想使用除
datetime
之外的任何其他模块,这个答案应该会有所帮助。datetime.utcfromtimestamp(timestamp)
返回一个简单的datetime
对象(不是一个有意识的对象)。有意识的人会意识到时区,而天真的人则不会。如果您想在时区之间进行转换(例如在 UTC 和本地时间之间),您需要一个有意识的转换。如果您不是实例化日期的人,但您仍然可以以 UTC 时间创建一个简单的
datetime
对象,您可能需要尝试使用以下 Python 3.x 代码来转换它:小心不要错误地认为,如果您的时区当前是 MDT,则夏令时不适用于上述代码,因为它会打印 MST。您会注意到,如果将月份更改为八月,它将打印 MDT。
获取可感知的
datetime
对象(也在 Python 3.x 中)的另一种简单方法是使用指定的时区来创建它。下面是一个使用 UTC 的示例:如果您使用 Python 2.x,您可能需要子类化
datetime.tzinfo
并使用它来帮助您创建一个感知的datetime
对象,因为 Python 2.x 中不存在datetime.timezone
。This answer should be helpful if you don't want to use any other modules besides
datetime
.datetime.utcfromtimestamp(timestamp)
returns a naivedatetime
object (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).If you aren't the one instantiating the date to start with, but you can still create a naive
datetime
object in UTC time, you might want to try this Python 3.x code to convert it: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.
Another easy way to get an aware
datetime
object (also in Python 3.x) is to create it with a timezone specified to start with. Here's an example, using UTC:If you use Python 2.x, you'll probably have to subclass
datetime.tzinfo
and use that to help you create an awaredatetime
object, sincedatetime.timezone
doesn't exist in Python 2.x.如果使用 Django,您可以使用
timezone.localtime
方法:
If using Django, you can use the
timezone.localtime
method:以下内容在美国西部的云环境中对我有用:
The following worked for me in a Cloud environment for US west:
将 franksands 的答案合并为一种方便的方法。
Consolidating the answer from franksands into a convenient method.
您可以使用 arrow
您可以使用
arrow.get()
提供任何事物。时间戳、iso 字符串等You can use arrow
you can feed
arrow.get()
with anything. timestamp, iso string etc从此处的答案中,您可以使用时间模块将 utc 转换为计算机中设置的本地时间:
From the answer here, you can use the time module to convert from utc to the local time set in your computer:
这对我有用:
This worked for me:
您可以使用
calendar.timegm
将时间转换为自Unix纪元以来的秒数,并使用time.localtime
转换回来:给出
Fri Jan 21 05:37:21 2011
(因为我位于 UTC+03:00 时区)。You can use
calendar.timegm
to convert your time to seconds since Unix epoch andtime.localtime
to convert back:Gives
Fri Jan 21 05:37:21 2011
(because I'm in UTC+03:00 timezone).当我输入
utc_tz_example_str
= 2018-10-17T00:00:00.111Z,(UTC +00:00)然后我会得到
local_tz_str
= 2018-10-17T08:00:00+08:00 (我的目标时区 +08:00)参数
utc_format
是由您的特定utc_tz_example_str
确定的格式。参数
local_fmt
是最终所需的格式。就我而言,我所需的格式是
%Y-%m-%dT%H:%M:%S+08:00
(+08:00 时区)。您应该构建您想要的格式。When I input
utc_tz_example_str
= 2018-10-17T00:00:00.111Z, (UTC +00:00)then I will get
local_tz_str
= 2018-10-17T08:00:00+08:00 (My target timezone +08:00)parameter
utc_format
is a format determined by your specificutc_tz_example_str
.parameter
local_fmt
is the final desired format.In my case, my desired format is
%Y-%m-%dT%H:%M:%S+08:00
( +08:00 timezone). You should construct the format you want.我传统上将其推迟到前端——从后端将时间作为时间戳或 UTC 中的其他日期时间格式发送,然后让客户端计算出时区偏移并在正确的时区中呈现此数据。
对于网络应用程序来说,这在 javascript 中很容易做到——您可以使用内置方法轻松计算出浏览器的时区偏移量,然后正确地从后端渲染数据。
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.
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.
这是我的工作代码,允许时区自动检测并支持 DST 时区:
This is my working code allowing timezone auto-detect and support DST timezone:
这是一个快速但肮脏的版本,它使用本地系统设置来计算时差。注意:如果您需要转换到当前系统未运行的时区,这将不起作用。我已经在 BST 时区下使用英国设置对此进行了测试
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