SUN_RISE_SET_GEOM

This function estimates sunrise, sunset, and solar transit times using a geometric approximation based on declination and equation of time.

The method assumes a circular orbit and neglects atmospheric refraction, so it is faster but less accurate than SPA-based event timing.

Event hour-angle geometry is based on relations such as:

\cos(H_0) = -\tan(\phi)\tan(\delta)

where H_0 is the sunrise/sunset hour angle, \phi is latitude, and \delta is declination.

Excel Usage

=SUN_RISE_SET_GEOM(times, latitude, longitude, declination, equation_of_time)
  • times (list[list], required): Timestamps for the events (ISO8601 format).
  • latitude (float, required): Site latitude (degrees).
  • longitude (float, required): Site longitude (degrees).
  • declination (list[list], required): Solar declination angle (radians).
  • equation_of_time (list[list], required): Equation of time offset (minutes).

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

Example 1: Geometric events for basic inputs

Inputs:

times latitude longitude declination equation_of_time
2024-06-21T12:00:00-06:00 39.742 -105.179 0.4091 -1.5

Excel formula:

=SUN_RISE_SET_GEOM({"2024-06-21T12:00:00-06:00"}, 39.742, -105.179, {0.4091}, {-1.5})

Expected output:

Result
2024-06-21T05:37:41.734449192-06:00 2024-06-21T20:26:44.185550809-06:00 2024-06-21T13:02:12.959999998-06:00
Example 2: Geometric events for winter solstice

Inputs:

times latitude longitude declination equation_of_time
2024-12-21T12:00:00-07:00 39.742 -105.179 -0.4091 2

Excel formula:

=SUN_RISE_SET_GEOM({"2024-12-21T12:00:00-07:00"}, 39.742, -105.179, {-0.4091}, {2})

Expected output:

Result
2024-12-21T07:23:14.185550806-07:00 2024-12-21T16:34:11.734449193-07:00 2024-12-21T11:58:42.960000-07:00
Example 3: Geometric events near equinox

Inputs:

times latitude longitude declination equation_of_time
2024-03-20T12:00:00-06:00 39.742 -105.179 0 -7.5

Excel formula:

=SUN_RISE_SET_GEOM({"2024-03-20T12:00:00-06:00"}, 39.742, -105.179, {0}, {-7.5})

Expected output:

Result
2024-03-20T07:08:12.959999998-06:00 2024-03-20T19:08:12.959999998-06:00 2024-03-20T13:08:12.959999998-06:00
Example 4: Scalar timestamp geometric events

Inputs:

times latitude longitude declination equation_of_time
2024-06-21T12:00:00-06:00 39.742 -105.179 0.4091 -1.5

Excel formula:

=SUN_RISE_SET_GEOM("2024-06-21T12:00:00-06:00", 39.742, -105.179, {0.4091}, {-1.5})

Expected output:

Result
2024-06-21T05:37:41.734449192-06:00 2024-06-21T20:26:44.185550809-06:00 2024-06-21T13:02:12.959999998-06:00

Python Code

Show Code
import pandas as pd
import numpy as np
from pvlib.solarposition import sun_rise_set_transit_geometric as result_func

def sun_rise_set_geom(times, latitude, longitude, declination, equation_of_time):
    """
    Geometric calculation of solar sunrise, sunset, and transit.

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

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

    Args:
        times (list[list]): Timestamps for the events (ISO8601 format).
        latitude (float): Site latitude (degrees).
        longitude (float): Site longitude (degrees).
        declination (list[list]): Solar declination angle (radians).
        equation_of_time (list[list]): Equation of time offset (minutes).

    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 != ""]

        def flatten_num(data):
            if not isinstance(data, list): return [float(data)]
            flat = []
            for row in data:
                row = row if isinstance(row, list) else [row]
                for val in row:
                    if val == "": flat.append(float('nan'))
                    else: flat.append(float(val))
            return flat

        time_list = flatten_str(times)
        dec_list = flatten_num(declination)
        eot_list = flatten_num(equation_of_time)

        n = len(time_list)
        if n == 0 or len(dec_list) != n or len(eot_list) != n:
            return "Error: All input arrays must have the same non-zero length"

        lat = float(latitude)
        lon = float(longitude)
        idx = pd.DatetimeIndex(time_list)

        res = result_func(
            times=idx,
            latitude=lat,
            longitude=lon,
            declination=np.array(dec_list),
            equation_of_time=np.array(eot_list)
        )

        # res is a tuple (sunrise, sunset, transit) which are DatetimeIndex-like Series
        sr = res[0]
        ss = res[1]
        tr = res[2]

        out = []
        for i in range(n):
            out.append([
                sr[i].isoformat() if not pd.isna(sr[i]) else "",
                ss[i].isoformat() if not pd.isna(ss[i]) else "",
                tr[i].isoformat() if not pd.isna(tr[i]) else ""
            ])
        return out
    except Exception as e:
        return f"Error: {str(e)}"

Online Calculator

Timestamps for the events (ISO8601 format).
Site latitude (degrees).
Site longitude (degrees).
Solar declination angle (radians).
Equation of time offset (minutes).