How do I determine if current time is within a specified range using Python's datetime module?
Asked Answered
A

10

76

What would be the best way to see if the current time lies between say 10:30 AM and 4:30 PM.

I could think of the following, not sure how correct:

from datetime import datetime
nw = datetime.now()
hrs = nw.hour;mins = nw.minute;secs = nw.second;
zero = timedelta(seconds = secs+mins*60+hrs*3600)
st = nw - zero # this take me to 0 hours. 
time1 = st + timedelta(seconds=10*3600+30*60) # this gives 10:30 AM
time2 = st + timedelta(seconds=16*3600+30*60)  # this gives 4:30 PM
if nw>= time1 or nw <= time2:
    print "yes, within the interval"

Please let me know if this the correct approach, can something better be written?

Andra answered 6/4, 2012 at 19:24 Comment(1)
timedelta() allows you to specify days, hours and minutes too, so you don't have to calculate it and the code is more readable.Bruges
C
128

My original answer focused very specifically on the question as posed and didn't accommodate time ranges that span midnight. As this is still the accepted answer 6 years later, I've incorporated @rouble's answer below that expanded on mine to support midnight.

from datetime import datetime, time

def is_time_between(begin_time, end_time, check_time=None):
    # If check time is not given, default to current UTC time
    check_time = check_time or datetime.utcnow().time()
    if begin_time < end_time:
        return check_time >= begin_time and check_time <= end_time
    else: # crosses midnight
        return check_time >= begin_time or check_time <= end_time

# Original test case from OP
is_time_between(time(10,30), time(16,30))

# Test case when range crosses midnight
is_time_between(time(22,0), time(4,00))

I still stick to my original comment below that most applications of this logic would probably be better suited with datetime objects where crossing midnight is reflected as a date change anyway.

Copenhagen answered 6/4, 2012 at 19:28 Comment(13)
Should also work with: if time(10,30) <= now.time() <= time(16,30):.Blancmange
An extension : how do i make these comparisons for the date. say today is 12th march. so how do i check if a given date is 12th march?Andra
@user993563: Check out the datetime doc, and in particular datetime.date.Blancmange
But what if you're trying to check if a time is in between 10 pm and 4 am? :-)Unarmed
Ha, yes this answer gives a very specific solution to the problem presented. For your problem, you have to account for crossing midnight. An easy solution would be to use datetime objects instead of time objects so the comparisons are date sensitive as well.Copenhagen
@rouble's solution is more general. This solution only works if start_time < end_time, which is not true if your period starts before midnight of the day before. (e.g. night starts at 11PM and ends at 5AM, and `11PM > 5AM)Woollyheaded
@JoeHolloway, how do you reference a time range including 12AM midnight? i.e. 18,00 to 24:00 but that throws an error.Downe
@Downe midnight is time(0), not time(24)Copenhagen
@JoeHolloway, I am facing an issue, for eg: I have a model in Django which has from_time and to_time. Consider a case an entry already exists for from_time:6:00 am and end_time:10:00 am. Now, if someone tries creating for start_time = 8:00am and end_time = 9:00 am. It should throw error. Can you please help me with it? #61523409Inflorescence
@JoeHolloway It doesn't work if the start_time is 7AM and end_time is 7AM and the current time is 5 AM. It gives True instead of FalsePolacre
@Polacre Whether that's right or wrong depends on your definition of the range 7AM to 7AM. This example treats it as a 24h range that crosses midnight, not a 0h range. If you want the latter, you can change "if begin_time < end_time" to "if begin_time <= end_time". If you need to optionally support either case and let the caller decide, then you'll need another parameter to the function that tells you which conditional to use.Copenhagen
Possible to set the timezone to GMT+1?Bott
@Bott If I follow your question, the function itself doesn't really care about timezones as long as the caller is consistent. The decision to default the check_time arg to UTC was arbitrary. If you want it to default to local time, you could set check_time = datetime.now().time() instead of letting it default to datetime.utcnow().time(). If that's not what you're asking, you probably need to open a new question as it's likely out of scope here since time zone conversion is a complex topic on its own.Copenhagen
A
69

The above accepted solution does not work with overnight times, this does:

import datetime as dt  
def isNowInTimePeriod(startTime, endTime, nowTime): 
    if startTime < endTime: 
        return nowTime >= startTime and nowTime <= endTime 
    else: 
        #Over midnight: 
        return nowTime >= startTime or nowTime <= endTime 

#normal example: 
isNowInTimePeriod(dt.time(13,45), dt.time(21,30), dt.datetime.now().time())

#over midnight example: 
isNowInTimePeriod(dt.time(20,30), dt.time(1,30), dt.datetime.now().time())
Amaranth answered 8/8, 2016 at 19:16 Comment(4)
Great solution. Note that startTime, endTime and nowTime are time objects, you can access the time part of a datetime object with datetime.time()Plutonic
How is everyone missing this!Dicephalous
@Amaranth It doesn't work if the start_time is 7AM and end_time is 7AM and the current time is 5 AM. It gives True instead of FalsePolacre
Python code evolves so quickly over minor version updates, that the python3 code that worked fine a year ago no longer works now, and it takes years for the 120+ most upvoted answer to be brought to bottom of the page where it belongs as (both depreciated and broken)Mismate
D
15

here's little example for @rouble's answer:

from datetime import datetime

def isNowInTimePeriod(startTime, endTime, nowTime):
    if startTime < endTime:
        return nowTime >= startTime and nowTime <= endTime
    else: #Over midnight
        return nowTime >= startTime or nowTime <= endTime


timeStart = '3:00PM'
timeEnd = '11:00AM'
timeNow = '2:59AM'
timeEnd = datetime.strptime(timeEnd, "%I:%M%p")
timeStart = datetime.strptime(timeStart, "%I:%M%p")
timeNow = datetime.strptime(timeNow, "%I:%M%p")

print(isNowInTimePeriod(timeStart, timeEnd, timeNow))
Disarming answered 24/1, 2017 at 9:33 Comment(0)
P
8

My 2 cent, it works for me and it is easy

while True:
    now = datetime.now()
    current_time = now.strftime("%H:%M:%S")
    start = '19:19:00'
    end = '19:19:20'
    if current_time > start and current_time < end:
        print('in')
        print(current_time)
        tempo.sleep(1)
    else:
        print('out')
        print(current_time)
Pelagic answered 6/12, 2019 at 15:2 Comment(0)
E
1

I had a similar requirement where I wanted a certain task to run on every weekday between 9 AM and 3:30 PM.

def somefunction():
    cdate = datetime.datetime.strftime(datetime.datetime.now(), "%d-%m-%Y")
    if (0 <= time.localtime().tm_wday <= 4) and (datetime.datetime.strptime(cdate + " 09:00:00", "%d-%m-%Y %H:%M:%S") <= datetime.datetime.now() <= datetime.datetime.strptime(cdate + " 15:30:00", "%d-%m-%Y %H:%M:%S")):
         << do something >>

explanation:

cdate variable gets current date in string format.

The condition checks if the current week day is >= 0 (Monday) and <= 4(Friday). It also checks if the current time in datetime format is >= 9:00 AM on today's date and if current time is <= 15:30 on today's date.

Evolution answered 17/4, 2020 at 19:2 Comment(0)
E
1

A solution that may be closer to OP's request than the selected answer. It uses datetime rather than time as the object to check against. It also uses a duration rather than a time to specify the end of the interval.

from datetime import datetime, time, timedelta

def is_date_within(begin_time, span_time, check_date=None):
    """                                                                                        
    Return True if given check_date is within the interval begining                            
    at begin_time with a duration of span_time.                                                
                                                                                               
    Args:                                                                                      
       - begin_time: datetime.time object                                                      
       - span_time: datetime.timedelta object                                                  
       - check_date: datetime.datetime object.                                                 
           If None, default to current UTC date                                                
    """
    check_date = check_date or datetime.utcnow()
    if check_date.time() >= begin_time:
        begin_date = check_date.combine(check_date.date(), begin_time)
    else:
        begin_date = check_date.combine(check_date.date() - timedelta(days=1),
                                        begin_time)
    return begin_date <= check_date <= begin_date + span_time

test_date = datetime(2020, 6, 22, 11, 31)
assert(is_date_within(time(10,30), timedelta(hours=4), test_date) == True)
assert(is_date_within(time(10,30), timedelta(hours=1), test_date) == False)

# Span midnight                                                                                
assert(is_date_within(time(23,30), timedelta(hours=13), test_date) == True)
assert(is_date_within(time(23,30), timedelta(hours=1), test_date) == False)
Etna answered 23/6, 2020 at 3:31 Comment(0)
H
0

Take a look in py-time-between package: https://pypi.org/project/py-time-between/

Test cases:

from datetime import time
from timebetween import is_time_between


def test_is_time_between():
    t, s, e = time(0), time(0), time(0)
    assert is_time_between(t, s, e)

    t, s, e = time(0, 0, 0, 1), time(0), time(0, 0, 0, 2)
    assert is_time_between(t, s, e)

    t, s, e = time(0, 0, 0, 1), time(0, 0, 0, 1), time(0, 0, 0, 2)
    assert is_time_between(t, s, e)

    t, s, e = time(0, 0, 0, 2), time(0, 0, 0, 1), time(0, 0, 0, 2)
    assert is_time_between(t, s, e)

    t, s, e = time(0, 0, 1), time(23, 59, 59), time(0, 0, 2)
    assert is_time_between(t, s, e)

    t, s, e = time(12, 0, 0), time(23, 59, 59), time(0, 0, 0)
    assert is_time_between(t, s, e)

    t, s, e = time(23, 59, 57), time(23, 59, 59), time(23, 59, 57)
    assert is_time_between(t, s, e)

    t, s, e = time(23, 59, 58), time(23, 59, 59), time(23, 59, 57)
    assert not is_time_between(t, s, e)

    t, s, e = time(22), time(22), time(5, 59, 59)
    assert is_time_between(t, s, e)
Havana answered 8/9, 2018 at 14:4 Comment(0)
B
0

Can be simplified further:

def isNowInTimePeriod(startTime, endTime, nowTime):
    if startTime < endTime:
        return startTime <= nowTime <= endTime
    else: #Over midnight
        return nowTime >= startTime or nowTime <= endTime
Badtempered answered 24/9, 2019 at 7:45 Comment(0)
I
0
import datetime
# if your start-end range is within a day  || example: 09:00 till 05:00
time_to_run = bool( (datetime.time(9,00)<=datetime.datetime.now().time()<=datetime.time(17,00)) 
# if your start-end range is overnight || example: 20:00 till 04:30
time_to_run = bool( (datetime.time(20,00)<=datetime.datetime.now().time()<=datetime.time(23,59)) or (datetime.time(0,0)<=datetime.datetime.now().time()<=datetime.time(4,30)) )

Above is my implementation of this... Remove = signs if you want just times between the ranges

Indo answered 1/2, 2024 at 10:57 Comment(0)
E
-1

Here how i did it in python

import datetime    
e = datetime.datetime.now()    
current_time = (e.strftime("%I:%M:%S %p"))
if current_time < '04:30:00 PM' or current_time > '9:30 AM':
    print(current_time)
Exchangeable answered 6/9, 2022 at 20:35 Comment(1)
This answer is wrong. It is just doing a string comparison and it doesn't workGarwood

© 2022 - 2025 — McMap. All rights reserved.