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

datetime.datetime.utcnow() 

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

我期望这将包含tzinfo

这意味着它是时区天真的,所以你不能用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结束转换期间失败。

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

编辑:尽pipe库中没有实现,但在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() 

要使用它,获取当前时间作为一个知道的date时间对象:

 from datetime import datetime now = datetime.now(utc) 

Python 3.2+中有datetime.timezone.utc

 from datetime import datetime, timezone now = datetime.now(timezone.utc) 

请注意,对于Python 3.2以后, datetime模块包含datetime.timezonedatetime.utcnow()的文档说:

可以通过调用datetime.now ( timezone.utc )来获得当前UTCdate时间。

所以你可以这样做:

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

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时区信息。 我怀疑这不包括,因为本地date时间库默认为天真的date时间交叉兼容性。

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

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

唉,即使你可能使用utcnow() ,你仍然不会看到时区信息,因为你发现。

build议:

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

  • 使用ISO 8601作为input和输出string格式。 使用datetime.datetime.isoformat()以时间戳的格式返回时间戳,格式包括时区信息。

  • 如果您需要parsing包含ISO 8601格式化时间戳的string,则可以使用iso8601 ,它会返回具有正确时区信息的时间戳。 这使得时间戳可以直接比较。

 import datetime >>> d = datetime.datetime.now(tz=datetime.timezone.utc) >>> print(d.tzinfo) 'UTC+00:00' 
 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] 

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