Sunrise and Sunset Times¶
This tutorial computes sunrise and sunset times for every day of 2024 at a given location, then visualizes how daylight hours change over the course of the year.
satkit.sun.rise_set returns the sunrise and sunset times in UTC for a given date and ground location. The results are converted to local time (US Eastern) for display. The shaded region in the plot represents daylight hours.
In [1]:
Copied!
import satkit as sk
import datetime
from zoneinfo import ZoneInfo
import plotly.graph_objects as go
import satkit as sk
import datetime
from zoneinfo import ZoneInfo
import plotly.graph_objects as go
Compute Rise and Set Times¶
For each day in 2024, compute the sunrise and sunset in UTC, then convert to US Eastern time using Python's built-in zoneinfo module.
In [2]:
Copied!
# Array of times for each day of 2024
basetime = sk.time(2024, 1, 1)
timearr = [basetime + sk.duration(days=i) for i in range(365)]
# Coordinates of Arlington, MA
coord = sk.itrfcoord(latitude_deg=42.1514, longitude_deg=-71.1516)
# sunrise, sunset in UTC
riseset = [sk.sun.rise_set(t, coord) for t in timearr]
rise, set = zip(*riseset)
# Convert to Eastern Time
eastern = ZoneInfo("America/New_York")
drise = [r.datetime().astimezone(eastern) for r in rise]
dset = [s.datetime().astimezone(eastern) for s in set]
# Hour of day, in [0,24]
risefrac = [r.hour + r.minute / 60 + r.second / 3600 for r in drise]
setfrac = [s.hour + s.minute / 60 + s.second / 3600 for s in dset]
# Convert hour of day to a time
risetime = [datetime.time(hour=r.hour, minute=r.minute, second=r.second) for r in drise]
settime = [datetime.time(hour=s.hour, minute=s.minute, second=s.second) for s in dset]
# Array of times for each day of 2024
basetime = sk.time(2024, 1, 1)
timearr = [basetime + sk.duration(days=i) for i in range(365)]
# Coordinates of Arlington, MA
coord = sk.itrfcoord(latitude_deg=42.1514, longitude_deg=-71.1516)
# sunrise, sunset in UTC
riseset = [sk.sun.rise_set(t, coord) for t in timearr]
rise, set = zip(*riseset)
# Convert to Eastern Time
eastern = ZoneInfo("America/New_York")
drise = [r.datetime().astimezone(eastern) for r in rise]
dset = [s.datetime().astimezone(eastern) for s in set]
# Hour of day, in [0,24]
risefrac = [r.hour + r.minute / 60 + r.second / 3600 for r in drise]
setfrac = [s.hour + s.minute / 60 + s.second / 3600 for s in dset]
# Convert hour of day to a time
risetime = [datetime.time(hour=r.hour, minute=r.minute, second=r.second) for r in drise]
settime = [datetime.time(hour=s.hour, minute=s.minute, second=s.second) for s in dset]
Visualize¶
Plot sunrise and sunset times over the year. The shaded area represents daylight hours. Note the characteristic asymmetry around the solstices and the abrupt shifts from daylight saving time transitions.
In [3]:
Copied!
def frac2str(y):
return y.strftime("%H:%M:%S")
risestring = [frac2str(r) for r in risetime]
setstring = [frac2str(s) for s in settime]
fig = go.Figure()
fig.add_trace(
go.Scatter(
x=[x.datetime() for x in timearr],
y=risefrac,
customdata=risestring,
name="Sunrise",
mode="lines",
line=dict(color="rgb(0,100,80)"),
hovertemplate="Date: %{x}<br>Sunrise: %{customdata}<extra></extra>", # Custom hover text
)
)
fig.add_trace(
go.Scatter(
x=[x.datetime() for x in timearr],
y=setfrac,
name="SunSet",
mode="lines",
fill="tonexty",
customdata=setstring,
fillcolor="rgba(0,100,80,0.2)",
line=dict(color="rgb(0,100,80)"),
hovertemplate="Date: %{x}<br>Sunset: %{customdata}<extra></extra>", # Custom hover text
)
)
fig.update_yaxes(title="Local Hour of Day")
fig.update_xaxes(title="Date")
fig.update_layout(
title="Sunrise and Sunset Times for 2024 in Arlington, MA",
xaxis=dict(
gridcolor="#dddddd",
gridwidth=1,
showline=True,
mirror=True,
linewidth=2,
linecolor="black",
),
yaxis=dict(
gridcolor="#dddddd",
gridwidth=1,
showline=True,
mirror=True,
linewidth=2,
linecolor="black",
range=[0, 24],
tickvals=[0, 6, 12, 18, 24], # Set y-axis tick positions
ticktext=["Midnight", "6 AM", "Noon", "6 PM", "Midnight"],
),
plot_bgcolor="white",
paper_bgcolor="white",
width=600,
height=520,
)
fig.show()
def frac2str(y):
return y.strftime("%H:%M:%S")
risestring = [frac2str(r) for r in risetime]
setstring = [frac2str(s) for s in settime]
fig = go.Figure()
fig.add_trace(
go.Scatter(
x=[x.datetime() for x in timearr],
y=risefrac,
customdata=risestring,
name="Sunrise",
mode="lines",
line=dict(color="rgb(0,100,80)"),
hovertemplate="Date: %{x}
Sunrise: %{customdata} ", # Custom hover text
)
)
fig.add_trace(
go.Scatter(
x=[x.datetime() for x in timearr],
y=setfrac,
name="SunSet",
mode="lines",
fill="tonexty",
customdata=setstring,
fillcolor="rgba(0,100,80,0.2)",
line=dict(color="rgb(0,100,80)"),
hovertemplate="Date: %{x}
Sunset: %{customdata} ", # Custom hover text
)
)
fig.update_yaxes(title="Local Hour of Day")
fig.update_xaxes(title="Date")
fig.update_layout(
title="Sunrise and Sunset Times for 2024 in Arlington, MA",
xaxis=dict(
gridcolor="#dddddd",
gridwidth=1,
showline=True,
mirror=True,
linewidth=2,
linecolor="black",
),
yaxis=dict(
gridcolor="#dddddd",
gridwidth=1,
showline=True,
mirror=True,
linewidth=2,
linecolor="black",
range=[0, 24],
tickvals=[0, 6, 12, 18, 24], # Set y-axis tick positions
ticktext=["Midnight", "6 AM", "Noon", "6 PM", "Midnight"],
),
plot_bgcolor="white",
paper_bgcolor="white",
width=600,
height=520,
)
fig.show()
Sunrise: %{customdata}
Sunset: %{customdata}