use crate::math::*;
use chrono::{Datelike, NaiveDate};
pub fn julian(date: NaiveDate) -> f64 {
let year: i32 = date.year();
let month: u32 = date.month();
let day: u32 = date.day();
let mut y = year as f64;
let mut m = month as f64;
let d = day as f64;
if m == 1.0 || m == 2.0 {
y = y - 1.0;
m = m + 12.0;
}
let a = (y / 100.0).floor();
let b = 2.0 - a + (a / 4.0).floor();
return (365.25 * (y + 4716.0)).floor() + (30.6001 * (m + 1.0)).floor() + d + b - 1524.5;
}
pub fn sun_coords(jd: f64) -> (f64, f64) {
let j_2000 = jd - 2_451_545.0;
let g = deg::normalize_angle(357.529 + (0.98560028 * j_2000));
let q = deg::normalize_angle(280.459 + (0.98564736 * j_2000));
let l = deg::normalize_angle(q + (1.915 * deg::sin(g)) + (0.020 * deg::sin(2.0 * g)));
let e = 23.439 - (0.00000036 * j_2000);
let mut ra = deg::atan2(deg::cos(e) * deg::sin(l), deg::cos(l)) / 15_f64;
ra = time::normalize_hour(ra);
let eqt = (q / 15.0) - ra;
let decl = deg::asin(deg::sin(e) * deg::sin(l));
return (eqt, decl);
}
pub fn zenith(jd: f64, lng: f64, tz: f64) -> f64 {
let eqt = sun_coords(jd).0;
return 12_f64 + tz - (lng / 15_f64) - eqt;
}
pub enum HorizonDirection {
Sunrise,
Sunset,
}
pub fn horizon_hour_angle(
angle: f64,
jd: f64,
zenith: f64,
lat: f64,
direction: HorizonDirection,
) -> f64 {
let decl = sun_coords(jd).1;
let t_a = (1_f64 / 15_f64)
* deg::acos(
(-deg::sin(angle) - deg::sin(lat) * deg::sin(decl)) / (deg::cos(lat) * deg::cos(decl)),
);
match direction {
HorizonDirection::Sunrise => return zenith - t_a,
HorizonDirection::Sunset => return zenith + t_a,
}
}
pub fn shadow_length_hour(length: f64, jd: f64, zenith: f64, lat: f64) -> f64 {
let decl = sun_coords(jd).1;
let a_t = (1_f64 / 15_f64)
* deg::acos(
(deg::sin(deg::acot(length + deg::tan(lat - decl))) - (deg::sin(lat) * deg::sin(decl)))
/ (deg::cos(lat) * deg::cos(decl)),
);
return zenith + a_t;
}