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

时间:2010-02-25 04:14:00

标签: python datetime

datetime.datetime.utcnow()

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

我希望这会包含tzinfo

9 个答案:

答案 0 :(得分:167)

这意味着它是时区,因此您无法将其与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过渡期间失败。

答案 1 :(得分:96)

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

  

可以通过致电datetime.now ( timezone.utc )来获取当前的UTC日期时间。

所以你可以这样做:

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

答案 2 :(得分:66)

标准Python库不包含任何tzinfo类(但see pep 431)。我只能猜测原因。就个人而言,我认为不包括UTC的tzinfo类是错误的,因为那个版本对于标准实现来说是没有争议的。

编辑虽然库中没有实现,但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()

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

from datetime import datetime 

now = datetime.now(utc)

Python 3.2 +中有datetime.timezone.utc

from datetime import datetime, timezone 

now = datetime.now(timezone.utc)

答案 3 :(得分: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())

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

答案 4 :(得分:9)

朱利安丹茹写了一篇很好的文章解释why you should never deal with timezones。摘录:

  

实际上,Python datetime API总是会返回不知道的日期时间对象,   这是非常不幸的。的确,只要你得到其中一个   对象,没有办法知道时区是什么,因此这些   对象本身非常“无用”。

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

建议:

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

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

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

  •   

答案 5 :(得分:3)

在Python 3.2 +

中添加timezone信息
import datetime

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

答案 6 :(得分:0)

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

答案 7 :(得分:-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]

答案 8 :(得分:-13)

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