不能比较naive和aware datetime.now() <= challenge.datetime_end

我试图比较当前日期和时间与使用比较运算符在模型中指定的日期和时间:

if challenge.datetime_start <= datetime.now() <= challenge.datetime_end:

脚本错误如下:

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

模型是这样的:

class Fundraising_Challenge(models.Model):
name = models.CharField(max_length=100)
datetime_start = models.DateTimeField()
datetime_end = models.DateTimeField()

我也有django使用区域日期和时间。

我还没有找到的是django使用DateTimeField()的格式。是天真还是有意识?我如何得到datetime.now()识别区域日期时间?

331170 次浏览

默认情况下,datetime对象在Python中是naive,所以你需要使它们都是naive或aware datetime对象。这可以使用:

import datetime
import pytz


utc=pytz.UTC


challenge.datetime_start = utc.localize(challenge.datetime_start)
challenge.datetime_end = utc.localize(challenge.datetime_end)
# now both the datetime objects are aware, and you can compare them

注意:如果已经设置了tzinfo,则会引发ValueError。如果你不确定,那就用

start_time = challenge.datetime_start.replace(tzinfo=utc)
end_time = challenge.datetime_end.replace(tzinfo=utc)

顺便说一下,您可以在datetime中格式化UNIX时间戳。带有时区信息的Datetime对象,如下所示

d = datetime.datetime.utcfromtimestamp(int(unix_timestamp))
d_with_tz = datetime.datetime(
year=d.year,
month=d.month,
day=d.day,
hour=d.hour,
minute=d.minute,
second=d.second,
tzinfo=pytz.UTC)

datetime.datetime.now不是时区感知的。

Django提供了一个helper,它需要pytz

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

你应该能够比较nowchallenge.datetime_start

所以我解决这个问题的方法是确保两个日期时间在正确的时区。

我可以看到你正在使用datetime.now(),它将返回系统当前时间,没有tzinfo设置。

Tzinfo是附加到datetime上的信息,用于让它知道自己所在的时区。如果使用naive datetime,则需要在整个系统中保持一致。我强烈建议只使用datetime.utcnow()

当你在某个地方创建有tzinfo关联的datetime时,你需要做的是确保这些被本地化(有tzinfo关联)到正确的时区。

看看,它让处理这类事情变得更容易。

一行代码解决方案

if timezone_aware_var <= datetime.datetime.now(timezone_aware_var.tzinfo):
pass #some code

解释的版本

# Timezone info of your timezone aware variable
timezone = your_timezone_aware_variable.tzinfo


# Current datetime for the timezone of your variable
now_in_timezone = datetime.datetime.now(timezone)


# Now you can do a fair comparison, both datetime variables have the same time zone
if your_timezone_aware_variable <= now_in_timezone:
pass #some code

总结

你必须将时区信息添加到你的now() datetime中 但是,必须添加引用变量的相同时区;这就是为什么我首先读取tzinfo属性

禁用时区。 使用challenge.datetime_start.replace(tzinfo=None);

你也可以将replace(tzinfo=None)用于其他datetime

if challenge.datetime_start.replace(tzinfo=None) <= datetime.now().replace(tzinfo=None) <= challenge.datetime_end.replace(tzinfo=None):
它在我身上起作用。 在这里,我正在获取创建datetime的表,并在datetime上添加10分钟。

.

.

.

.
from datetime import datetime, time, timedelta
import pytz

在数据库datetime上增加了10分钟

Table_datetime = '2019-06-13 07:49:02.832969'(示例)

# Added 10 minutes on database datetime
# table_datetime = '2019-06-13 07:49:02.832969' (example)


table_expire_datetime = table_datetime + timedelta(minutes=10 )


# Current datetime
current_datetime = datetime.now()




# replace the timezone in both time
expired_on = table_expire_datetime.replace(tzinfo=utc)
checked_on = current_datetime.replace(tzinfo=utc)




if expired_on < checked_on:
print("Time Crossed)
else:
print("Time not crossed ")

这对我很管用。

只是:

dt = datetimeObject.strftime(format) # format = your datetime format ex) '%Y %d %m'
dt = datetime.datetime.strptime(dt,format)

所以这样做:

start_time = challenge.datetime_start.strftime('%Y %d %m %H %M %S')
start_time = datetime.datetime.strptime(start_time,'%Y %d %m %H %M %S')


end_time = challenge.datetime_end.strftime('%Y %d %m %H %M %S')
end_time = datetime.datetime.strptime(end_time,'%Y %d %m %H %M %S')

然后使用start_timeend_time

您正在尝试为date_time设置时区,该date_time已经有一个时区。 使用replaceastimezone函数

local_tz = pytz.timezone('Asia/Kolkata')


current_time = datetime.now().replace(tzinfo=pytz.utc).astimezone(local_tz)

没有第三方,只有本地datetime模块。

from datetime import datetime, timedelta, timezone


time1 = datetime.strptime('2021-07-15T00:22:02+0000', '%Y-%m-%dT%H:%M:%S%z')
time2 = datetime(2021, 7, 15, tzinfo=timezone(offset=timedelta()))
if time1 < time2:
print(True)

如果你正在使用SQLAlchemy并存储DateTime,那么你可以将它与时区信息一起存储。这将允许您将该DateTime与时区感知的DateTimes进行比较。SQLAlchemy core中的列定义示例:

Column("created_at", DateTime(timezone=True), nullable=False)

如果你使用的是Python 3.6及更新版本,你可以利用本机datetime功能。

utc_date = datetime.datetime.fromtimestamp(0, datetime.timezone.utc)