我试图从datetime.datetime.today()的值中减去一个日期值,以计算多长时间以前的事情。但它抱怨道:

TypeError: can't subtract offset-naive and offset-aware datetimes

datetime.datetime.today()的返回值似乎不是“时区感知”,而我的其他日期值是。我如何从datetime.datetime.today()得到一个时区感知的返回值?

理想的解决方案是让它自动知道时区。

现在,它给我的时间是当地时间,恰好是PST,即UTC - 8小时。最坏的情况下,是否有一种方法我可以手动输入一个时区值到datetime.datetime.today()返回的datetime对象,并将其设置为UTC-8?


当前回答

在Python 3.2+中:datetime. zone.utc:

标准库使得将UTC指定为时区变得更加容易:

>>> import datetime
>>> datetime.datetime.now(datetime.timezone.utc)
datetime.datetime(2020, 11, 27, 14, 34, 34, 74823, tzinfo=datetime.timezone.utc)

你也可以使用astimezone获取一个包含本地时间偏移量的datetime:

>>> datetime.datetime.now(datetime.timezone.utc).astimezone()
datetime.datetime(2020, 11, 27, 15, 34, 34, 74823, tzinfo=datetime.timezone(datetime.timedelta(seconds=3600), 'CET'))

(在Python 3.6+中,您可以将最后一行缩短为:datetime.datetime.now().astimezone()))

如果你想要一个只使用标准库并且在Python 2和Python 3中都能工作的解决方案,请参阅jfs的答案。

在Python 3.9+中:zoneinfo使用IANA时区数据库:

在Python 3.9中,你可以使用标准库使用zoneinfo指定特定的时区,如下所示:

>>> from zoneinfo import ZoneInfo
>>> datetime.datetime.now(ZoneInfo("America/Los_Angeles"))
datetime.datetime(2020, 11, 27, 6, 34, 34, 74823, tzinfo=zoneinfo.ZoneInfo(key='America/Los_Angeles'))

zoneinfo从操作系统获取时区数据库,或者从第一方PyPI包tzdata(如果可用的话)获取时区数据库。

其他回答

获取特定时区的当前时间:

import datetime
import pytz
my_date = datetime.datetime.now(pytz.timezone('US/Pacific'))

记得先安装pytz。

在utc时区中获取一个支持时区的日期就足以让日期减法工作了。

但是如果你想要一个当前时区的时区感知日期,tzlocal是最好的方法:

from tzlocal import get_localzone  # pip install tzlocal
from datetime import datetime
datetime.now(get_localzone())

PS dateutil具有类似的函数(dateutil.tz.tzlocal)。但是尽管共享名称,但它有一个完全不同的代码库,正如J.F.塞巴斯蒂安所指出的那样,这可能会给出错误的结果。

另一种构造表示当前时间的时区感知datetime对象的方法:

import datetime
import pytz

pytz.utc.localize( datetime.datetime.utcnow() )  

你可以通过以下命令从PyPI安装pytz:

$ pipenv install pytz

pytz是一个Python库,允许使用Python 2.3或更高版本进行精确的跨平台时区计算。

对于stdlib,这是不可能的。

在SO上可以看到类似的问题。

在Python 3.2+中:datetime. zone.utc:

标准库使得将UTC指定为时区变得更加容易:

>>> import datetime
>>> datetime.datetime.now(datetime.timezone.utc)
datetime.datetime(2020, 11, 27, 14, 34, 34, 74823, tzinfo=datetime.timezone.utc)

你也可以使用astimezone获取一个包含本地时间偏移量的datetime:

>>> datetime.datetime.now(datetime.timezone.utc).astimezone()
datetime.datetime(2020, 11, 27, 15, 34, 34, 74823, tzinfo=datetime.timezone(datetime.timedelta(seconds=3600), 'CET'))

(在Python 3.6+中,您可以将最后一行缩短为:datetime.datetime.now().astimezone()))

如果你想要一个只使用标准库并且在Python 2和Python 3中都能工作的解决方案,请参阅jfs的答案。

在Python 3.9+中:zoneinfo使用IANA时区数据库:

在Python 3.9中,你可以使用标准库使用zoneinfo指定特定的时区,如下所示:

>>> from zoneinfo import ZoneInfo
>>> datetime.datetime.now(ZoneInfo("America/Los_Angeles"))
datetime.datetime(2020, 11, 27, 6, 34, 34, 74823, tzinfo=zoneinfo.ZoneInfo(key='America/Los_Angeles'))

zoneinfo从操作系统获取时区数据库,或者从第一方PyPI包tzdata(如果可用的话)获取时区数据库。