WayBehind
WayBehind

Reputation: 1697

Django After Midnight Business Hours TimeField Comparison Error

I have a Business Hours that I need to compare and I'm getting incomplete results if the business hours are past midnight

My Model

class Hours(models.Model):
  dayofweek = models.ForeignKey('Dayofweek')
  opentime = models.TimeField(blank=True, null=True)
  closetime = models.TimeField(blank=True, null=True)
  ...

If I just need to display hours everything works OK such: Saturday 5pm - 2am

Now when I'm trying to query the hours to check if the business is even open, those with past midnight hours will return False for exists():

my query

if Hours.objects.filter(
            business__id=id,
            dayofweek__pyday=dt, 
            opentime__lte=mytime, 
            closetime__gte=mytime).exists():
    #do something

Any suggestions how to tell Django that the 2am is after 5pm?

Upvotes: 6

Views: 1058

Answers (3)

BjornW
BjornW

Reputation: 226

(Q(daily_starts_at__lte=F('daily_ends_at')) &
 Q(daily_starts_at__lte=now_time, daily_ends_at__gte=now_time)) |   
(Q(daily_starts_at__gt=F('daily_ends_at')) &
 (Q(daily_starts_at__lte=now_time) | Q(daily_ends_at__gte=now_time))

This is how I solved the same case, use this in your filter() clause (and replace my daily_starts/ends_at with your names and now_time with now().time() or something). The logic is like in the other answers here, the comparison has to be different depending on if the range crosses midnight.

You also need to & with a Q() clause containing your other filter parameters.

Upvotes: 0

Pynchia
Pynchia

Reputation: 11606

What about using F and Q expressions through two queries:

one for the simple case (opening time <= closing time)

Hours.objects.filter(
         opentime__lte=F('closetime'),
         business__id=id,
         dayofweek__pyday=dt, 
         opentime__lte=mytime, 
         closetime__gte=mytime).exists():

and one for the odd case (closing time < opening time)

Hours.objects.filter(
         opentime__gt=F('closetime'),
         business__id=id,
         dayofweek__pyday=dt, 
         Q(opentime__lte=mytime) | Q(closetime__gte=mytime)).exists():

Upvotes: 2

Dr.Knowitall
Dr.Knowitall

Reputation: 10508

A day can have multiple periods, but no matter what, the day ends at 11:59 PM. If that extends into the next day, you have to break up your time intervals. So the logic of your filters will be like so...

# Spans over 2 days
if opentime > closetime:
  Hours.objects.filter(
    business_id=id,
    dayofweek_pyday=dt,
    opentime_tye=myOpenTime,
    closetime_gte=11:59:99
  ).exists() ||
  Hours.objects.filter(
    business_id=id,
    # Next date
    dayofweek_pyday=dt + 1,
    opentime_tye=00:00:00,
    closetime_gte=myCloseTime
  ).exists()
# Spans over 1 day
else:
   Hours.objects.filter(
   business__id=id,
   dayofweek__pyday=dt, 
   opentime__lte=myOpentime, 
   closetime__gte=myClosetime).exists()

I don't know django so this is just some pseudo code and an alternative approach I would use.

Upvotes: 2

Related Questions