In the model \'entered\' is a datetime field. I want to query the data to find all entry\'s that where made between noon(start_time) and 5:00pm (end_time).
s
You can use range to filter in between. I found this the best way to filter since SQL does filtering better than Django.
fromRange=datetime.datetime.strptime(request.GET.get('from'),'%Y-%m-%dT%H:%M:%S.%fZ')
toRange=datetime.datetime.strptime(request.GET.get('to'),'%Y-%m-%dT%H:%M:%S.%fZ')
entry = Entry.objects.filter(entryTime__range=(fromRange,toRange))
I suggest filter x<=arg
and exclude x>=arg2
.
I don't believe there's built-in support for this, but you can pass extra where-clause parameters (warning: some possibility of introducing DB-dependent behaviour here).
For example, on Postgres, something like:
Entry.objects.extra(where=['EXTRACT(hour from entered) >= 12 and '\
'EXTRACT(hour from entered) < 17'])
If you're using potentially unsafe input to determine the values 12
and 17
, note that you can also specify a params option to extra that will ensure proper quoting and escaping, and then use the standard sql %s
placeholders in your where statement.
Using SQLite as an example, a relatively clean and generic solution would be:
Entry.objects.extra(where=["time(entered) between '%s' and '%s'"],
params=[start_time.strftime("%H:%M"), end_time.strftime("%H:%M")])
I just figured out a solution for a similar use case – perhaps someone finds this useful:
In my case, I have Availability and Constraint models like so (simplified):
class Availability(...):
start = models.DateTimeField()
end = models.DateTimeField()
class Constraint(...):
from = models.TimeField()
to = models.TimeField()
I wanted to find availabilities that don't violate any constraints.
With Postgres, this worked for me:
Availability.objects.extra(
where=['NOT (start::time, "end"::time) OVERLAPS (\'{0}\'::time, \'{1}\'::time)'.format(
from.strftime("%H:%M"), to.strftime("%H:%M")
)]
)
Note how you can cast DateTime
to Time
(or rather timestamp
to time without timezone
in Postgres terms) with ::time
and then use OVERLAPS
to compare the time ranges.
And in regards to the original question, you can also do:
Availability.objects.extra(
where=['start::time BETWEEN \'{0}\'::time AND \'{1}\'::time AND
"end"::time BETWEEN \'{0}\'::time AND \'{1}\'::time'.format(
from.strftime("%H:%M"), to.strftime("%H:%M")
)]
)
You could filter in python instead using the db's mechanisms:
for e in Entry.objects.all():
if i.entered.hour>= 9 and i.entered.hour < 17 :# or break down to minutes/seconds
list.append(e)
but both solutions are ugly, i think.
Steve, you have to decide, what is less ugly for you: