[英]Can't compare naive and 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() 识别语言环境日期时间?
默认情况下, datetime
对象在 Python 中是naive
的,因此您需要使它们都成为幼稚或感知的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.datetime 对象中格式化 UNIX 时间戳,如下所示
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为此提供了一个助手,这需要pytz
from django.utils import timezone
now = timezone.now()
您now
应该能够与challenge.datetime_start
进行比较
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()
日期时间。
但是,您必须添加与引用变量相同的时区; 这就是我首先阅读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.now()
它将返回系统当前时间,没有设置 tzinfo。
tzinfo 是附加到日期时间的信息,以使其知道它所在的时区。如果您使用天真的日期时间,您需要在整个系统中保持一致。 我强烈建议只使用datetime.utcnow()
看到您正在创建的日期时间与 tzinfo 相关联,您需要做的是确保将它们本地化(与 tzinfo 相关联)到正确的时区。
看看Delorean ,它使处理此类事情变得更加容易。
这是我的工作。 在这里,我正在创建表创建的日期时间并在日期时间上添加 10 分钟。 稍后根据当前时间,到期操作完成。
from datetime import datetime, time, timedelta
import pytz
在数据库日期时间上添加了 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 ")
它对我有用。
您正在尝试为已有时区的 date_time 设置时区。 使用replace
和astimezone
函数。
local_tz = pytz.timezone('Asia/Kolkata')
current_time = datetime.now().replace(tzinfo=pytz.utc).astimezone(local_tz)
没有第三方,只有本机日期时间模块。
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那么您可以将其与时区信息一起存储。 这将允许您将该日期时间与时区感知日期时间进行比较。 SQLAlchemy core
中的示例列定义:
Column("created_at", DateTime(timezone=True), nullable=False)
只是:
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_time
和end_time
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.