问题:为什么datetime.datetime.utcnow()不包含时区信息?
datetime.datetime.utcnow()
datetime
鉴于它明确是UTC,为什么没有任何时区信息datetime
?
我希望这将包含tzinfo
。
datetime.datetime.utcnow()
Why does this datetime
not have any timezone info given that it is explicitly a UTC datetime
?
I would expect that this would contain tzinfo
.
回答 0
这意味着它是时区幼稚的,所以您不能将其与 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结束过渡期间可能会失败。
That means it is timezone naive, so you can’t use it with datetime.astimezone
you can give it a timezone like this
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
now you can change timezones
print(u.astimezone(pytz.timezone("America/New_York")))
To get the current time in a given timezone, you could pass tzinfo to datetime.now()
directly:
#!/usr/bin/env python
from datetime import datetime
import pytz # $ pip install pytz
print(datetime.now(pytz.timezone("America/New_York")))
It works for any timezone including those that observe daylight saving time (DST) i.e., it works for timezones that may have different utc offsets at different times (non-fixed utc offset). Don’t use tz.localize(datetime.now())
— it may fail during end-of-DST transition when the local time is ambiguous.
回答 1
Note that for Python 3.2 onwards, the datetime
module contains datetime.timezone
. The documentation for datetime.utcnow()
says:
An aware current UTC datetime can be obtained by calling datetime.now
(
timezone.utc
)
.
So, datetime.utcnow()
doesn’t set tzinfo
to indicate that it is UTC, but datetime.now(datetime.timezone.utc)
does return UTC time with tzinfo
set.
So you can do:
>>> import datetime
>>> datetime.datetime.now(datetime.timezone.utc)
datetime.datetime(2014, 7, 10, 2, 43, 55, 230107, tzinfo=datetime.timezone.utc)
回答 2
标准的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)
The standard Python libraries don’t include any tzinfo classes (but see pep 431). I can only guess at the reasons. Personally I think it was a mistake not to include a tzinfo class for UTC, because that one is uncontroversial enough to have a standard implementation.
Edit: Although there’s no implementation in the library, there is one given as an example in the 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()
To use it, to get the current time as an aware datetime object:
from datetime import datetime
now = datetime.now(utc)
There is datetime.timezone.utc
in Python 3.2+:
from datetime import datetime, timezone
now = datetime.now(timezone.utc)
回答 3
该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时区信息。我怀疑这不包括在内,因为本机日期时间库默认为天真日期时间以实现交叉兼容性。
The pytz
module is one option, and there is another python-dateutil
, which although is also third party package, may already be available depending on your other dependencies and operating system.
I just wanted to include this methodology for reference- if you’ve already installed python-dateutil
for other purposes, you can use its tzinfo
instead of duplicating with 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())
I tend to agree that calls to utcnow
should include the UTC timezone information. I suspect that this is not included because the native datetime library defaults to naive datetimes for cross compatibility.
回答 4
朱利安•丹乔(Julien Danjou)写了一篇很好的文章,解释了为什么永远不要处理时区。摘录:
确实,Python datetime API总是返回不知道的datetime对象,这是非常不幸的。确实,一旦您获得此对象之一,就无法知道时区是什么,因此,这些对象本身就非常“无用”。
las,即使您可以使用utcnow()
,也仍然看不到时区信息,就像您发现的那样。
建议:
始终使用感知datetime
对象,即带有时区信息。这样可以确保您可以直接比较它们(感知datetime
对象和未感知对象是不可比较的),并将它们正确返回给用户。利用pytz具有时区对象。
使用ISO 8601作为输入和输出字符串格式。用于datetime.datetime.isoformat()
将时间戳返回为使用该格式格式化的字符串,其中包括时区信息。
如果您需要解析包含ISO 8601格式的时间戳记的字符串,则可以依靠iso8601
,它返回带有正确时区信息的时间戳记。这使得时间戳直接可比。
Julien Danjou wrote a good article explaining why you should never deal with timezones. An excerpt:
Indeed, Python datetime API always returns unaware datetime objects,
which is very unfortunate. Indeed, as soon as you get one of this
object, there is no way to know what the timezone is, therefore these
objects are pretty “useless” on their own.
Alas, even though you may use utcnow()
, you still won’t see the timezone info, as you discovered.
Recommendations:
Always use aware datetime
objects, i.e. with timezone information. That
makes sure you can compare them directly (aware and unaware datetime
objects are not comparable) and will return them correctly to users.
Leverage pytz to have timezone objects.
Use ISO 8601 as the input and
output string format. Use datetime.datetime.isoformat()
to return
timestamps as string formatted using that format, which includes the
timezone information.
If you need to parse strings containing ISO 8601 formatted timestamps,
you can rely on iso8601
, which returns timestamps with correct
timezone information. This makes timestamps directly comparable.
回答 5
timezone
在Python 3.2+中添加信息
import datetime
>>> d = datetime.datetime.now(tz=datetime.timezone.utc)
>>> print(d.tzinfo)
'UTC+00:00'
To add timezone
information in Python 3.2+
import datetime
>>> d = datetime.datetime.now(tz=datetime.timezone.utc)
>>> print(d.tzinfo)
'UTC+00:00'
回答 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]
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]
回答 7
由于UTC日期是UTC,因此不需要任何时区信息,根据定义,这意味着它们没有偏移量。
UTC dates don’t need any timezone info since they’re UTC, which by definition means that they have no offset.