72

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?

Joe Holloway
  • 28,320
  • 15
  • 82
  • 92
user993563
  • 18,601
  • 10
  • 42
  • 55
  • `timedelta()` allows you to specify days, hours and minutes too, so you don't have to calculate it and the code is more readable. – C2H5OH Apr 06 '12 at 19:28

9 Answers9

121

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.

Joe Holloway
  • 28,320
  • 15
  • 82
  • 92
  • 24
    Should also work with: `if time(10,30) <= now.time() <= time(16,30):`. – Rik Poggi Apr 06 '12 at 19:30
  • 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? – user993563 Apr 06 '12 at 19:45
  • @user993563: Check out the [`datetime` doc](http://docs.python.org/py3k/library/datetime.html#available-types), and in particular [`datetime.date`](http://docs.python.org/py3k/library/datetime.html#date-objects). – Rik Poggi Apr 06 '12 at 19:51
  • 7
    But what if you're trying to check if a time is in between 10 pm and 4 am? :-) – 2arrs2ells Apr 09 '15 at 05:46
  • 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. – Joe Holloway Apr 09 '15 at 21:53
  • 3
    @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) – Alain1405 May 24 '17 at 07:54
  • @JoeHolloway, how do you reference a time range including 12AM midnight? i.e. 18,00 to 24:00 but that throws an error. – HelloWorld123 Apr 20 '20 at 22:06
  • @HelloWorld123 midnight is time(0), not time(24) – Joe Holloway Apr 21 '20 at 15:00
  • 1
    @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? https://stackoverflow.com/questions/61522909/creation-of-slots-at-regular-intervals – Timshrok Apr 30 '20 at 13:01
  • @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 False – Mirza715 Oct 12 '20 at 23:50
  • @Mirza715 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. – Joe Holloway Oct 13 '20 at 18:11
  • Possible to set the timezone to GMT+1? – Adam Dec 07 '20 at 09:12
  • @Adam 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. – Joe Holloway Dec 08 '20 at 17:02
67

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())
Sean McCarthy
  • 4,838
  • 8
  • 39
  • 61
rouble
  • 16,364
  • 16
  • 107
  • 102
  • 5
    Great solution. Note that startTime, endTime and nowTime are time objects, you can access the time part of a datetime object with `datetime.time()` – Braza Oct 07 '16 at 10:00
  • 3
    How is everyone missing this! – Carson Holzheimer Feb 28 '18 at 12:25
  • @rouble 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 False – Mirza715 Oct 12 '20 at 23:46
  • 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) – Eric Leschinski Jan 14 '21 at 02:13
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))
Maulik
  • 2,881
  • 1
  • 22
  • 27
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)
EVE Milano
  • 109
  • 2
  • 12
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.

rickydj
  • 629
  • 5
  • 17
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)
Thomas Vincent
  • 158
  • 1
  • 6
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)
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
Deepak Sood
  • 385
  • 5
  • 16
-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)
user8214
  • 1
  • 2