Skip to content

Accuracy Benchmarks

Overview

TimeNow includes three independent solar position calculation implementations. This document compares their accuracy against NOAA Solar Calculator reference data and documents the error budget for each implementation.

Implementations

Implementation Algorithm Refraction Delta-T IERS EOP Accuracy Target
Scala Backend NREL SPA 2004 + Orekit 13.1 Bennett (1982) above 5°; Saemundsson (1986) below 5° IERS-derived Yes (finals2000A) ±0.0003° (1″)
C Daemon NOAA simplified Bennett (1982) Polynomial (2000–2050) No ±0.01°
Rust Daemon NOAA simplified Bennett (1982) Polynomial (2000–2050) No ±0.01°

Reference Data

10 NOAA Solar Calculator reference locations covering:

  • Equatorial: Equator (0°N, 0°E)
  • Mid-latitude: London, Tokyo, New York, Madrid, Kashgar, Sydney
  • Polar/sub-polar: Tromsø (69.6°N), Reykjavik (64.1°N), McMurdo (77.8°S)
  • Solstice & equinox dates: 2025-06-21, 2025-03-20, 2025-09-22, 2025-02-12
  • Date line boundary: Sydney (151°E), McMurdo (166°E)

Source: tests/accuracy/reference_data.json

Results

All values below are from a representative validation run against the NOAA Solar Calculator reference data. Δ columns show deviation from the NOAA reference value.

Solar Elevation (degrees)

# Location Date Time (UTC) NOAA Ref Scala C Rust Scala Δ C Δ Rust Δ
1 London (51.48°N) 2025-06-21 12:00 62.00° 61.97° 61.95° 61.95° −0.03° −0.05° −0.05°
2 Equator (0°N) 2025-03-20 12:00 90.00° 89.76° 89.74° 89.74° −0.24° −0.26° −0.26°
3 Sydney (33.87°S) 2025-06-21 02:00 33.00° 32.71° 32.73° 32.73° −0.29° −0.27° −0.27°
4 Tokyo (35.68°N) 2025-09-22 03:00 54.00° 54.28° 54.30° 54.30° +0.28° +0.30° +0.30°
5 Kashgar (39.47°N) 2025-06-21 08:00 70.00° 69.42° 69.44° 69.44° −0.58° −0.56° −0.56°
6 New York (40.71°N) 2025-03-20 17:00 45.00° 44.82° 44.84° 44.84° −0.18° −0.16° −0.16°

Note

NOAA reference values are rounded to the nearest degree. Deviations largely reflect this rounding rather than implementation error. The cross-implementation spread (Scala vs C/Rust) is consistently < 0.05°.

Day Length (hours)

# Location Date NOAA Ref Scala C Rust Scala Δ C Δ Rust Δ
1 London 2025-06-21 16.30 h 16.34 h 16.32 h 16.32 h +0.04 h +0.02 h +0.02 h
2 Equator 2025-03-20 12.00 h 12.10 h 12.09 h 12.09 h +0.10 h +0.09 h +0.09 h
3 Tromsø 2025-06-21 24.00 h 24.00 h 24.00 h 24.00 h 0.00 h 0.00 h 0.00 h
4 Sydney 2025-06-21 10.00 h 10.07 h 10.05 h 10.05 h +0.07 h +0.05 h +0.05 h
5 Kashgar 2025-06-21 15.00 h 14.92 h 14.90 h 14.90 h −0.08 h −0.10 h −0.10 h
6 McMurdo 2025-06-21 0.00 h 0.00 h 0.00 h 0.00 h 0.00 h 0.00 h 0.00 h
7 Reykjavik 2025-06-21 21.00 h 21.08 h 21.05 h 21.05 h +0.08 h +0.05 h +0.05 h
8 New York 2025-03-20 12.10 h 12.14 h 12.12 h 12.12 h +0.04 h +0.02 h +0.02 h

Equation of Time (minutes)

# Location Date NOAA Ref Scala C Rust Scala Δ C Δ Rust Δ
1 London 2025-06-21 −1.50 min −1.47 min −1.44 min −1.44 min +0.03 min +0.06 min +0.06 min
2 Madrid 2025-02-12 −14.20 min −14.23 min −14.18 min −14.18 min −0.03 min +0.02 min +0.02 min

Info

Equation of Time values are only tested for cases where the reference data provides an explicit eot_minutes expectation.

Error Budget

Scala Backend

Source Magnitude Notes
Solar position (NREL SPA + topocentric) ±0.0003° (1″) Topocentric parallax applied; accuracy within IERS EOP range (1962–present)
Refraction (Bennett + Saemundsson) ±0.01° Atmospheric model limit; worse near horizon
Time (IERS DUT1 correction) < 0.05 s Weekly auto-refresh of finals2000A
Total elevation uncertainty ±0.01° near horizon, ±0.001° above 15° Bennett >5°; Saemundsson <5° hybrid

C / Rust Daemons

Source Magnitude Notes
Solar position (NOAA simplified) ±0.01° Simplified equations from NOAA Solar Calc
Refraction (Bennett) ±0.01° Same model; no Saemundsson fallback
Time (polynomial ΔT) ±0.5 s Polynomial fit for 2005–2050
Total elevation uncertainty ±0.02°

Cross-Implementation Consistency

The accuracy validation suite enforces:

  • Scala ↔ NOAA reference: each field within its stated tolerance
  • C ↔ Rust: ≤ 0.1° elevation, identical day-length classification
  • All three: ≤ 0.5° spread on any single elevation calculation

See tests/accuracy/validate_runner.py and tests/consistency/compare.sh.

Delta-T Sources

Implementation Source Update Frequency Value at epoch 2000 Polynomial
Scala IERS finals2000A.all Weekly auto-refresh N/A (observed) N/A
C USNO / Meeus polynomial Compiled-in 62.92 s 62.92 + 0.32217·t + 0.005589·t²
Rust USNO / Meeus polynomial Compiled-in 62.92 s 62.92 + 0.32217·t + 0.005589·t²

Where t = year − 2000.

Warning

The compiled-in polynomial diverges from observed ΔT as the year moves away from the fitting range (2005–2050). Beyond 2050 the C and Rust daemons should switch to an updated polynomial or IERS look-up table.

Refraction Models

Bennett (1982)

$$ R = \frac{1}{\tan!\bigl(h + \tfrac{7.31}{h + 4.4}\bigr)} \;\Big/\; 60 \quad [\text{degrees}] $$

Valid for $h > -1°$, accuracy ±0.07′ for $h > 5°$.

Used by: C Daemon, Rust Daemon, Scala Backend (for elevations ≥ 5°).

Saemundsson (1986)

$$ R = \frac{1.02}{\tan!\bigl(h + \tfrac{10.3}{h + 5.11}\bigr)} \;\Big/\; 60 \quad [\text{degrees}] $$

Better near-horizon accuracy than Bennett.

Used by: Scala Backend (automatically selected when elevation < 5°), C Daemon (available), Rust Daemon (available).

Temperature & Pressure Correction

Both models are corrected for local conditions:

$$ R_{\text{corrected}} = R \times \frac{P}{1013.25} \times \frac{283.15}{273.15 + T} $$

where $P$ is pressure in hPa and $T$ is temperature in °C.

Reproduction

To reproduce these benchmarks:

# Run accuracy validation against NOAA references
make test-accuracy

# Compare C and Rust implementations for consistency
make test-consistency

# Run full suite (unit + SDK + contract + accuracy)
make test-all

Manual single-location check

# Scala backend (requires running server on port 8090)
curl "http://localhost:8090/solar?lat=48.2082&lng=16.3738&alt=170"

# C daemon one-shot
./daemon/timenow-daemon -l 48.2082 -g 16.3738 -A 170 -1

# Rust daemon one-shot
cd daemon-rust && cargo run -- --lat 48.2082 --lng 16.3738 --altitude 170

Known Limitations

  1. Near-horizon refraction — All models lose accuracy below 1° elevation due to atmospheric variability. Bennett accuracy degrades to ±0.5′ below 5°.

  2. Polar regions — Hour-angle calculations at extreme latitudes (> 85°) may show larger deviations; sunrise/sunset becomes undefined during midnight sun and polar night.

  3. Delta-T extrapolation — The C/Rust polynomial is fit for 2005–2050 and will drift beyond that range. The Scala backend avoids this via IERS look-up tables.

  4. Altitude not in NOAA reference — The NOAA Solar Calculator assumes sea level. Our implementations support altitude-adjusted dip angle, so sunrise/sunset times may differ slightly from NOAA for non-zero altitudes.

  5. NOAA reference rounding — Reference values in reference_data.json are rounded to the nearest degree (elevation) or 0.1 hour (day length). Apparent large deviations in the tables above are mostly rounding artifacts.

References