无法比较幼稚和知道的datetime.now()<= Challenge.datetime_end


154

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

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?



2
可能的重复项无法减去未
过时的

1
有一个很好的lib可以和日期一起玩:摆锤(我不隶属于)
Thomas Decaux

Answers:


137

默认情况下,该datetime对象naive位于Python中,因此您需要将它们都设为天真或感知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

注意:这将引发一个ValueErrorif tzinfo值。如果您不确定,请使用

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)

它说:ValueError:尝试计算时不是幼稚的datetime(已经设置了tzinfo):datetimeStart = utc.localize(challenge.datetime_start)
sccrthlt 2013年

是的,它引发ValueError。
Dmitrii Mikhailov

4
替换tzinfo不会进行任何转换,从而使比较不正确。
OrangeDog

为此+1。并且,utc = pytz.utc用于防止pylint错误No value for argument 'dt' in unbound method call (no-value-for-parameter)pytz链接
SAM

90

datetime.datetime.now 不了解时区。

Django为此提供了一个帮助程序,它需要 pytz

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

你应该能够比较nowchallenge.datetime_start


3
如果USE_TZ=True这样,timezone.now()即使pytz未安装,也会返回一个时区感知的日期时间对象(尽管出于其他原因,建议安装)。
jfs

49

一行代码解决方案

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属性的原因。


18

禁用时区。用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):

2

因此,我要解决此问题的方法是确保两个日期时间在正确的时区中。

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

tzinfo是附加在日期时间上的信息,以使其知道它所在的时区。如果使用的是朴素的日期时间,则需要在整个系统中保持一致。我强烈建议只使用datetime.utcnow()

看到您正在创建与tzinfo相关联的日期时间,您需要做的是确保将它们本地化(与tzinfo相关联)到正确的时区。

看一下Delorean,它使处理这种事情变得更加容易。


8
您还可以通过utcnow看到此问题。
安迪·海登

0

这是我的工作。在这里,我对创建的日期时间的表进行geet,并在日期时间上添加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 ")

它为我工作。


0

只是:

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.