如何仅使用标准库将 UTC 日期时间转换为本地日期时间?
我有一个使用 datetime.utcnow()
创建并保存在数据库中的 python datetime
实例。
为了显示,我想使用默认的本地时区将从数据库检索的 datetime
实例转换为本地 datetime
(即,就像 datetime
> 是使用datetime.now()
创建的)。
如何仅使用 python 标准库(例如,没有 pytz
依赖项)将 UTC datetime
转换为本地 datetime
?
似乎一种解决方案是使用 datetime.astimezone(tz) ,但是如何获得默认的本地时区?
I have a python datetime
instance that was created using datetime.utcnow()
and persisted in database.
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()
).
How can I convert the UTC datetime
to a local datetime
using only python standard library (e.g., no pytz
dependency)?
It seems one solution would be to use datetime.astimezone(tz)
, but how would you get the default local timezone?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(14)
在 Python 3.3+ 中:
在 Python 2/3 中:
使用 pytz(均为 Python 2/3):
示例
输出
Python 3.3
Python 2
pytz
注意:它考虑了 DST 和 MSK 时区 utc 偏移量的最新变化。
我不知道非 pytz 解决方案是否适用于 Windows。
In Python 3.3+:
In Python 2/3:
Using
pytz
(both Python 2/3):Example
Output
Python 3.3
Python 2
pytz
Note: it takes into account DST and the recent change of utc offset for MSK timezone.
I don't know whether non-pytz solutions work on Windows.
从 Python 3.9 开始,您可以使用
zoneinfo
模块。首先让我们使用 utcnow() 获取时间:
然后创建时区:
然后进行转换。要在时区之间进行转换,日期时间必须知道它所在的时区,然后我们只需使用
astimezone()
:对于 Python 3.6 到 3.8,您需要 backports.zoneinfo 模块:
其余相同。
对于早于该版本的版本,需要
pytz
或dateutil
。 datutil 的工作方式与 zoneinfo 类似:pytz
有一个不同的接口,这是 Python 的时区处理不处理模糊时间的结果:Since Python 3.9 you can use the
zoneinfo
module.First lets get that time with
utcnow()
:Then create the time zones:
Then convert. To convert between timezones, the datetime must know what timezone it is in, then we just use
astimezone()
:For Python 3.6 to 3.8 you need the backports.zoneinfo module:
The rest is the same.
For versions earlier than that need
pytz
ordateutil
. datutil works similar to zoneinfo:pytz
has a different interface which is a result of Python's time zone handling not handling ambigous times:Python 3.9 添加了
zoneinfo
模块< /strong> 所以现在可以按如下方式完成(仅限 stdlib):中欧比 UTC 早 1 或 2 小时,因此
local_aware
为:as
str
:Windows 没有系统时区数据库,所以这里需要一个额外的包:
有一个向后移植允许在Python 3.6到3.8中使用:
然后:
Python 3.9 adds the
zoneinfo
module so now it can be done as follows (stdlib only):Central Europe is 1 or 2 hours ahead of UTC, so
local_aware
is:as
str
:Windows has no system time zone database, so here an extra package is needed:
There is a backport to allow use in Python 3.6 to 3.8:
Then:
你不能用标准库做到这一点。使用pytz模块,您可以将任何天真/感知的日期时间对象转换为任何其他时区。让我们看一些使用 Python 3 的示例。
要将 naive 对象转换为任何其他时区,首先必须将其转换为 aware 日期时间目的。您可以使用
replace
方法将naive日期时间对象转换为aware日期时间对象。然后,要将感知日期时间对象转换为任何其他时区,您可以使用astimezone
方法。变量 pytz.all_timezones 为您提供 pytz 模块中所有可用时区的列表。
因为
now
方法返回当前日期和时间,所以你必须首先让 datetime 对象时区知道。localize
函数将原始日期时间对象转换为时区感知的日期时间对象。然后您可以使用astimezone
方法将其转换为另一个时区。You can't do it with standard library. Using pytz module you can convert any naive/aware datetime object to any other time zone. Lets see some examples using Python 3.
To convert a naive object to any other time zone, first you have to convert it into aware datetime object. You can use the
replace
method for converting a naive datetime object to an aware datetime object. Then to convert an aware datetime object to any other timezone you can useastimezone
method.The variable
pytz.all_timezones
gives you the list of all available time zones in pytz module.Because
now
method returns current date and time, so you have to make the datetime object timezone aware first. Thelocalize
function converts a naive datetime object into a timezone-aware datetime object. Then you can use theastimezone
method to convert it into another timezone.以阿列克谢的评论为基础。这也适用于 DST。
Building on Alexei's comment. This should work for DST too.
我想我已经弄清楚了:计算自纪元以来的秒数,然后使用 time.localtime 转换为本地 timzeone,然后将时间结构转换回日期时间...
它正确应用夏季/冬季 DST:
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...
It applies the summer/winter DST correctly:
标准 Python 库根本不附带任何 tzinfo 实现。我一直认为这是日期时间模块的一个令人惊讶的缺点。
tzinfo 类的文档确实提供了一些有用的示例。查找本节末尾的大代码块。
The standard Python library does not come with any
tzinfo
implementations at all. I've always considered this a surprising shortcoming of the datetime module.The documentation for the tzinfo class does come with some useful examples. Look for the large code block at the end of the section.
使用
time.timezone
,它给出一个以“UTC 以西秒数”为单位的整数。例如:
在我的电脑(Python 3.7.3)上,它给出:
非常简单,仅使用标准库~
Use
time.timezone
, it gives an integer in "seconds west of UTC".For example:
On my PC (Python 3.7.3), it gives:
Pretty simple and uses only standard libraries~
我发现的最简单的方法是获取您所在位置的时间偏移量,然后从小时中减去该偏移量。
这对我有用,在 Python 3.5.2 中。
The easiest way I have found is to get the time offset of where you are, then subtract that from the hour.
This works for me, in Python 3.5.2.
一种在 Python 2 和 3 中工作的简单(但可能有缺陷)的方法:
它的优点是编写反函数很简单
A simple (but maybe flawed) way that works in Python 2 and 3:
Its advantage is that it's trivial to write an inverse function
这是另一种以日期时间格式更改时区的方法(我知道我在这方面浪费了精力,但我没有看到此页面,所以我不知道如何),无需分钟。和秒。因为我的项目不需要它:
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:
对于特定情况:
输入 utc 日期时间字符串。 // 通常来自日志
输出区域设置日期时间字符串。
测试:
for a specific situation:
input utc datetime string. // usually from log
output locale datetime string.
tests:
这是一种糟糕的方法,但它避免了创建定义。它满足了坚持使用基本 Python3 库的要求。
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.
使用 timedelta 在时区之间切换。您所需要的只是时区之间的小时偏移量。不必摆弄日期时间对象的所有 6 个元素的边界。 timedelta 也可以轻松处理闰年、闰世纪等。您必须首先
然后如果
offset
是以小时为单位的时区增量:timeout = timein + timedelta(hours = offset)
其中 timein 和 timeout 是日期时间对象。例如
timein + timedelta(hours = -8)
从 GMT 转换为 PST。
那么,如何确定
offset
呢?这是一个简单的函数,前提是您只有几种转换的可能性,而不使用时区“感知”的日期时间对象,其他一些答案很好地做到了这一点。有点手动,但有时清晰度是最好的。在查看了众多答案并使用了我能想到的最严格的代码之后(目前),似乎所有时间很重要且必须考虑混合时区的应用程序都应该真正努力创建所有日期时间对象“意识到的”。那么看起来最简单的答案就是:
例如转换为 GMT。当然,要与您希望的任何其他时区(本地时区或其他时区)进行转换,只需使用 pytz 能够理解的适当时区字符串(来自 pytz.all_timezones)。然后还会考虑夏令时。
Use timedelta to switch between timezones. All you need is the offset in hours between timezones. Don't have to fiddle with boundaries for all 6 elements of a datetime object. timedelta handles leap years, leap centuries, etc., too, with ease. You must first
Then if
offset
is the timezone delta in hours:timeout = timein + timedelta(hours = offset)
where timein and timeout are datetime objects. e.g.
timein + timedelta(hours = -8)
converts from GMT to PST.
So, how to determine
offset
? Here is a simple function provided you only have a few possibilities for conversion without using datetime objects that are timezone "aware" which some other answers nicely do. A bit manual, but sometimes clarity is best.After looking at the numerous answers and playing around with the tightest code I can think of (for now) it seems best that all applications, where time is important and mixed timezones must be accounted for, should make a real effort to make all datetime objects "aware". Then it would seem the simplest answer is:
to convert to GMT for example. Of course, to convert to/from any other timezone you wish, local or otherwise, just use the appropriate timezone string that pytz understands (from pytz.all_timezones). Daylight savings time is then also taken into account.