2

I have a model with 2 datetime fields which looks like this:

class Booking(models.Model):
    start_date = models.DateTimeField()
    end_date = models.DateTimeField()
    ...

As test data I have 2 bookings with start_date before 17:30 and 2 bookings after 17:45, all on the same day (8 May 2018). I am trying to filter the bookings with the __time lookup to find all the bookings before (and including) 17:30. My queryset is:

bookings = Booking.objects.filter(date__time__lte=datetime.time())

Where datetime.time prints as

datetime.time(17, 30)

and where the date part of the datetime is the same as the bookings dates. The above query is returning an empty queryset but if I use the same query except filtering for times greater than datetime.time() i.e.

bookings = Booking.objects.filter(date__time__gte=datetime.time())

The queryset returns all the bookings (where it should only return the 2 bookings with start_date after 17:30). Can someone please explain to me how the __time lookup is meant to be used?

EDIT I updated the filter to

bookings = Booking.objects.filter(start_date__time__lte=datetime.time())

and the result is the same. When I print the values of the bookings, the values are:

print Booking.objects.all().values('date', 'end_date')
[
    {'start_date': datetime.datetime(2018, 5, 8, 16, 30, tzinfo=<DstTzInfo 'Africa/Harare' CAT+2:00:00 STD>), 'end_date': datetime.datetime(2018, 5, 8, 17, 0, tzinfo=<DstTzInfo 'Africa/Harare' CAT+2:00:00 STD>)},
    {'start_date': datetime.datetime(2018, 5, 8, 17, 0, tzinfo=<DstTzInfo 'Africa/Harare' CAT+2:00:00 STD>), 'end_date': datetime.datetime(2018, 5, 8, 17, 30, tzinfo=<DstTzInfo 'Africa/Harare' CAT+2:00:00 STD>)}, 
    {'start_date': datetime.datetime(2018, 5, 8, 17, 45, tzinfo=<DstTzInfo 'Africa/Harare' CAT+2:00:00 STD>), 'end_date': datetime.datetime(2018, 5, 8, 18, 15, tzinfo=<DstTzInfo 'Africa/Harare' CAT+2:00:00 STD>)}, 
    {'start_date': datetime.datetime(2018, 5, 8, 17, 45, tzinfo=<DstTzInfo 'Africa/Harare' CAT+2:00:00 STD>), 'end_date': datetime.datetime(2018, 5, 8, 18, 15, tzinfo=<DstTzInfo 'Africa/Harare' CAT+2:00:00 STD>)}
]

EDIT 2 I forgot to mention I need to get the bookings that are on the same date. As siddhant0905 suggested I filtered the queryset with datetimes instead and added an extra filter to make sure it was on the same date. The following worked for me:

bookings = Booking.objects.filter(Q(start_date__date=datetime.date()) & Q(start_date__lte=datetime))
Jcraine
  • 23
  • 5
  • In your `filter` you use `date`, but you specified `start_date` and `end_date`? – Willem Van Onsem May 23 '18 at 15:24
  • Perhaps it would be useful to show what values you filled it (i.e. `Booking.objects.all().values_list('begin_date', 'end_date')`). – Willem Van Onsem May 23 '18 at 15:25
  • @WillemVanOnsem I updated the query to filter the correct field but the result is still the same. I will update the post to include the values printed – Jcraine May 23 '18 at 15:30
  • @willem I also only want to filter the start date for now, and the end date for a later use case but the filtering for both of them will be similar, I just need to get it working for the start date first. – Jcraine May 23 '18 at 15:42
  • Can't this be a timezone issue? What if you add the timezone to your data? – Willem Van Onsem May 23 '18 at 15:43
  • @willem adding the timezone returns the same results for me. I am doing so with pytz: datetime = pytz.timezone(settings.TIME_ZONE).localize(start_datetime) – Jcraine May 23 '18 at 15:59

1 Answers1

1

I think you should compare the complete datetime object rather than just comparing the time part. Debug the 'Type' of the time that the query returns and the type of time you are providing it to compare with. Both should be same. Django shell can be of great help.

  • While this could be the issue, could you provide example code showing how this could be done? – vielkind May 23 '18 at 15:44
  • Yes I agree, django shell is awesome when it comes to debugging and testing code. I did print the types and both the query objects and time I am providing are datetime.time() instances. – Jcraine May 23 '18 at 15:46
  • I think @siddhant0905 is right, you should try the whole `datetime`, not only the `time` – Lemayzeur May 23 '18 at 15:49
  • It does work when using the whole datetime. Since this works for my use case I'm going to mark this answer as correct, however I am still confused as to why the __time filter does not work the same way. – Jcraine May 23 '18 at 15:52
  • hey @Jcraine since you find this answer correct so your upvote would be highly appreciated. – siddhant0905 May 23 '18 at 15:52