Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find objects with date and time less then 24 hours from now

I have model with two fields:

class Event(models.Model):
    date = models.DateField(_(u'Date'))
    time = models.TimeField(_(u'Time'))

I need to find all objects where date&time is in 24 hours from now.

I am able to do this when using DateTime field, but I am not sure how to achieve this when fields are separated. Thanks in advance.

like image 529
dease Avatar asked Jun 01 '15 13:06

dease


3 Answers

For the simple case (not sure if all are simple cases though...), this should do the trick:

import datetime

today = datetime.datetime.now()
tomorrow = today + datetime.timedelta(days=1)

qs_today = queryset.filter(
    date=today.date(),
    time__gte=today.time(),
)
qs_tomorrow = queryset.filter(
    date=tomorrow.date(),
    time__lt=tomorrow.time(),
)
qs = qs_today | qs_tomorrow
like image 184
Wolph Avatar answered Nov 10 '22 02:11

Wolph


As you state you can do what you want with a DateTimeField, but now with the separate fields, I understand your issue is how to combine them.

Looking at the docs for DateField - your date variable is a datetime.date instance and similarly for TimeField time is a datetime.time. You can convert these into a datetime.datetime by using combine()

import datetime as dt
datetime = dt.datetime.combine(date,time)

You now have the datetime object as you would have from DateTimeField. You say in the question you can do the 24 hour from now bit from there, although let me know in comments if you need that made explicit.

Caveat I combine will fail where one of the fields is None - you state this can't happen, so I haven't added any error checking or validation of this.

EDIT

It occurs to me that the problem may not be the combination, but adding the calculated field to the Event object. You could look at this Q&A, or this. In summary you define the calculated value in a function in your class and then make it a property - either with a decorator or a function call. There's an example in the docs, adapting for your case:

    def _get_datetime(self):
       '''Returns a combination of date and time as a datetime'''
       return dt.datetime.combine(self.date,self.time)
    datetime = property(_get_datetime)

This should behave in the same way as you would expect a DateTimeField to behave.

like image 36
J Richard Snape Avatar answered Nov 10 '22 02:11

J Richard Snape


You can use Q objects to search for "yesterday after current time or today before current time":

from django.db.models import Q
from .models import Event
from datetime import datetime, timedelta

def get_event_during_last_day():
    now = datetime.now()
    today = now.date()
    yesterday = (now - timedelta(day=1)).date()
    time = now.time()

    query_yesterday = Q(date=yesterday, time__gt=time)
    query_today = Q(date=today, time__lt=time)

    return Event.objects.filter(query_yesterday | query_today)
like image 5
301_Moved_Permanently Avatar answered Nov 10 '22 02:11

301_Moved_Permanently