Python Forum

Full Version: time range midnight problem
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
The following code determines if the current time is between two times and it works well until midnight is in the range of times. Not sure how to make it allow for that case.

Pointers?

        tm= datetime.datetime.now()
                now_time = tm.time()
                
                # The next line is a test for a range that crosses midnight
                now_time = datetime.time(23,56)

                strthr = 23
                strtmin = 55
                stphr = 0
                stpmin = 5

                if now_time >= datetime.time(strthr,strtmin) and now_time <= datetime.time(stphr,stpmin):
                    print("in the range")
                else:
                    print("not in the range")
Possible solution: if you encompass midnight then stop<start. So swap start and end and check that the time is not in the interval.
That seems to work just fine.  Good idea!
Here is the code that now works before, after, and encompassing midnight.

Thank you

                tm= datetime.datetime.now()
                now_time = tm.time()
                
                # The next few lines are a test for a range that crosses midnight
                #now_time = datetime.time(23,54) # should fail
                #now_time = datetime.time(23,55) # should passs
                #now_time = datetime.time(0,4) # should fail
                #now_time = datetime.time(0,3) # should pass

                starthr = 23 # befot=re midnight
                startmin = 55
                stophr = 0 # after midnight
                stopmin = 3
                
                if stophr >= starthr:
                    if now_time >= datetime.time(starthr, startmin) and now_time <= datetime.time(stophr,stopmin):
                        print("in the range")
                else:
                    if now_time <= datetime.time(stophr,stopmin) or now_time >= datetime.time(starthr, startmin):
                        print("in the range")    
                    else:
                        print("not in the range")
You could also change this line:

if now_time >= datetime.time(strthr,strtmin) and now_time <= datetime.time(stphr,stpmin):
to this:

if datetime.time(strthr, strtmin, strtsec) <= now_time or datetime.time(stphr, stpmin,stpsec) >= now_time:
btw, i added a strtsec and stpsec and the seconds parameter to the datetime.time(), just cuz I was bored  Smile
Couldn't you also combine them into a single comparison?
if datetime.time(strthr, strtmin) <= now_time <= datetime.time(stphr, stpmin):
Similar to how this works:
>>> x = 5
>>> 4 < x < 10
True
Okay, after the last comment, I combined the if statements and I also turned this into a function so here's what it looks like now. I have not yet tested it fully, but it looks right.
    def onrange(self, starthr, startmin, stophr, stopmin):
        tm= datetime.datetime.now()
        now_time = tm.time()
        #now_time = datetime.time(hour=0, minute=2)
        
        if stophr >= starthr:
            if datetime.time(starthr, startmin) <= now_time <= datetime.time(stophr, stopmin):
                # return True
                print("yes")  
            else:
                # return False
                print("no")
        else:
            if datetime.time(starthr, startmin) >= now_time >= datetime.time(stophr, stopmin):
                # return True
                print("yes")
            else:
                # return False
                print("no")
Almost all of that function looks the same, except it's there twice.  The only difference is in one spot you have >, and in another <.

How about...
# if stophr is BEFORE the starthr, swap all values, so starthr is always the smaller value
if stophr < starthr:
   starthr, startmin, stophr, stopmin = stophr, stopmin, starthr, startmin

if datetime.time(starthr, startmin) <= now_time <= datetime.time(stophr, stopmin):
   return True
return False

#...that's it.  you've saved yourself 3 lines, and it's easier to make changes/understand
Modulo method:
(time-start) % 24 < (stop-start) % 24
For instance on a 12-hour clock:
Output:
# from 2 to 10: >>> [(x-2)%12 < (10-2)%12 for x in range(12)] [False, False, True, True, True, True, True, True, True, True, False, False] # from 10 to 2: >>> [(x-10)%12 < (2-10)%12 for x in range(12)] [True, True, False, False, False, False, False, False, False, False, True, True]
I have only been using python for about two weeks.  I didn't understand the last couple posts and the line below is a mystery to me.

 [(x-2)%12 < (10-2)%12 for x in range(12)]
The code I have been testing didn't handle midnight in the range well so I took a different approach. I turned the time into integers (hours * 60 + minutes) so I could use simple integer comparisons.  Midnight is handled by simply adding 24 hours to now and stop. This seems to work.
# determine if the curren time in within a given time range (24 hour clock)
def inrange(self, starthour, startmin, stophour, stopmin):
    # Set the now time to an integer that is hours * 60 + minutes
    n = datetime.datetime.now()
    now = n.hour * 60 + n.minute 
    
    # Set the start time to an integer that is hours * 60 + minutes
    str = datetime.time(starthour, startmin)
    start = str.hour * 60 + str.minute 
    
    # Set the stop time to an integer that is hours * 60 + minutes
    stp = datetime.time(stophour, stopmin)
    stop = stp.hour * 60 + stp.minute

    # handle midnight by adding 24 hours to stop time and now time
    if stop < start:
        stop += 1440
        now += 1440 
    #see if we are in the range
    if start <= now < stop:
        return True
    return False
(Dec-14-2016, 07:45 PM)PickyBiker Wrote: [ -> ]I have only been using python for about two weeks.  I didn't understand the last couple posts and the line below is a mystery to me.

 [(x-2)%12 < (10-2)%12 for x in range(12)

This is a  'comprehension'. It generates an array that contains the result of (x-2)%12 < (10-2)%12 for all values of x in range(12)