I'm checking time about every minute, but don't have a good way to check whether I'm in this 'on' mode of operation. I want to be 'on' 2hours before daylight up until 1 hour before sunset. If I continuously check using next_rising()
and next_setting()
, the moment the sun rises, my logic seems to fail because after that point it starts computing the sunrise for tomorrow. My is_daytime()
is broken.
def is_daytime():
"""
Returns whether we should operate in the 'daytime' mode. Note that this
mode is shifted earlier to begin before sunrise and end before sunset.
"""
# Get the localized hour of the day
now = datetime.datetime.now()
# Get the next sunrise/sunset
here.date = now
sunrise = ephem.localtime(here.next_rising(ephem.Sun))
sunset = ephem.localtime(here.next_setting(ephem.Sun))
sunrise_shift = datetime.timedelta(hours=START_BEFORE_SUNSRISE_HR)
sunset_shift = datetime.timedelta(hours=END_BEFORE_SUNSET_HR)
# Return whether it is some amount of time before sunrise AND sunset
return ((sunrise - now) < sunrise_shift) and ((sunset - now) < sunset_shift)
# Dependencies
import time
import datetime
import pytz
import ephem
# Choose your location for sunrise/sunset calculations
MY_TIMEZONE = "America/Los_Angeles"
MY_LONGITUDE = '37.7833' # +N
MY_LATITUDE = '-122.4167' # +E
MY_ELEVATION = 0 # meters
# Choose when to start and stop relative to sunrise and sunset
START_BEFORE_SUNSRISE_HR = 1
END_BEFORE_SUNSET_HR = 1
here = ephem.Observer()
def is_daytime():
"""
Returns whether we should operate in the 'daytime' mode. Note that this
mode is shifted earlier to begin before sunrise and end before sunset.
Assumes sunset NEVER comes after midnight
"""
# Get the localized hour of the day
now = datetime.datetime.now()
# Get the next sunrise/sunset
here.date = now
next_sunrise = ephem.localtime(here.next_rising(ephem.Sun()))
next_sunset = ephem.localtime(here.next_setting(ephem.Sun()))
sunrise_shift = datetime.timedelta(hours=START_BEFORE_SUNSRISE_HR)
sunset_shift = datetime.timedelta(hours=END_BEFORE_SUNSET_HR)
# If it's daytime
if (next_sunset < next_sunrise):
return (now < (next_sunset - sunset_shift))
# Otherwise it's nighttime
else:
return ((next_sunrise - sunrise_shift) < now)
def main():
# Configure the timezone
pytz.timezone(MY_TIMEZONE)
# Configure the ephem object
here.lat = MY_LATITUDE
here.lon = MY_LONGITUDE
here.elevation = MY_ELEVATION
while True:
if is_daytime():
print "It's daytime!"
time.sleep(60)
if __name__ == '__main__':
main()
the moment the sun rises, my logic seems to fail because after that point it starts computing the sunrise for tomorrow.
Think through the logic. What are the cases?
<= sunrise-2H
; the check for sunset-1H
is irrelevant, but harmless.<= sunset-1H
; the check for sunrise-2H
is not only irrelevant, but harmful.So, how do you know which case you're in? Simple. If sunset > sunrise
, you're in case 1 or 3; just check sunrise-2H
; otherwise, you're in case 2, just check sunset-1H
.
What if you go even farther north than Oulo? For example, in Rovaniemi, in early of June, the next sunset is a month away. Does that mean you want your program to stay on all month? Or that you want to pick an arbitrary time to start up and shut down (e.g., start 2 hours before "midnight" and end an hour after)? Whatever rule you come up with, I think ephem
has enough data for you to write it. Or, if you don't know, at least test the code and see what rule it is applying, so you can document that. (I'm guessing people who live up there are used to looking at the docs for time-related programs like this…)