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

Vit*_*biy 251 python datetime

datetime.datetime.utcnow()
Run Code Online (Sandbox Code Playgroud)

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

我希望这会包含tzinfo.

Joh*_*ooy 177

这意味着它是时区天真,所以你不能使用它 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
Run Code Online (Sandbox Code Playgroud)

现在你可以改变时区了

print(u.astimezone(pytz.timezone("America/New_York")))
Run Code Online (Sandbox Code Playgroud)

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

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

print(datetime.now(pytz.timezone("America/New_York")))
Run Code Online (Sandbox Code Playgroud)

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

  • 但是没有充分的理由让它成为时区 - 它被指定为UTC.为什么需要搜索第三方库以使其正常工作? (186认同)
  • 怎么样只是'u = datetime.now(pytz.utc)` (13认同)
  • @bobince为什么pytz和标准的datetime库不适合你呢?Python核心和pytz作为独立项目发展,降低了核心团队的后勤复杂性.是的,降低Python核心团队的复杂性会增加所有需要处理时区的Python用户的复杂性,但我相信他们做出这个决定是有充分理由的.规则"标准库没有tzinfo实例......"很棒,因为它很简单,为什么在这里例外? (5认同)
  • @bain:不要使用`tz.localize(datetime.now())`; 使用`datetime.now(tz)`代替. (4认同)
  • 我同意; 对我来说,'天真'时代是完全没用的.关于将pytz添加到stdlib的python列表的讨论; 问题不是许可,而是时区数据经常更新的事实(Python本身不可能).此外,pytz没有以预期的方式实现tzinfo接口,因此如果您尝试在`astimezone`中使用某些城市时区,则可能会出错.因此,datetime不仅没有本机时区,而且tzinfo唯一广泛可用的实现不符合所谓的标准. (3认同)
  • 在 3.9+ python 中添加了 [ZoneInfo](https://docs.python.org/3/library/zoneinfo.html) 类,该类可以用作 `ZoneInfo('America/Denver')` 并且不使用第三方库。请注意,如果操作系统没有可用的区域文件,它将从 pypi 回退到“tzdata”(您需要安装它)。请参阅 [PEP615](https://www.python.org/dev/peps/pep-0615/) (2认同)

Cra*_*een 111

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

通过调用可以获得知道的当前UTC日期时间.datetime.now(timezone.utc)

所以你可以这样做:

>>> import datetime
>>> datetime.datetime.now(datetime.timezone.utc)
datetime.datetime(2014, 7, 10, 2, 43, 55, 230107, tzinfo=datetime.timezone.utc)
Run Code Online (Sandbox Code Playgroud)

  • @Babu:`datetime.utcnow()`没有设置`tzinfo`来表示它是UTC.但是`datetime.now(datetime.timezone.utc)`确实返回UTC时间*并设置了*`tzinfo`. (7认同)
  • `datetime.utcnow()`不带参数.所以它必须是`datetime.now(timezone.utc)`. (4认同)
  • 我认为现在这是正确的解决方案,当时区元数据已经明确为 UTC 时,不需要添加外部依赖项来指定时区元数据 (3认同)
  • 没有回答问题 - 为什么它不包含时区信息? (3认同)
  • 哪个更受欢迎?`datetime.now(timezone.utc)` 或 `datetime.utcnow(timezone.utc)`? (2认同)
  • 注意,从 Python 3.12 开始,[`datetime.utcnow()`](https://docs.python.org/3/library/datetime.html#datetime.datetime.utcnow) 已被弃用,取而代之的是 `datetime.now (时区.utc)` (2认同)

Mar*_*som 69

标准Python库不包含任何tzinfo类(但请参阅pep 431).我只能猜测原因.就个人而言,我认为不包括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()
Run Code Online (Sandbox Code Playgroud)

要使用它,要将当前时间作为识别日期时间对象:

from datetime import datetime 

now = datetime.now(utc)
Run Code Online (Sandbox Code Playgroud)

datetime.timezone.utc在Python 3.2+:

from datetime import datetime, timezone 

now = datetime.now(timezone.utc)
Run Code Online (Sandbox Code Playgroud)

  • 时区对象`timezone.utc`最终被添加到Python 3.2中.为了向后兼容,`utcnow()`仍然返回一个没有时区的时间对象,但你可以通过调用`now(timezone.utc)`得到你想要的东西. (15认同)
  • 去看看为什么这个类没有首先提供(更重要的是,用于`utcnow()`创建的`datetime`对象)... (8认同)
  • @rgove,这就是错误的纠正,这对于Python 3来说应该是公平的游戏.他们不应该担心向后兼容性.我在最近几天读到的另一个例子是`struct`模块将自动从Unicode转换为bytestring,最后的决定是破坏与早期Python 3版本的兼容性,以防止未来的错误决定. (4认同)
  • 我很傻,Python的tzinfo文档中包含实现该示例的代码示例,但它们在日期时间本身中并未包含该功能!https://docs.python.org/2/library/datetime.html#datetime.tzinfo.fromutc (2认同)

bbe*_*ort 19

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())
Run Code Online (Sandbox Code Playgroud)

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


Joe*_*rea 10

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

实际上,Python datetime API总是返回不知道的日期时间对象,这是非常不幸的.实际上,只要你得到这个对象中的一个,就无法知道时区是什么,因此这些对象本身就非常"无用".

唉,即使你可能会使用utcnow(),你仍然不会看到你所发现的时区信息.

建议:

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

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

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

  • 这有点误导性的建议。经验法则是,永远不要处理时区。始终存储和传输 tz unware utc 对象(纪元对象)。时区应仅在 UI 中表示时计算 (2认同)
  • 如果所有日期时间数学都是在 UTC 中完成的,那么 TZ 不知道的对象就不是问题。您应该以 UTC 格式存储和处理所有日期时间,并且仅在需要时(即在 UI 层)将日期时间值转换为特定的 TZ。 (2认同)

小智 7

timezone在Python 3.2+中添加信息

import datetime

>>> d = datetime.datetime.now(tz=datetime.timezone.utc)
>>> print(d.tzinfo)
'UTC+00:00'
Run Code Online (Sandbox Code Playgroud)


Han*_*hin 5

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