1

I already have working code for this but i'm still very new to python and I know there is a better way of doing this. This is the code i've used in a motion detection script on my raspberry pi. It simply checks if it occurs in the timeframe when i'm not home. I've pulled the code from the rest of the script:

import time
import datetime
import calendar

now = datetime.datetime.now()
x = time.localtime(time.time())

starttime = datetime.datetime(x.tm_year,x.tm_mon,x.tm_mday,8,20,0)
start_timestamp =  calendar.timegm(starttime.timetuple())
now_timestamp =  calendar.timegm(now.timetuple())
future = starttime + datetime.timedelta(minutes=550)
future_timestamp =  calendar.timegm(future.timetuple())

print start_timestamp
print now_timestamp
print future_timestamp

if now_timestamp > start_timestamp and now_timestamp < future_timestamp:
    print "bam!"

All i need to do is see if the current time is between the start time and the end time. I'm sure there is a way of writing this much more efficiently, I think my code is fairly obtuse.

Dan
  • 13
  • 3

3 Answers3

2

You don't need to use timestamps and keep converting to and through - datetime objects support comparison. So you can shorten it to:

from datetime import datetime, timedelta

now = datetime.now()
start_time = now.replace(hour=8, minute=20, second=0)
end_time = start_time + timedelta(minutes=550)

if start_time <= now <= end_time:
    print 'was out'
Jon Clements
  • 138,671
  • 33
  • 247
  • 280
  • Ahh wow. That is so much better! and i didnt know you could nest (not the correct term but i dont know a better one) the if statements "start_time <= time_to_check <= end_time" I've got a lot to learn obviously. That code looks fantastic though, nice and clean. – Dan Feb 27 '15 at 09:14
  • @Dan the term is "chain" :) (it's a chained comparison) – Jon Clements Feb 27 '15 at 09:15
  • You do need to [use timestamps (or equivalent) if you want to take into account the local timezone](http://stackoverflow.com/a/28767876/4279) – jfs Feb 27 '15 at 14:54
0

Covert current time to epoch time using: int(time.time()). You can compare this value using:

import time
# 60*60*24 --> count of seconds in one day

current_time = int(time.time())
start_time = current_time - 4*60*60*24  # Marking start_time as of 4 days back
end_time = current_time + 2*60*60*24  # Marking end_time as of 2 days ahead

if start_time < current_time <= end_time:
    print('Yes, time is between start_time & end_time')

where start_time and end_time are also the values of epoch time.

Moinuddin Quadri
  • 46,825
  • 13
  • 96
  • 126
  • Yup. It could be done that way as well. Updated the answer. :) – Moinuddin Quadri Feb 27 '15 at 09:11
  • It's easier to do the type of calculations that OP wants with datetime objects, so Jon's answer is better, although this is not wrong. – Lennart Regebro Feb 27 '15 at 09:11
  • I find this easier to maintain, especially if you are storing these values in the database. You need not to worry about the conversions and format. You may use it the way you want. – Moinuddin Quadri Feb 27 '15 at 09:22
  • I will use int(time.time()) in the future to get epoch time. Much better than what i'd hacked together from other code i'd found. Thanks for taking the time to answer. – Dan Feb 27 '15 at 09:38
0

Local time is not monotonous i.e., d2 < d1 being True does not mean that d2 is always in the past relative to d1 if d1, d2 are naive datetime objects representing local time.

Do not use start_time <= now <= end_time where the values are naive datetime objects referring to the local time if start_time, end_time may ever happen around end-of-DST transition.

You do need to use timestamps or UTC time or timezone-aware datetime objects if you want to handle the change in the utc offset of the local timezone.

If start_time is given as a local time e.g., today at '8:20' and the end_time is the relative time (not absolute) e.g., 550 minutes into the future:

#!/usr/bin/env python
import time
from datetime import datetime

start_time = datetime.strptime('8:20','%H:%M').time()
start_dt = datetime.combine(datetime.now(), start_time)
start_ts = time.mktime(start_dt.timetuple()) #NOTE: may fail, see the link below
end_ts = start_ts + 550*60 # +550 minutes
if start_ts <= time.time() < end_ts:
    print "the current time is in between"

For time intervals larger than several seconds, you don't need to think about what happens around a leap second such as 2015-06-30 23:59:60+0000. Or changes in time.time() values due to ntp adjustments, etc.

See also, Find if 24 hrs have passed between datetimes - Python.

If you want to find out whether the given local time e.g., '2:26' belongs to the time interval specified as hour:minutes range in the local time e.g., '23:00-07:00; see python time range validator.

Community
  • 1
  • 1
jfs
  • 399,953
  • 195
  • 994
  • 1,670