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


284
datetime.datetime.utcnow()

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

我希望这将包含tzinfo


如何将字符串类型的正常iso格式日期字段转换为utc格式?
Navi

Answers:


192

这意味着它是时区幼稚的,所以您不能将其与 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结束过渡期间可能会失败。


216
但是,没有充分的理由使它成为时区幼稚的东西-它被指定为UTC。为什么需要搜索第三方库以使其正常运行?
马克·兰瑟姆

4
我同意; 对我来说,“幼稚”的时代是完全没有用的。目前,关于在python列表上进行有关将pytz添加到stdlib的讨论;问题不是许可,而是时区数据更新得如此频繁(Python本身不能这样)的事实。另外pytz并未以预期的方式实现tzinfo接口,因此,如果您尝试使用中的某些城市时区,可能会出错astimezone。因此datetime不仅没有本地时区,而且tzinfo唯一可广泛使用的实现不符合假定的标准。
bobince 2010年

5
@bobince为什么pytz和标准datetime库对您不起作用?作为独立项目发展的Python核心和pytz降低了核心团队的后勤复杂性。是的,降低Python核心团队的复杂性会增加所有需要处理时区的Python用户的复杂性,但是,我相信他们有充分的理由做出这一决定。规则“标准库没有tzinfo实例...”之所以很棒,是因为它很简单,为什么在这里例外?
德里克·里兹

15
怎么样u=datetime.now(pytz.utc)
Craig McQueen 2014年

4
@bain:不要使用tz.localize(datetime.now());使用datetime.now(tz)代替。
jfs

142

请注意,对于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)

2
哪个更喜欢?datetime.now(timezone.utc)还是datetime.utcnow(timezone.utc)
Jesse Webb 2014年

8
datetime.utcnow()不带任何参数。因此必须如此datetime.now(timezone.utc)
Craig McQueen 2014年

1
datetime.now()将返回机器时间,但datetime.utcnow()将返回实际UTC时间。
巴布(Babu)2013年

13
@Babu:datetime.utcnow()未设置tzinfo为表明它是UTC。但datetime.now(datetime.timezone.utc)不会返回UTC时间 tzinfo设定。
Craig McQueen

@CraigMcQueen那么,如果我们tz在now构造函数中传递一个对象,它将返回该时区的时间?好!感谢您指出。
巴布(Babu)2013年

71

标准的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()

要使用它,以将当前时间作为已知的datetime对象获取:

from datetime import datetime 

now = datetime.now(utc)

datetime.timezone.utc在Python 3.2+:

from datetime import datetime, timezone 

now = datetime.now(timezone.utc)

8
去图,为什么在第一个地方是没有提供这个类(和,更重要的是,用于datetime通过创建的对象utcnow())...
安德烈·卡伦

17
时区对象timezone.utc最终已添加到Python 3.2中。为了向后兼容,utcnow()仍返回一个无时区的时间对象,但是您可以通过调用来获得所需的内容now(timezone.utc)
mhsmith 2013年

4
@rgove,这是对错误的纠正,对于Python 3来说应该是公平的游戏。他们不应该担心向后兼容性。最近几天我读了另一个例子-该struct模块将自动从Unicode转换为字节串,最终决定是破坏与早期Python 3版本的兼容性,以防止继续做出错误决定。
Mark Ransom 2013年

2
我很傻,Python的tzinfo文档中包含实现它的代码示例,但是它们没有在日期时间本身中包含该功能! docs.python.org/2/library/datetime.html#datetime.tzinfo.fromutc
LS

1
@LS是的,pytz是很棒的资源。当我编辑完答案以放入示例代码时,其他人已经提出了建议,而我不想窃取他们的意见。
Mark Ransom

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


1
NameError:未定义名称'
dt'– xApple

我正在使用datetime.datetime.utcfromtimestamp()调用,并且需要添加tzinfo,第二个解决方案对我有用: utcdt = datetime.datetime.utcfromtimestamp(1234567890).replace(dateutil.tz.tzutc())
Ian Lee

1
注意:与以往不同的datetime.now(pytz_tz)是,它总是有效的;datetime.now(dateutil.tz.tzlocal())在DST转换可能会失败PEP 495-本地时间消歧可能会改善dateutil未来的状况。
jfs 2015年

@IanLee:你可以使用utc_dt = datetime.fromtimestamp(1234567890, dateutil.tz.tzutc())(注:dateutil与非固定的UTC偏移量(如dateutil.tz.tzlocal())可能无法在这里使用一个pytz基于解决方案来代替)。
jfs 2015年

由于我的程序已经进口dateutildateutil.parser,我喜欢这个解决方案最好。它是那样简单:utcCurrentTime = datetime.datetime.now(tz=dateutil.tz.tzutc())。中提琴!
LS 2016年

11

朱利安•丹乔(Julien Danjou)写了一篇很好的文章,解释了为什么永远不要处理时区。摘录:

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

las,即使您可以使用utcnow(),也仍然看不到时区信息,就像您发现的那样。

建议:

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

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

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


1
这是有点误导性的建议。经验法则是,永远不要处理时区。始终存储和传输未经保护的utc对象(时期对象)。时区只能在用户界面中表示时进行计算
nehem

1
听起来已经很符合Julien的想法了。他的哪些具体建议(如上所述)具有误导性?
Joe D'Andrea

10

timezone在Python 3.2+中添加信息

import datetime

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

1
AttributeError: 'module' object has no attribute 'timezone' Python 2.7.13(默认值,2017年1月19日,14:48:08)
Marcin Owsiany

-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]

-13

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


10
据我从docs.python.org/library/datetime.html所知道的,没有tzinfo的日期时间是未指定时区的日期时间。这里的时间段已经被指定,因此在逻辑上应该存在。没有相关联时区的日期/时间与UTC中肯定存在的日期/时间之间存在很大差异。(理想情况下,它们应该是IMO的不同类型,但这是另一回事...)
Jon Skeet 2010年

@JonSkeet我想您会错过Ignacio所说的UTC不是时区的观点。令人惊讶的是,当我输入此答案时,答案为-9 ...
CS

3
@CS:好吧,伊格纳西奥(Ignacio)从来没有说过……虽然严格地说,UTC不是时区,但通常视为使生活变得更加简单的时区(包括Python中的,例如pytz.utc)。请注意,与UTC的偏移量未知的值与已知为0的值之间存在很大差异。后者utcnow() 返回IMO。根据文档,这将与“一个有意识的对象用于表示一个无法解释的特定时间”相对应。
乔恩·斯基特
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.