datetime.datetime.utcnow()
为什么这个
datetime
没有任何时区信息,明明它是一个明确的UTC datetime
?我本来期望它会包含
tzinfo
。datetime
模块包含datetime.timezone
。datetime.utcnow()
的文档中写道:
通过调用
datetime.now
(
timezone.utc
)
可以获得一个具有意识的当前UTC日期时间。
datetime.utcnow()
不会设置tzinfo
来指示它是UTC时间,但datetime.now(datetime.timezone.utc)
会返回具有设置了tzinfo
的UTC时间。>>> import datetime
>>> datetime.datetime.now(datetime.timezone.utc)
datetime.datetime(2014, 7, 10, 2, 43, 55, 230107, tzinfo=datetime.timezone.utc)
datetime.UTC
,它等同于datetime.timezone.utc
。因此,你也可以使用datetime.datetime.now(datetime.UTC)
。datetime.now(timezone.utc)
还是datetime.utcnow(timezone.utc)
? - Jesse Webbdatetime.utcnow()
不需要参数。所以应该使用 datetime.now(timezone.utc)
。 - Craig McQueendatetime.utcnow()
没有设置tzinfo
来表示它是UTC时间。但是,datetime.now(datetime.timezone.utc)
会返回已设置tzinfo
的UTC时间。 - Craig McQueen这意味着它没有时区信息,因此您不能使用 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")))
它适用于任何时区,包括那些观察夏令时的时区,即适用于可能在不同时间具有不同UTC偏移量(非固定UTC偏移量)的时区。不要使用tz.localize(datetime.now())
,它可能会在本地时间不明确的夏令时结束转换期间失败。
astimezone
中使用某些城市时区,则可能会出现错误。因此,datetime不仅没有本地化的时区,而且唯一广泛可用的tzinfo实现也不符合所谓的标准。 - bobinceu=datetime.utcnow().replace(tzinfo=pytz.utc)
。 - Craig McQueentz.localize(datetime.now())
,而应该使用datetime.now(tz)
。 - jfstzinfo
文档中提供了一个示例。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()
一旦你有了一个UTC的tzinfo
对象,你仍然不能使用它与utcnow
一起使用。为了将当前时间作为明确的datetime对象:
from datetime import datetime
now = datetime.now(utc)
在 Python 3.2 版本中,他们终于在库中加入了一个UTC的tzinfo
类:
from datetime import datetime, timezone
now = datetime.now(timezone.utc)
在Python 3.9中,他们为所有其他时区创建了tzinfo
类。有关详细信息,请参阅PEP 615--支持IANA时区数据库的标准库。
utcnow()
创建的“datetime”对象)?这还真难说...... - André Carontzinfo
文档包括实现它的代码示例,但datetime本身却没有包含这个功能!https://docs.python.org/2/library/datetime.html#datetime.tzinfo.fromutc - Mr. Lance E Sloanpytz
模块的实现完全相同。它添加了一些有用的方法。 - Mr. Lance E Sloanpytz
是一个很好的资源。当我编辑我的答案并加入示例代码时,已经有其他人建议了它,我不想抢他们的风头。 - Mark Ransomutcnow()
被保留不变。 - Smart Manojpytz
模块是一种选择,还有另一个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时区信息。我怀疑这个信息没有被包含是因为本地的datetime库默认使用naive日期时间以实现跨平台兼容性。
utcdt = datetime.datetime.utcfromtimestamp(1234567890).replace(dateutil.tz.tzutc())
- Ian Leedatetime.now(pytz_tz)
不同,datetime.now(dateutil.tz.tzlocal())
可能在 DST 转换期间失败。未来,PEP 495 -- 本地时间消歧 可能会改善 dateutil
的情况。 - jfsutc_dt = datetime.fromtimestamp(1234567890, dateutil.tz.tzutc())
(注意:dateutil
带有非固定UTC偏移量(例如dateutil.tz.tzlocal()
)可能会失败,请改用基于pytz
的解决方案)。 - jfsdateutil.parser
,因此我最喜欢这个解决方案。它非常简单:utcCurrentTime = datetime.datetime.now(tz=dateutil.tz.tzutc())
。哇! - Mr. Lance E Sloan在Python 3.2+中添加时区
信息
import datetime
>>> d = datetime.datetime.now(tz=datetime.timezone.utc)
>>> print(d.tzinfo)
'UTC+00:00'
Python 2.7.13(默认,2017年1月19日,14:48:08) - Marcin Owsianyfrom datetime import datetime, timezone
然后使用 datetime.now(tz=timezone.utc)
调用。 - s2t2Julien Danjou写了一篇很好的文章,解释了为什么你永远不应该处理时区。以下是节选内容:
事实上,Python datetime API总是返回无时区意识(datetime)对象,这非常不幸。确实,一旦你得到这样一个对象,就没有办法知道它所处的时区,因此这些对象本身相当“无用”。
遗憾的是,即使你使用utcnow()
,你仍然看不到时区信息,正如你所发现的那样。
建议:
始终使用带有时区信息的意识清醒的
datetime
对象。这样可以确保您可以直接比较它们(未知和已知时区的datetime
对象不可比较),并将它们正确返回给用户。利用 pytz 来获取时区对象。使用 ISO 8601 作为输入和输出字符串格式。使用
datetime.datetime.isoformat()
将时间戳作为字符串格式化,使用该格式,该格式包括时区信息。如果需要解析包含 ISO 8601 格式的时间戳的字符串,则可以依赖于
iso8601
,它会返回具有正确时区信息的时间戳。这使得时间戳直接可比较。
datetime.datetime.utcnow()
方法返回的UTC时间作为纯日期时间对象显然存在问题,必须进行修复。如果您的系统本地时区不是UTC,则可能会导致意外结果,因为datetime库假定纯日期时间对象代表系统本地时间。例如,datetime.datetime.utcnow().timestamp()
在我的计算机上会比正确值提前4个小时。另外,自Python 3.6起,可以在纯日期时间实例上调用datetime.astimezone()
方法,但是datetime.datetime.utcnow().astimezone(any_timezone)
会给出错误的结果,除非您的系统本地时区是UTC。datetime.datetime.utcnow()
自从它被引入到 Python 中以来,在大多数情况下并没有使用 tz-aware 对象 - 我们只存储和处理 UTC,并且仅在 UI 层面为人类用户进行转换。如果您出于某种原因想要带有 tzinfo 的 UTC,请仅使用具有 tz 支持的现代 datetime 对象。 - cowbert应该包括now()
。相关的问题。
因此,在那之前,now()
优于today()
和utcnow()
。
from datetime import datetime, timezone
utc = timezone.utc
date = datetime.now(utc)
print(date) # 2022-04-06 05:40:13.025347+00:00
date = datetime.now(timezone.utc) # datetime.datetime(2023, 10, 13, 8, 17, 21, 862183, tzinfo=datetime.timezone.utc)
和 date = datetime.utcnow() #datetime.datetime(2023, 10, 13, 8, 17, 35, 668704)
。 - undefinedfrom 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]
UTC日期不需要任何时区信息,因为它们是协调世界时(UTC),根据定义,这意味着它们没有偏移量。
pytz.utc
)。请注意,一个值其与UTC的偏移量未知,与一个已知偏移量为0的值之间存在很大的区别。后者是utcnow()
应该返回的内容,我认为如此。这将符合文档中所述的“意识到对象用于表示特定时刻,该时刻不容解释”。 - Jon Skeet