Python:如何获得“timezone aware”的datetime.today()值?

问题描述 投票:244回答:15

我试图从datetime.today()的值中减去一个日期值来计算多久以前的东西。但它抱怨说:

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

datetime.today()似乎不是“时区感知”,而我的其他日期值是。如何获得时区感知的datetime.today()值?现在它给了我当地时间的时间,恰好是PST,即UTC-8hrs。最坏的情况是,有没有办法我可以手动输入时区值到datetime返回的datetime.today()对象并将其设置为UTC-8?当然,理想的解决方案是让它自动知道时区。

python datetime date timezone
15个回答
315
投票

在标准库中,没有创建自己的时区类的创建感知时区的跨平台方法。

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

使用本地时区可能非常棘手(请参阅下面的“进一步阅读”链接),因此您可能更愿意在整个应用程序中使用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:


3
投票

从Python 3.3开始,您可以使用datetime(作为astimezone)获得一个带有单行的本地时区感知suggested by johnchen902

from datetime import datetime, timezone

aware_local_now = datetime.now(timezone.utc).astimezone()

print(aware_local_now)
2019-08-02 11:26:32.341817-07:00

1
投票

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的noted可能给出错误的结果。


0
投票

如果你在python中获得当前的时间和日期然后导入日期和时间,python包在python之后你将得到当前的日期和时间,如...

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

0
投票

对于时区感知日期时间,使用如下所示的时区,默认为UTC:

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

0
投票

我将此答案添加为经常使用非UTC时区的人。

唯一拥有自己方法的时区是timezone.utc,但如果你需要使用timedeltatimezone,并使用.replace强制它,你可以用任何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'

使用timezone(timedelta(hours=n))作为时区是真正的银弹,它有许多其他有用的应用程序。


-1
投票

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

>>> import pendulum

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

要安装Pendulum并查看其文档,请访问here。它有很多选项(如简单的ISO8601,RFC3339和许多其他格式支持),更好的性能,并倾向于产生更简单的代码。


92
投票

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

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

44
投票

在Python 3中,标准库使得将UTC指定为时区变得更加容易:

>>> import datetime
>>> datetime.datetime.now(datetime.timezone.utc)
datetime.datetime(2016, 8, 26, 14, 34, 34, 74823, tzinfo=datetime.timezone.utc)

如果您想要一个仅使用标准库并且在Python 2和Python 3中都有效的解决方案,请参阅J. F. Sebastien's answer


18
投票

这是一个适用于Python 2和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是一个知道日期时间实例,表示UTC中的一天(午夜)开始,而utc是一个tzinfo对象(example from the docs):

from datetime import tzinfo, timedelta

ZERO = timedelta(0)

class UTC(tzinfo):
    def utcoffset(self, dt):
        return ZERO

    def tzname(self, dt):
        return "UTC"

    def dst(self, dt):
        return ZERO

utc = UTC()

相关:several ways to get midnight (start of a day) for a given UTC time的性能比较。 注意:对get midnight for a time zone with a non-fixed utc offset来说更复杂。


13
投票

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

import datetime
import pytz

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

9
投票

如果您使用的是Django,则可以将日期设置为非tz(仅限utc)。

在settings.py中注释以下行:

USE_TZ = True

6
投票

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

使用stdlib,这是不可能的。

SO上查看类似的问题。


6
投票

以下是使用stdlib生成它的一种方法:

import time
from datetime import datetime

FORMAT='%Y-%m-%dT%H:%M:%S%z'
date=datetime.strptime(time.strftime(FORMAT, time.localtime()),FORMAT)

date将存储本地日期和UTC的偏移量,而不是UTC时区的日期,因此如果需要确定生成日期的时区,则可以使用此解决方案。在此示例中和我当地时区:

date
datetime.datetime(2017, 8, 1, 12, 15, 44, tzinfo=datetime.timezone(datetime.timedelta(0, 7200)))

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

关键是将%z指令添加到表示FORMAT,以指示生成的时间结构的UTC偏移量。其他表示格式可以在datetime模块docs中查阅

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

date=datetime.strptime(time.strftime(FORMAT, time.gmtime()),FORMAT)

date    
datetime.datetime(2017, 8, 1, 10, 23, 51, tzinfo=datetime.timezone.utc)

date.tzname()
'UTC'

编辑

这仅适用于python3。 z指令在python 2 _strptime.py code上不可用


5
投票

为什么不使用这里描述的dateutil:http://joelinoff.com/blog/?p=802

from dateutil.tz import tzlocal
# Get the current date/time with the timezone.
now = datetime.datetime.now(tzlocal())
© www.soinside.com 2019 - 2024. All rights reserved.