如何在Python中获得datetime.today()的值,即;时区感知“;?

如何在Python中获得datetime.today()的值,即;时区感知“;?,python,datetime,date,timezone,Python,Datetime,Date,Timezone,我正在尝试从datetime.datetime.today()的值中减去一个日期值,以计算某物的存在时间。但它抱怨说: TypeError: can't subtract offset-naive and offset-aware datetimes 值datetime.datetime.today()似乎不是“时区感知”,而我的另一个日期值是。如何获取时区感知的datetime.datetime.today()值 现在,它给了我当地时间的时间,正好是太平洋标准时间,即UTC-8小时。最糟糕的

我正在尝试从
datetime.datetime.today()的值中减去一个日期值,以计算某物的存在时间。但它抱怨说:

TypeError: can't subtract offset-naive and offset-aware datetimes
datetime.datetime.today()
似乎不是“时区感知”,而我的另一个日期值是。如何获取时区感知的
datetime.datetime.today()

现在,它给了我当地时间的时间,正好是太平洋标准时间,即UTC-8小时。最糟糕的情况是,有没有办法手动将时区值输入到
datetime.datetime.today()返回的
datetime
对象中,并将其设置为UTC-8

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

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

对于stdlib,这是不可能的


请参见标准库中的类似问题。

在不创建自己的时区类的情况下,没有跨平台的方法来创建感知时区

在Windows上,有
win32timezone.utcnow()
,但这是pywin32的一部分。我更愿意建议使用,它有一个不断更新的大多数时区数据库

使用本地时区可能非常棘手(请参阅下面的“进一步阅读”链接),因此您可能更希望在整个应用程序中使用UTC,尤其是在计算两个时间点之间的差值等算术运算中

您可以按如下方式获取当前日期/时间:

import pytz
from datetime import datetime
datetime.utcnow().replace(tzinfo=pytz.utc)
请注意
datetime.today()
datetime.now()
返回本地时间,而不是UTC时间,因此对它们应用
.replace(tzinfo=pytz.UTC)
是不正确的

另一个很好的方法是:

datetime.now(pytz.utc)
它稍微短一点,并且做同样的事情


进一步阅读/观察在许多情况下选择UTC的原因:

  • –许多实际用例的开发提示
  • –关于时区工作复杂性的有趣、令人大开眼界的解释(视频)

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

import datetime
import pytz

pytz.utc.localize( datetime.datetime.utcnow() )  
您可以通过运行以下命令从PyPI安装:

$ pipenv install pytz

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

import datetime
import pytz
my_date = datetime.datetime.now(pytz.timezone('US/Pacific'))
date
datetime.datetime(2017, 8, 1, 12, 15, 44, tzinfo=datetime.timezone(datetime.timedelta(0, 7200)))

date.tzname()
'UTC+02:00'

请记住先安装。

如果您使用的是Django,则可以设置不支持tz的日期(仅限)

注释settings.py中的以下行:

USE_TZ = True

下面是一个适用于Python 2和Python 3的stdlib解决方案:

from datetime import datetime

now = datetime.now(utc) # Timezone-aware datetime.utcnow()
today = datetime(now.year, now.month, now.day, tzinfo=utc) # Midnight
其中,
today
是一个aware datetime实例,以UTC表示一天的开始(午夜),而
UTC
是一个tzinfo对象():

相关:性能比较。
注意:使用dateutil更为复杂,如中所述:


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.Sebastian所说,这可能会给出错误的结果。

这里有一种使用stdlib生成它的方法:

import time
from datetime import datetime

FORMAT='%Y-%m-%dT%H:%M:%S%z'
date=datetime.strptime(time.strftime(FORMAT, time.localtime()),FORMAT)
日期将存储本地日期和与UTC的偏移量,而不是UTC时区的日期,因此,如果需要确定日期在哪个时区生成,可以使用此解决方案。在本例和我的本地时区中:

import datetime
import pytz
my_date = datetime.datetime.now(pytz.timezone('US/Pacific'))
date
datetime.datetime(2017, 8, 1, 12, 15, 44, tzinfo=datetime.timezone(datetime.timedelta(0, 7200)))

date.tzname()
'UTC+02:00'
关键是将
%z
指令添加到表示格式中,以指示生成的时间结构的UTC偏移量。可以在datetime模块中查阅其他表示格式

如果需要UTC时区的日期,可以将time.localtime()替换为time.gmtime()

编辑

这仅适用于python3。z指令在python 3.2+中的python 2上不可用:
datetime.timezone.utc
: 通过标准库,可以更轻松地将UTC指定为时区:

>>> import datetime
>>> datetime.datetime.now(datetime.timezone.utc)
datetime.datetime(2020, 11, 27, 14, 34, 34, 74823, tzinfo=datetime.timezone.utc)
您还可以使用以下方法获取包含本地时间偏移的日期时间:

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

如果您想要一个只使用标准库且同时适用于Python 2和Python 3的解决方案,请参阅

在Python 3.9+中:
zoneinfo
要使用IANA时区数据库: 在Python 3.9中,可以使用标准库指定特定时区,如下所示:

>>> 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包(如果可用)获取其时区数据库。

如果在python中获取当前时间和日期,则在获取当前日期和时间后,导入日期和时间,pytz包(在python中),如下所示

from datetime import datetime
import pytz
import time
str(datetime.strftime(datetime.now(pytz.utc),"%Y-%m-%d %H:%M:%S%t"))

仅使用标准库的一行程序从Python 3.3开始就可以工作。您可以使用(as)获取本地时区感知的
datetime
对象:


在我看来,另一个更好的选择是使用
钟摆
而不是
pytz
。考虑下面的简单代码:

>>> import pendulum

>>> dt = pendulum.now().to_iso8601_string()
>>> print (dt)
2018-03-27T13:59:49+03:00
>>>

要安装钟摆并查看其文档,请转到。它有大量的选项(如简单的ISO8601、RFC3339和许多其他格式支持)、更好的性能和更简单的代码

使用如下所示的时区作为时区感知日期时间。默认值为UTC:

from django.utils import timezone
today = timezone.now()

特别是对于非UTC时区:

唯一有自己方法的时区是
timezone.utc
,但如果需要,您可以使用
timedelta
&
timezone
,强制使用
。替换
,以任意utc偏移量伪造时区

In [1]: from datetime import datetime, timezone, timedelta

In [2]: def force_timezone(dt, utc_offset=0):
   ...:     return dt.replace(tzinfo=timezone(timedelta(hours=utc_offset)))
   ...:

In [3]: dt = datetime(2011,8,15,8,15,12,0)

In [4]: str(dt)
Out[4]: '2011-08-15 08:15:12'

In [5]: str(force_timezone(dt, -8))
Out[5]: '2011-08-15 08:15:12-08:00'
使用
时区(timedelta(hours=n))
因为时区是这里真正的银弹,并且
>>> import pendulum

>>> dt = pendulum.now().to_iso8601_string()
>>> print (dt)
2018-03-27T13:59:49+03:00
>>>
from django.utils import timezone
today = timezone.now()
In [1]: from datetime import datetime, timezone, timedelta

In [2]: def force_timezone(dt, utc_offset=0):
   ...:     return dt.replace(tzinfo=timezone(timedelta(hours=utc_offset)))
   ...:

In [3]: dt = datetime(2011,8,15,8,15,12,0)

In [4]: str(dt)
Out[4]: '2011-08-15 08:15:12'

In [5]: str(force_timezone(dt, -8))
Out[5]: '2011-08-15 08:15:12-08:00'
from pytz import timezone

datetime.now(timezone('Europe/Berlin'))
datetime.now(timezone('Europe/Berlin')).today()
import pytz

pytz.all_timezones
pytz.common_timezones # or
.replace(tzinfo=pytz.utc)
import pytz
import datetime from datetime

date = datetime.now().replace(tzinfo=pytz.utc)
>>> from pnp_datetime.pnp_datetime import Pnp_Datetime
>>>
>>> Pnp_Datetime.utcnow()
datetime.datetime(2020, 6, 5, 12, 26, 18, 958779, tzinfo=<UTC>)
import datetime

datetime.datetime(2010, 12, 25, 10, 59).astimezone()
# e.g.
# datetime.datetime(2010, 12, 25, 10, 59, tzinfo=datetime.timezone(datetime.timedelta(seconds=3600), 'Mitteleuropäische Zeit'))

datetime.datetime(2010, 12, 25, 12, 59).astimezone().isoformat()
# e.g.
# '2010-12-25T12:59:00+01:00'

# I'm on CET/CEST
today = datetime.utcnow()