SUN_RISE_SET_SPA

This function computes sunrise, sunset, and solar transit times for localized timestamps using the NREL Solar Position Algorithm (SPA).

SPA is a high-accuracy astronomical method used widely in PV and solar-resource workflows where event-timing precision matters.

Conceptually, sunrise and sunset occur near the condition:

\mathrm{zenith} \approx 90^\circ

with corrections from detailed SPA geometry, refraction, and time-scale terms.

Excel Usage

=SUN_RISE_SET_SPA(times, latitude, longitude, delta_t)
  • times (list[list], required): Timestamps for which to calculate events (ISO8601 format).
  • latitude (float, required): Site latitude (degrees).
  • longitude (float, required): Site longitude (degrees).
  • delta_t (float, optional, default: 67): Difference between terrestrial time and UT1 (seconds).

Returns (list[list]): 2D list [[sunrise, sunset, transit]] as ISO8601 strings, or an error string.

Example 1: Solstice events in Golden, CO

Inputs:

times latitude longitude delta_t
2024-06-21T12:00:00-06:00 39.742 -105.179 67

Excel formula:

=SUN_RISE_SET_SPA({"2024-06-21T12:00:00-06:00"}, 39.742, -105.179, 67)

Expected output:

Result
2024-06-21T05:33:02.276770560-06:00 2024-06-21T20:32:09.189224704-06:00 2024-06-21T13:02:42.069548544-06:00
Example 2: Winter solstice events in Golden, CO

Inputs:

times latitude longitude delta_t
2024-12-21T12:00:00-07:00 39.742 -105.179 67

Excel formula:

=SUN_RISE_SET_SPA({"2024-12-21T12:00:00-07:00"}, 39.742, -105.179, 67)

Expected output:

Result
2024-12-21T07:18:31.492916224-07:00 2024-12-21T16:39:47.010416128-07:00 2024-12-21T11:59:09.093026048-07:00
Example 3: Equinox events in Golden, CO

Inputs:

times latitude longitude delta_t
2024-03-20T12:00:00-06:00 39.742 -105.179 67

Excel formula:

=SUN_RISE_SET_SPA({"2024-03-20T12:00:00-06:00"}, 39.742, -105.179, 67)

Expected output:

Result
2024-03-20T07:03:07.839649792-06:00 2024-03-20T19:12:23.359081216-06:00 2024-03-20T13:07:56.168577536-06:00
Example 4: Scalar timestamp SPA events

Inputs:

times latitude longitude delta_t
2024-06-21T12:00:00-06:00 39.742 -105.179 67

Excel formula:

=SUN_RISE_SET_SPA("2024-06-21T12:00:00-06:00", 39.742, -105.179, 67)

Expected output:

Result
2024-06-21T05:33:02.276770560-06:00 2024-06-21T20:32:09.189224704-06:00 2024-06-21T13:02:42.069548544-06:00

Python Code

Show Code
import pandas as pd
from pvlib.solarposition import sun_rise_set_transit_spa as result_func

def sun_rise_set_spa(times, latitude, longitude, delta_t=67):
    """
    Calculate sunrise, sunset, and solar transit times using the NREL SPA algorithm.

    See: https://pvlib-python.readthedocs.io/en/stable/reference/generated/pvlib.solarposition.sun_rise_set_transit_spa.html

    This example function is provided as-is without any representation of accuracy.

    Args:
        times (list[list]): Timestamps for which to calculate events (ISO8601 format).
        latitude (float): Site latitude (degrees).
        longitude (float): Site longitude (degrees).
        delta_t (float, optional): Difference between terrestrial time and UT1 (seconds). Default is 67.

    Returns:
        list[list]: 2D list [[sunrise, sunset, transit]] as ISO8601 strings, or an error string.
    """
    try:
        def flatten_str(data):
            if not isinstance(data, list): return [str(data)]
            return [str(val) for row in data for val in (row if isinstance(row, list) else [row]) if val != ""]

        time_list = flatten_str(times)
        if len(time_list) == 0:
            return "Error: times array cannot be empty"

        lat = float(latitude)
        lon = float(longitude)
        dt = float(delta_t) if delta_t is not None else 67.0

        idx = pd.DatetimeIndex(time_list)

        res = result_func(
            times=idx,
            latitude=lat,
            longitude=lon,
            delta_t=dt
        )

        # res is a DataFrame with columns: sunrise, sunset, transit
        out = []
        for i in range(len(idx)):
            sr = res['sunrise'].iloc[i]
            ss = res['sunset'].iloc[i]
            tr = res['transit'].iloc[i]
            out.append([
                sr.isoformat() if not pd.isna(sr) else "",
                ss.isoformat() if not pd.isna(ss) else "",
                tr.isoformat() if not pd.isna(tr) else ""
            ])
        return out
    except Exception as e:
        return f"Error: {str(e)}"

Online Calculator

Timestamps for which to calculate events (ISO8601 format).
Site latitude (degrees).
Site longitude (degrees).
Difference between terrestrial time and UT1 (seconds).