373
datetime.datetime.utcnow()

为什么它datetime没有任何时区信息,因为它明确是 UTC datetime

我希望这将包含tzinfo.

4

9 回答 9

249

请注意,对于 Python 3.2 及更高版本,该datetime模块包含datetime.timezone. 的文档datetime.utcnow()说:

可以通过调用来获取当前的 UTC 日期时间。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)
于 2014-07-10T02:43:55.030 回答
235

这意味着它是时区天真的,所以你不能使用它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")))

要获取给定时区的当前时间,您可以将 tzinfodatetime.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 过渡结束时失败。

于 2010-02-25T04:28:53.053 回答
77

在 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()

一旦你有了一个 UTCtzinfo对象,你仍然不能将它与utcnow. 要将当前时间作为感知日期时间对象获取:

from datetime import datetime 

now = datetime.now(utc)

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

from datetime import datetime, timezone 

now = datetime.now(timezone.utc)

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

于 2010-02-25T04:27:46.287 回答
20

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 时区信息。我怀疑这不包括在内,因为本机日期时间库默认为天真的日期时间以实现交叉兼容性。

于 2013-11-07T15:03:14.120 回答
14

timezone在 Python 3.2+ 中添加信息

import datetime

>>> d = datetime.datetime.now(tz=datetime.timezone.utc)
>>> print(d.tzinfo)
'UTC+00:00'
于 2017-09-02T09:42:59.180 回答
11

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

确实,Python datetime API 总是返回不知道的 datetime 对象,这是非常不幸的。确实,一旦您获得其中一个对象,就无法知道时区是什么,因此这些对象本身就非常“无用”。

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

建议:

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

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

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

于 2015-09-08T18:53:36.850 回答
5

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

于 2020-09-16T08:14:43.220 回答
-6
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]
于 2014-07-28T21:29:25.583 回答
-13

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

于 2010-02-25T04:15:54.583 回答