sun#
See sun for the full API reference.
Basic usage#
from pyedautils.data_prep.sun import sun_position
# Zurich, summer solstice around solar noon (UTC)
elevation, azimuth = sun_position("2025-06-21 11:30", latitude=47.3769, longitude=8.5417)
print(round(elevation, 1), round(azimuth, 1)) # 66.1 181.3 (high, due south)
Convention#
Elevation is the angle above the horizon (negative when the sun is below it). Azimuth is measured clockwise from geographic north: 0=N, 90=E, 180=S, 270=W.
# Winter solstice noon: sun much lower, still due south
elevation, azimuth = sun_position("2025-12-21 11:30", 47.3769, 8.5417)
print(round(elevation, 1), round(azimuth, 1)) # 19.2 181.5
Timezone handling#
Timezone-aware timestamps are converted to UTC; naive timestamps are assumed to be UTC.
import pandas as pd
# 13:30 local (CEST) == 11:30 UTC -> identical result
sun_position(pd.Timestamp("2025-06-21 13:30", tz="Europe/Zurich"), 47.3769, 8.5417)
Vectorized with pandas#
Pass a Series or DatetimeIndex to get a DataFrame with elevation and azimuth
columns, indexed like the input:
import pandas as pd
idx = pd.date_range("2025-06-21 04:00", "2025-06-21 20:00", freq="1h", tz="UTC")
df = sun_position(idx, latitude=47.3769, longitude=8.5417)
print(df.round(1))
Geometric vs. apparent position#
By default the apparent position (including atmospheric refraction) is returned. Set
refraction=False for the true geometric position (the difference is largest near
the horizon):
sun_position("2025-06-21 04:00", 47.3769, 8.5417, refraction=False)