{
const PI = Math.PI,
sin = Math.sin,
cos = Math.cos,
tan = Math.tan,
asin = Math.asin,
acos = Math.acos,
pow = Math.pow,
deg = r => r / (PI / 180),
rad = d => d * (PI / 180);
const DAY_IN_MS = 1000 * 60 * 60 * 24,
J1970 = 2440588,
timezone = date => -date.getTimezoneOffset() / 60,
toJulian = date => date.valueOf() / DAY_IN_MS - 0.5 + J1970,
julianCentury = date => (toJulian(date) - 2451545) / 36525,
hours = date =>
date.getHours() +
date.getMinutes() / 60 +
date.getSeconds() / 3600 +
date.getMilliseconds() / 3600000;
const obliqCorr = jc => {
const sec =
21.448 - 46.815 * jc - 0.00059 * pow(jc, 2) + 0.001813 * pow(jc, 3);
const meanObliqEcliptic = 23 + (26 + sec / 60) / 60;
const corr = 0.00256 * cos(rad(125.04 - 1934.136 * jc));
return rad(meanObliqEcliptic + corr);
};
const geomMeanAnomSun = jc =>
rad(357.52911 + jc * (35999.05029 - 0.0001537 * jc));
const geomMeanSunLng = jc => 280.46646 + jc * (36000.76983 + jc * 0.0003032);
const declination = jc => {
const gmas = geomMeanAnomSun(jc);
const gmsl = geomMeanSunLng(jc);
const c =
sin(gmas) * (1.914602 - jc * (0.004817 + 0.000014 * jc)) +
sin(2 * gmas) * (0.019993 - 0.000101 * jc) +
sin(3 * gmas) * 0.000289;
const sunTrueLng = (gmsl % 360) + c;
const sunAppLng = rad(
sunTrueLng - 0.00569 - 0.00478 * sin(rad(125.04 - 1934.136 * jc))
);
const oc = obliqCorr(jc);
return asin(sin(oc) * sin(sunAppLng));
};
const hourAngle = (date, lng, jc) => {
const gmsl = rad(geomMeanSunLng(jc) % 360),
e = 0.016708634 - jc * (0.000042037 + 0.0000001267 * jc),
oc = obliqCorr(jc),
y = pow(tan(oc / 2), 2),
gmas = geomMeanAnomSun(jc);
const equationOfTime =
4 *
deg(
y * sin(2 * gmsl) -
2 * e * sin(gmas) +
4 * e * y * sin(gmas) * cos(2 * gmsl) -
0.5 * pow(y, 2) * sin(4 * gmsl) -
1.25 * pow(e, 2) * sin(2 * gmas)
);
const tz = timezone(date);
const days = hours(date) / 24;
let tst = (days * 1440 + equationOfTime + 4 * lng - 60 * tz) % 1440;
tst /= 4;
return rad(tst < 0 ? tst + 180 : tst - 180);
};
const zenith = (lat, dec, ha) =>
acos(sin(lat) * sin(dec) + cos(lat) * cos(dec) * cos(ha));
const azimuth = (lat, ha, zen, dec) => {
const r = deg(
acos((sin(lat) * cos(zen) - sin(dec)) / (cos(lat) * sin(zen)))
);
return ha > 0 ? rad((r + 180) % 360) : rad((540 - r) % 360);
};
const sunPosition = (date, lat, lng) => {
const jc = julianCentury(date);
const dec = declination(jc);
const ha = hourAngle(date, lng, jc);
const zen = zenith(rad(lat), dec, ha);
return {
altitude: deg(PI / 2 - zen),
azimuth: deg(azimuth(rad(lat), ha, zen, dec))
};
};
return CalculateSunPostion(sunPosition);
}