为什么 datetime.datetime.utcnow() 不包含时区信息?

发布于 2024-08-23 01:46:46 字数 154 浏览 4 评论 0原文

datetime.datetime.utcnow()

既然这个 datetime 明确是 UTC datetime,为什么它没有任何时区信息?

我希望这会包含 tzinfo。

datetime.datetime.utcnow()

Why does this datetime not have any timezone info given that it is explicitly a UTC datetime?

I would expect that this would contain tzinfo.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

心头的小情儿 2024-08-30 01:46:46

请注意,对于 Python 3.2 及以上版本, datetime 模块包含 datetime.timezonedatetime.utcnow() 的文档 说:

可以通过调用 datetime.now(timezone.utc).

因此,datetime.utcnow() 不会设置 tzinfo 来指示它是 UTC,而是 datetime.now(datetime.timezone.utc) > 确实返回设置了 tzinfo 的 UTC 时间。

所以你可以这样做:

>>> import datetime
>>> datetime.datetime.now(datetime.timezone.utc)
datetime.datetime(2014, 7, 10, 2, 43, 55, 230107, tzinfo=datetime.timezone.utc)

从Python 3.11开始,还存在 datetime。 UTC 相当于 datetime.timezone.utc。因此,您也可以执行datetime.datetime.now(datetime.UTC)

Note that for Python 3.2 onwards, the datetime module contains datetime.timezone. The documentation for datetime.utcnow() says:

An aware current UTC datetime can be obtained by calling datetime.now(timezone.utc).

So, datetime.utcnow() doesn't set tzinfo to indicate that it is UTC, but datetime.now(datetime.timezone.utc) does return UTC time with tzinfo set.

So you can do:

>>> import datetime
>>> datetime.datetime.now(datetime.timezone.utc)
datetime.datetime(2014, 7, 10, 2, 43, 55, 230107, tzinfo=datetime.timezone.utc)

Since Python 3.11, there also exists datetime.UTC which is equivalent to datetime.timezone.utc. So you can also do datetime.datetime.now(datetime.UTC).

平安喜乐 2024-08-30 01:46:46

这意味着它是天真的时区,所以你不能将它与datetime.astimezone一起使用

你可以给它一个像这样的时区

import pytz  # 3rd party: $ pip install pytz

u = datetime.utcnow()
u = u.replace(tzinfo=pytz.utc) #NOTE: it works only with a fixed utc offset

现在你可以更改时区

print(u.astimezone(pytz.timezone("America/New_York")))

要获取给定时区的当前时间,你可以直接将 tzinfo 传递给 datetime.now()

#!/usr/bin/env python
from datetime import datetime
import pytz # $ pip install pytz

print(datetime.now(pytz.timezone("America/New_York")))

它适用于任何时区,包括遵守夏令时 (DST) 的时区,即,它适用于在不同时间可能具有不同 utc 偏移量的时区(非固定 utc 偏移量)。不要使用 tz.localize(datetime.now()) - 当本地时间不明确时,它可能会在 DST 结束转换期间失败。

That means it is timezone naive, so you can't use it with datetime.astimezone

you can give it a timezone like this

import pytz  # 3rd party: $ pip install pytz

u = datetime.utcnow()
u = u.replace(tzinfo=pytz.utc) #NOTE: it works only with a fixed utc offset

now you can change timezones

print(u.astimezone(pytz.timezone("America/New_York")))

To get the current time in a given timezone, you could pass tzinfo to datetime.now() directly:

#!/usr/bin/env python
from datetime import datetime
import pytz # $ pip install pytz

print(datetime.now(pytz.timezone("America/New_York")))

It works for any timezone including those that observe daylight saving time (DST) i.e., it works for timezones that may have different utc offsets at different times (non-fixed utc offset). Don't use tz.localize(datetime.now()) -- it may fail during end-of-DST transition when the local time is ambiguous.

執念 2024-08-30 01:46:46

在 Python 3.2 之前,标准 Python 库不包含任何 tzinfo 类。我只能猜测原因。就我个人而言,我认为不包含 UTC 的 tzinfo 类是一个错误,因为该类没有争议,足以有一个标准实现。尽管库中没有实现,但在 tzinfo 文档

from datetime import timedelta, tzinfo

ZERO = timedelta(0)

# A UTC class.

class UTC(tzinfo):
    """UTC"""

    def utcoffset(self, dt):
        return ZERO

    def tzname(self, dt):
        return "UTC"

    def dst(self, dt):
        return ZERO

utc = UTC()

一旦您拥有 UTC tzinfo 对象,您仍然无法将其与 utcnow 一起使用。为了将当前时间作为感知的日期时间对象:

from datetime import datetime 

now = datetime.now(utc)

在 Python 3.2 中,他们最终在库中放入了 UTC tzinfo 类:

from datetime import datetime, timezone 

now = datetime.now(timezone.utc)

在 Python 3.9 中,他们为所有其他创建了 tzinfo 类时区。请参阅PEP 615 - 标准库中对 IANA 时区数据库的支持了解所有详细信息。

The standard Python libraries didn't include any tzinfo classes until Python 3.2. I can only guess at the reasons. Personally I think it was a mistake not to include a tzinfo class for UTC, because that one is uncontroversial enough to have a standard implementation. Although there was no implementation in the library, there is one given as an example in the tzinfo documentation.

from datetime import timedelta, tzinfo

ZERO = timedelta(0)

# A UTC class.

class UTC(tzinfo):
    """UTC"""

    def utcoffset(self, dt):
        return ZERO

    def tzname(self, dt):
        return "UTC"

    def dst(self, dt):
        return ZERO

utc = UTC()

Once you have a UTC tzinfo object, you still can't use it with utcnow. To get the current time as an aware datetime object:

from datetime import datetime 

now = datetime.now(utc)

In Python 3.2 they finally put a UTC tzinfo class in the library:

from datetime import datetime, timezone 

now = datetime.now(timezone.utc)

In Python 3.9 they created tzinfo classes for all the other time zones. See PEP 615 -- Support for the IANA Time Zone Database in the Standard Library for all the details.

眼前雾蒙蒙 2024-08-30 01:46:46

pytz 模块是一个选项,还有另一个 python-dateutil,虽然也是第三方包,但可能已经可用,具体取决于您的其他依赖项和操作系统。

我只是想包含此方法以供参考 - 如果您已经出于其他目的安装了 python-dateutil,则可以使用其 tzinfo 而不是使用 pytz 进行复制

import datetime
import dateutil.tz

# Get the UTC time with datetime.now:
utcdt = datetime.datetime.now(dateutil.tz.tzutc())

# Get the UTC time with datetime.utcnow:
utcdt = datetime.datetime.utcnow()
utcdt = utcdt.replace(tzinfo=dateutil.tz.tzutc())

# For fun- get the local time
localdt = datetime.datetime.now(dateutil.tz.tzlocal())

我倾向于同意对 utcnow 的调用应包含 UTC 时区信息。我怀疑这不包括在内,因为本机日期时间库默认为天真的日期时间以实现交叉兼容性。

The pytz module is one option, and there is another python-dateutil, which although is also third party package, may already be available depending on your other dependencies and operating system.

I just wanted to include this methodology for reference- if you've already installed python-dateutil for other purposes, you can use its tzinfo instead of duplicating with pytz

import datetime
import dateutil.tz

# Get the UTC time with datetime.now:
utcdt = datetime.datetime.now(dateutil.tz.tzutc())

# Get the UTC time with datetime.utcnow:
utcdt = datetime.datetime.utcnow()
utcdt = utcdt.replace(tzinfo=dateutil.tz.tzutc())

# For fun- get the local time
localdt = datetime.datetime.now(dateutil.tz.tzlocal())

I tend to agree that calls to utcnow should include the UTC timezone information. I suspect that this is not included because the native datetime library defaults to naive datetimes for cross compatibility.

拧巴小姐 2024-08-30 01:46:46

在 Python 3.2+ 中添加时区信息

import datetime

>>> d = datetime.datetime.now(tz=datetime.timezone.utc)
>>> print(d.tzinfo)
'UTC+00:00'

To add timezone information in Python 3.2+

import datetime

>>> d = datetime.datetime.now(tz=datetime.timezone.utc)
>>> print(d.tzinfo)
'UTC+00:00'
电影里的梦 2024-08-30 01:46:46

Julien Danjou 写了一篇很好的文章,解释了 原因你永远不应该处理时区。摘录:

事实上,Python datetime API 总是返回不知道的 datetime 对象,
这是非常不幸的。事实上,一旦你得到其中之一
对象,无法知道时区是什么,因此这些
对象本身非常“无用”。

唉,即使您可以使用 utcnow(),您仍然不会看到时区信息,正如您发现的那样。

建议:

  • 始终使用感知的datetime对象,即带有时区信息的对象。那
    确保您可以直接比较它们(有意识和无意识datetime
    对象不具有可比性)并将它们正确返回给用户。
    利用pytz来获取时区对象。

  • 使用 ISO 8601 作为输入并
    输出字符串格式。使用datetime.datetime.isoformat()返回
    时间戳为使用该格式格式化的字符串,其中包括
    时区信息。

  • 如果您需要解析包含 ISO 8601 格式时间戳的字符串,
    您可以依赖 iso8601,它会返回正确的时间戳
    时区信息。这使得时间戳可以直接比较。

Julien Danjou wrote a good article explaining why you should never deal with timezones. An excerpt:

Indeed, Python datetime API always returns unaware datetime objects,
which is very unfortunate. Indeed, as soon as you get one of this
object, there is no way to know what the timezone is, therefore these
objects are pretty "useless" on their own.

Alas, even though you may use utcnow(), you still won't see the timezone info, as you discovered.

Recommendations:

  • Always use aware datetime objects, i.e. with timezone information. That
    makes sure you can compare them directly (aware and unaware datetime
    objects are not comparable) and will return them correctly to users.
    Leverage pytz to have timezone objects.

  • Use ISO 8601 as the input and
    output string format. Use datetime.datetime.isoformat() to return
    timestamps as string formatted using that format, which includes the
    timezone information.

  • If you need to parse strings containing ISO 8601 formatted timestamps,
    you can rely on iso8601, which returns timestamps with correct
    timezone information. This makes timestamps directly comparable.

舂唻埖巳落 2024-08-30 01:46:46

datetime.datetime.utcnow() 将 UTC 时间返回为原始日期时间对象的行为显然是有问题的,必须修复。如果您的系统本地时区不是 UTC,则可能会导致意外结果,因为日期时间库假定原始日期时间对象来表示系统本地时间。例如,datetime.datetime.utcnow().timestaamp() 给出的时间戳比我计算机上的正确值提前 4 小时。另外,从 python 3.6 开始,可以在原始日期时间实例上调用 datetime.astimezone() ,但是 datetime.datetime.utcnow().astimezone(any_timezone) 给出错误的结果除非您的系统本地时区是 UTC。

The behaviour of datetime.datetime.utcnow() returning UTC time as naive datetime object is obviously problematic and must be fixed. It can lead to unexpected result if your system local timezone is not UTC, since datetime library presume naive datetime object to represent system local time. For example, datetime.datetime.utcnow().timestaamp() gives timestamp of 4 hours ahead from correct value on my computer. Also, as of python 3.6, datetime.astimezone() can be called on naive datetime instances, but datetime.datetime.utcnow().astimezone(any_timezone) gives wrong result unless your system local timezone is UTC.

杀手六號 2024-08-30 01:46:46

它还应该包括 now() 。相关问题

在此之前,now() 优于 today()utcnow()

from datetime import datetime, timezone
utc = timezone.utc
date = datetime.now(utc)
print(date) # 2022-04-06 05:40:13.025347+00:00

It should include and now() also. Related issue.

So till that, now() is preferred over today() and utcnow().

from datetime import datetime, timezone
utc = timezone.utc
date = datetime.now(utc)
print(date) # 2022-04-06 05:40:13.025347+00:00
清风无影 2024-08-30 01:46:46
from datetime import datetime 
from dateutil.relativedelta import relativedelta
d = datetime.now()
date = datetime.isoformat(d).split('.')[0]
d_month = datetime.today() + relativedelta(months=1)
next_month = datetime.isoformat(d_month).split('.')[0]
from datetime import datetime 
from dateutil.relativedelta import relativedelta
d = datetime.now()
date = datetime.isoformat(d).split('.')[0]
d_month = datetime.today() + relativedelta(months=1)
next_month = datetime.isoformat(d_month).split('.')[0]
小嗷兮 2024-08-30 01:46:46

UTC 日期不需要任何时区信息,因为它们是 UTC,根据定义,这意味着它们没有偏移量。

UTC dates don't need any timezone info since they're UTC, which by definition means that they have no offset.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文