calendar.features.get_day_night_features(
start,
cov_end,
location,
freq= 'h' ,
timezone= 'UTC' ,
)
Create day/night features using astronomical sunrise and sunset times.
Sunrise and sunset times are computed once per unique calendar date (using astral.sun.sun()) and then broadcast to all timestamps in the requested hourly grid, which avoids redundant computation for large date ranges.
The returned DataFrame contains four columns:
sunrise_hour — rounded sunrise hour (0–23).
sunset_hour — rounded sunset hour (0–23).
daylight_hours — sunset_hour - sunrise_hour.
is_daylight — 1 if the timestamp is between sunrise and sunset, else 0.
Parameters
start
Union [str , pd .Timestamp ]
Start of the time range. String values are parsed with utc=True.
required
cov_end
Union [str , pd .Timestamp ]
Inclusive end of the time range. String values are parsed with utc=True.
required
location
LocationInfo
LocationInfo instance describing the geographic location (latitude, longitude, timezone).
required
freq
str
Pandas-compatible frequency string for the output index. Defaults to "h" (hourly).
'h'
timezone
str
Timezone label applied to the generated index. Defaults to "UTC".
'UTC'
Examples
import pandas as pd
from astral import LocationInfo
from spotforecast2_safe.calendar import get_day_night_features
# Use a two-week window around the autumn equinox so that
# is_daylight.mean() is close to 0.5 (daylight ~12 h / 24 h).
start = pd.Timestamp("2024-09-15" , tz= "UTC" )
cov_end = pd.Timestamp("2024-09-28 23:00" , tz= "UTC" )
location = LocationInfo(
latitude= 51.5136 ,
longitude= 7.4653 ,
timezone= "UTC" ,
)
features = get_day_night_features(
start= start,
cov_end= cov_end,
location= location,
freq= "h" ,
timezone= "UTC" ,
)
print ("shape:" , features.shape)
print ("columns:" , features.columns.tolist())
print ("is_daylight mean:" , round (features["is_daylight" ].mean(), 3 ))
print (features.head(3 ))
assert features.shape == (336 , 4 )
assert features.columns.tolist() == [
"sunrise_hour" ,
"sunset_hour" ,
"daylight_hours" ,
"is_daylight" ,
]
assert 0.4 < features["is_daylight" ].mean() < 0.65
shape: (336, 4)
columns: ['sunrise_hour', 'sunset_hour', 'daylight_hours', 'is_daylight']
is_daylight mean: 0.518
sunrise_hour sunset_hour daylight_hours \
2024-09-15 00:00:00+00:00 5 18 13
2024-09-15 01:00:00+00:00 5 18 13
2024-09-15 02:00:00+00:00 5 18 13
is_daylight
2024-09-15 00:00:00+00:00 0
2024-09-15 01:00:00+00:00 0
2024-09-15 02:00:00+00:00 0