'Sunrise and Sunset time in Python
I'm currently working on a project that notifies the users when certain activities related to light are triggered. I've done the part related to light. Hence, I need to find an effective way to retrieve sunrise and sunset time in python, since the whole script is written in python. I know there are several libraries out there for other languages, I wonder what the most convenient way is to do this in python.
It will seem pretty much like this, I suppose:
if(sunrise<T<sunset) and (light<threshold):
notifyUser()
I'd appreciate any help here, have a good one.
Solution 1:[1]
Check out astral. Here's a slightly modified example from their docs:
>>> from astral import Astral
>>> city_name = 'London'
>>> a = Astral()
>>> a.solar_depression = 'civil'
>>> city = a[city_name]
>>> sun = city.sun(date=datetime.date(2009, 4, 22), local=True)
>>> if (sun['sunrise'] < T < sun['sunset']) and (light < threshold):
>>> notifyUser()
If you use something like this example, please remember to change the city_name and date provided to city.sun.
Solution 2:[2]
You can also try with suntime. An example from their doc below:
import datetime
from suntime import Sun, SunTimeException
latitude = 51.21
longitude = 21.01
sun = Sun(latitude, longitude)
# Get today's sunrise and sunset in UTC
today_sr = sun.get_sunrise_time()
today_ss = sun.get_sunset_time()
print('Today at Warsaw the sun raised at {} and get down at {} UTC'.
format(today_sr.strftime('%H:%M'), today_ss.strftime('%H:%M')))
# On a special date in your machine's local time zone
abd = datetime.date(2014, 10, 3)
abd_sr = sun.get_local_sunrise_time(abd)
abd_ss = sun.get_local_sunset_time(abd)
print('On {} the sun at Warsaw raised at {} and get down at {}.'.
format(abd, abd_sr.strftime('%H:%M'), abd_ss.strftime('%H:%M')))
Solution 3:[3]
The Astral package example above appears to be dated.
Below is an example for Astral v2.2 for the San Jose, CA airport location.
First, set up the observer's location:
from astral import LocationInfo
loc = LocationInfo(name='SJC', region='CA, USA', timezone='America/Los_Angeles',
latitude=37.3713439, longitude=-121.944675)
print(loc)
# LocationInfo(name='SJC', region='CA, USA', timezone='America/Los_Angeles',
# latitude=37.3713439, longitude=-121.944675)
print(loc.observer)
# Observer(latitude=37.3713439, longitude=-121.944675, elevation=0.0)
Note:
- Only the latitude, longitude, and timezone are important.
- The name and region are just labels.
Next, calculate the sun's info for that observer on the desired date (e.g., 2021-01-15 below):
import datetime
from astral.sun import sun
s = sun(loc.observer, date=datetime.date(2021, 1, 15), tzinfo=loc.timezone)
for key in ['dawn', 'dusk', 'noon', 'sunrise', 'sunset']:
print(f'{key:10s}:', s[key])
Output:
dawn : 2021-01-15 06:52:04.342105-08:00
dusk : 2021-01-15 17:42:59.471441-08:00
noon : 2021-01-15 12:17:05-08:00
sunrise : 2021-01-15 07:21:04.877697-08:00
sunset : 2021-01-15 17:13:58.467348-08:00
Notes:
- If the timezone is not specified, it defaults to UTC.
- Noon is solar noon -- the time when the sun crosses the meridian at the observer's location.
- Astral is an implementation of the Excel sheets published by the NOAA.
Solution 4:[4]
Further improving @Wojciech Jakubas answer, this is the benchmark (ommitting timezone):
# boilerplate
from datetime import date, datetime, timezone, timedelta
import pytz
import time
from suntime import Sun, SunTimeException
from suntimes import SunTimes
import sunriset
import astral, astral.sun
latitude = 6.2088
longitude = 106.8456
altitude = 0
tz_name = 'Asia/Jakarta'
for_date = date(2021, 4, 6)
%%timeit
# print('====== suntime ======')
sun = Sun(latitude, longitude)
today_sr = sun.get_sunrise_time(for_date)
today_ss = sun.get_sunset_time(for_date)
# 20.3 µs ± 90.3 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
%%timeit
# print('====== suntimes ======')
sun2 = SunTimes(longitude=longitude, latitude=latitude, altitude=altitude)
today_sr = sun2.riseutc(for_date)
today_ss = sun2.setutc(for_date)
# 83 µs ± 261 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
%%timeit
# print('====== sunriset ======')
df = sunriset.to_pandas(for_date, latitude, longitude, 0, 1)
for index, row in df.iterrows():
today_sr = row['Sunrise']
today_ss = row['Sunset']
break
# 28.7 ms ± 126 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
%%timeit
# print('====== astral ======')
l = astral.LocationInfo('Custom Name', 'My Region', tz_name, latitude, longitude)
today_sr = astral.sun.sunrise(l.observer, date=for_date)
today_sr = astral.sun.sunset(l.observer, date=for_date)
# 64.3 µs ± 292 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
To convert into local time zone (UTC+X), use:
# with known region name
tz_name = 'Asia/Jakarta'
tz = pytz.timezone(tz_name)
today_sr.astimezone(tz)
# with known time different
time_different = 7
tz = datetime.timezone(datetime.timedelta(hours=time_different))
today_sr.astimezone(tz)
Conclusion:
- Use
suntime(Be aware that it use LGPL LICENSE). - If you really need one year data and do not care with speed, try
sunrisetsince it spout one year period. sunrisetneed to be edited manually from the source code to solve only single timesunrisetoutput is intimedelta, thus can't be converted using.astimezonedirectly.
Solution 5:[5]
This can also be done using the skyfield library. Here's a short example using the current version (1.39), adapted from the documentation:
from skyfield import almanac, api
ts = api.load.timescale()
eph = api.load('de421.bsp')
# Location
bluffton = api.wgs84.latlon(+40.8939, -83.8917)
# Times between which to look for sunrises and sunsets
t0 = ts.utc(2018, 9, 12, 4)
t1 = ts.utc(2018, 9, 13, 4)
times, is_sunrise = almanac.find_discrete(t0, t1, almanac.sunrise_sunset(eph, bluffton))
time will contain the times of sunrises/sunsets between t0 and t1, and the corresponding value in is_sunrise will be 1 if it's a sunrise and 0 for a sunset.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | PHPirate |
| Solution 2 | Jon |
| Solution 3 | |
| Solution 4 | |
| Solution 5 | Florian Brucker |
