我试图从datetime.today()
的值中减去一个日期值来计算多久以前的东西。但它抱怨说:
TypeError: can't subtract offset-naive and offset-aware datetimes
值datetime.today()
似乎不是“时区感知”,而我的其他日期值是。如何获得时区感知的datetime.today()
值?现在它给了我当地时间的时间,恰好是PST,即UTC-8hrs。最坏的情况是,有没有办法我可以手动输入时区值到datetime
返回的datetime.today()
对象并将其设置为UTC-8?当然,理想的解决方案是让它自动知道时区。
在标准库中,没有创建自己的时区类的创建感知时区的跨平台方法。
在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:
从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
在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可能给出错误的结果。
如果你在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"))
对于时区感知日期时间,使用如下所示的时区,默认为UTC:
from django.utils import timezone
today = timezone.now()
我将此答案添加为经常使用非UTC时区的人。
唯一拥有自己方法的时区是timezone.utc
,但如果你需要使用timedelta
和timezone
,并使用.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))
作为时区是真正的银弹,它有许多其他有用的应用程序。
另一种选择,在我看来是一个更好的选择,是使用Pendulum
而不是pytz
。请考虑以下简单代码:
>>> import pendulum
>>> dt = pendulum.now().to_iso8601_string()
>>> print (dt)
2018-03-27T13:59:49+03:00
>>>
要安装Pendulum并查看其文档,请访问here。它有很多选项(如简单的ISO8601,RFC3339和许多其他格式支持),更好的性能,并倾向于产生更简单的代码。
获取特定时区的当前时间:
import datetime
import pytz
my_date = datetime.datetime.now(pytz.timezone('US/Pacific'))
在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。
这是一个适用于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来说更复杂。
另一种构造表示当前时间的时区感知日期时间对象的方法:
import datetime
import pytz
pytz.utc.localize( datetime.datetime.utcnow() )
如果您使用的是Django,则可以将日期设置为非tz(仅限utc)。
在settings.py中注释以下行:
USE_TZ = True
以下是使用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上不可用
为什么不使用这里描述的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())