A Self-Correcting Solar System Baseline From Sunrise/Sunset Data
A fixed-schedule solar baseline drifts out of sync with the sun throughout the year. In Phoenix the sun is up for 13 hours 10 minutes in late August and 10 hours 2 minutes at the December solstice. A flat daily kWh target flags that entire winter as a fault, then stays quiet on the July afternoon when one string dies at 2pm under full sun. The fix is to anchor the baseline to the actual sun instead of the clock, and most of what you need for that does not require an irradiance forecast. One thing before any code: sun geometry tells you when a system should be producing and when it should peak. It does not tell you how much light actually reached the panels. That is irradiance, and cloud cover swamps it. If you want modeled output in kWh, reach for Forecast.Solar or Solcast, which fold in weather and your array's tilt and azimuth. What follows is the free, dependency-light layer underneath that: the daylight window, the solar-noon peak, and the day-length trend. TL;DR Sun geometry (sunrise, sunset, solar noon, day length) catches a specific class of solar underperformance with no irradiance data. Gate alerts to the real daylight window so your monitor stops crying "underperformance" before sunrise. Track the daily production peak relative to solar noon. A persistent shift across comparable days can reveal shading, orientation, or system changes that a total-kWh check misses. Normalize a flat kWh target by day length so winter stops tripping false alarms. First-order fix, not a physics model. One call to an astronomy endpoint returns all of it. Code below in curl, Python, and Node. For real production forecasting, use an irradiance API. Sun times are the sanity layer, not the forecaster. Sun times will not predict your kWh, but they eliminate common timing-based false alarms and can surface useful production-shape anomalies early. Pull sunrise, sunset, solar noon, and day length once a day, gate your alerts to daylight, watch the peak, and scale the target for season.