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

Python 为什么datetime.datetime.utcnow()不包含时区信息?,python,datetime,Python,Datetime,为什么这个datetime没有任何时区信息,因为它是UTCdatetime 我希望这将包含tzinfoUTC日期不需要任何时区信息,因为它们是UTC,根据定义,这意味着它们没有偏移量。标准Python库不包括任何tzinfo类(但是)。我只能猜测原因。就我个人而言,我认为不包括UTC的tzinfo类是一个错误,因为该类没有足够的争议性,可以有一个标准的实现 编辑:虽然库中没有实现,但在中给出了一个示例 要使用它,请将当前时间作为aware datetime对象获取: from datetime

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


我希望这将包含
tzinfo

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

标准Python库不包括任何tzinfo类(但是)。我只能猜测原因。就我个人而言,我认为不包括UTC的tzinfo类是一个错误,因为该类没有足够的争议性,可以有一个标准的实现

编辑:虽然库中没有实现,但在中给出了一个示例

要使用它,请将当前时间作为aware datetime对象获取:

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()
Python 3.2+中有
datetime.timezone.utc

from datetime import datetime 

now = datetime.now(utc)

这意味着它是时区的幼稚,因此您不能将它与
datetime.astimezone

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

from datetime import datetime, timezone 

now = datetime.now(timezone.utc)
现在你可以改变时区了

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
要获取给定时区中的当前时间,可以直接将tzinfo传递给
datetime.now()

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

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

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

我只是想将此方法作为参考—如果您已经为其他目的安装了
python dateutil
,那么您可以使用它的
tzinfo
,而不是使用
pytz

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

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

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

注意,对于Python3.2以后的版本,模块包含。文件说明:

可通过调用
获取当前UTC日期时间

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

因此,您可以:

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

朱利安·丹茹写了一篇很好的文章解释。摘录:

实际上,Python datetime API总是返回不知道的datetime对象, 这是非常不幸的。事实上,只要你得到一个 对象,无法知道时区是什么,因此 对象本身是相当“无用”的

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

建议:

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

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

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


在Python 3.2中添加
时区
信息+

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]

datetime.datetime.utcnow()。如果系统本地时区不是UTC,则可能会导致意外结果,因为datetime库假定原始datetime对象表示系统本地时间。例如,
datetime.datetime.utcnow().timestaamp()
给出的时间戳比我的计算机上的正确值提前4小时。另外,在python 3.6中,
datetime.astimezone()
可以在朴素的datetime实例上调用,但是
datetime.datetime.utcnow().astimezone(任意时区)
会给出错误的结果,除非您的系统本地时区是UTC。

但是没有充分的理由认为它是朴素的时区-它被指定为UTC。为什么你需要寻找一个第三方图书馆,使其正常工作?我同意;对我来说,“天真”的时光是完全无用的。目前在python列表中有关于将pytz添加到stdlib的讨论;问题不在于许可,而在于时区数据更新如此频繁(Python本身无法做到这一点)。此外,pytz没有以预期的方式实现tzinfo接口,因此如果您试图在
astimezone
中使用某些城市时区,则可能会出现错误。所以datetime不仅没有本机时区,而且tzinfo唯一广泛使用的实现也不符合假定的标准。@bobince为什么pytz和标准datetime库不能为您工作?Python核心和pytz作为独立项目的发展降低了核心团队的后勤复杂性。是的,降低Python核心团队的复杂性会增加所有需要处理时区的Python用户的复杂性,但是,我相信他们做出这个决定是有充分理由的。“标准库没有tzinfo实例…”这条规则很好,因为它很简单,为什么要在这里破例呢?只使用
u=datetime.now(pytz.utc)
@bain:不要使用
tz.localize(datetime.now())
;使用
datetime.now(tz)>>> import datetime
>>> datetime.datetime.now(datetime.timezone.utc)
datetime.datetime(2014, 7, 10, 2, 43, 55, 230107, tzinfo=datetime.timezone.utc)
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]
import datetime

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