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.