///|
/// Approximate solar declination in degrees for a day of year (1..365/366).
pub fn solar_declination(day_of_year : Int32) -> Double {
  -23.44 * @math.cos(to_radians(360.0 / 365.0 * (day_of_year + 10).to_double()))
}

///|
/// Simplified NOAA sunrise/sunset in local solar hours, or `None` for polar day/night.
pub fn sunrise_sunset(
  lat_degrees : Double,
  day_of_year : Int32,
) -> (Double, Double)? {
  let lat = to_radians(lat_degrees)
  let decl = to_radians(solar_declination(day_of_year))
  let zenith = to_radians(90.833)
  let cos_hour_angle = (@math.cos(zenith) - @math.sin(lat) * @math.sin(decl)) /
    (@math.cos(lat) * @math.cos(decl))
  if cos_hour_angle > 1.0 || cos_hour_angle < -1.0 {
    return None
  }
  let hour_angle = to_degrees(@math.acos(cos_hour_angle)) / 15.0
  let sunrise = 12.0 - hour_angle
  let sunset = 12.0 + hour_angle
  if sunrise >= sunset {
    return None
  }
  Some((sunrise, sunset))
}