Skip to content

Instantly share code, notes, and snippets.

@vojty
Created September 10, 2022 18:32
Show Gist options
  • Save vojty/6196edd98fca80a2a7292ed3072b6741 to your computer and use it in GitHub Desktop.
Save vojty/6196edd98fca80a2a7292ed3072b6741 to your computer and use it in GitHub Desktop.
SunCalc = (function() {
var J1970 = 2440588,
J2000 = 2451545,
deg2rad = Math.PI / 180,
M0 = 357.5291 * deg2rad,
M1 = 0.98560028 * deg2rad,
J0 = 0.0009,
J1 = 0.0053,
J2 = -0.0069,
C1 = 1.9148 * deg2rad,
C2 = 0.0200 * deg2rad,
C3 = 0.0003 * deg2rad,
P = 102.9372 * deg2rad,
e = 23.45 * deg2rad,
th0 = 280.1600 * deg2rad,
th1 = 360.9856235 * deg2rad,
h0 = -0.83 * deg2rad, //sunset angle
d0 = 0.53 * deg2rad, //sun diameter
h1 = -6 * deg2rad, //nautical twilight angle
h2 = -12 * deg2rad, //astronomical twilight angle
h3 = -18 * deg2rad //darkness angle
msInDay = 1000 * 60 * 60 * 24;
function dateToJulianDate( date ) {
return date.valueOf() / msInDay - 0.5 + J1970;
}
function julianDateToDate( j ) {
return new Date((j + 0.5 - J1970) * msInDay);
}
function getJulianCycle( J, lw ) {
return Math.round(J - J2000 - J0 - lw/(2 * Math.PI));
}
function getApproxSolarTransit( Ht, lw, n ) {
return J2000 + J0 + (Ht + lw)/(2 * Math.PI) + n;
}
function getSolarMeanAnomaly( Js ) {
return M0 + M1 * (Js - J2000);
}
function getEquationOfCenter( M ) {
return C1 * Math.sin(M) + C2 * Math.sin(2 * M) + C3 * Math.sin(3 * M);
}
function getEclipticLongitude( M, C ) {
return M + P + C + Math.PI;
}
function getSolarTransit( Js, M, Lsun ) {
return Js + (J1 * Math.sin(M)) + (J2 * Math.sin(2 * Lsun));
}
function getSunDeclination( Lsun ) {
return Math.asin(Math.sin(Lsun) * Math.sin(e));
}
function getRightAscension( Lsun ) {
return Math.atan2(Math.sin(Lsun) * Math.cos(e), Math.cos(Lsun));
}
function getSiderealTime( J, lw ) {
return th0 + th1 * (J - J2000) - lw;
}
function getAzimuth( th, a, phi, d ) {
var H = th - a;
return Math.atan2(Math.sin(H), Math.cos(H) * Math.sin(phi) -
Math.tan(d) * Math.cos(phi));
}
function getAltitude( th, a, phi, d ) {
var H = th - a;
return Math.asin(Math.sin(phi) * Math.sin(d) +
Math.cos(phi) * Math.cos(d) * Math.cos(H));
}
function getHourAngle( h, phi, d ) {
return Math.acos((Math.sin(h) - Math.sin(phi) * Math.sin(d)) /
(Math.cos(phi) * Math.cos(d)));
}
function getSunsetJulianDate( w0, M, Lsun, lw, n ) {
return getSolarTransit(getApproxSolarTransit(w0, lw, n), M, Lsun);
}
function getSunriseJulianDate( Jtransit, Jset ) {
return Jtransit - (Jset - Jtransit);
}
function getSunPosition( J, lw, phi ) {
var M = getSolarMeanAnomaly(J),
C = getEquationOfCenter(M),
Lsun = getEclipticLongitude(M, C),
d = getSunDeclination(Lsun),
a = getRightAscension(Lsun),
th = getSiderealTime(J, lw);
return {
azimuth: getAzimuth( th, a, phi, d ),
altitude: getAltitude( th, a, phi, d )
};
}
return {
getDayInfo: function( date, lat, lng, detailed ) {
var lw = -lng * deg2rad,
phi = lat * deg2rad,
J = dateToJulianDate(date);
var n = getJulianCycle(J, lw),
Js = getApproxSolarTransit(0, lw, n),
M = getSolarMeanAnomaly(Js),
C = getEquationOfCenter(M),
Lsun = getEclipticLongitude(M, C),
d = getSunDeclination(Lsun),
Jtransit = getSolarTransit(Js, M, Lsun),
w0 = getHourAngle(h0, phi, d),
w1 = getHourAngle(h0 + d0, phi, d),
Jset = getSunsetJulianDate(w0, M, Lsun, lw, n),
Jsetstart = getSunsetJulianDate(w1, M, Lsun, lw, n),
Jrise = getSunriseJulianDate(Jtransit, Jset),
Jriseend = getSunriseJulianDate(Jtransit, Jsetstart),
w2 = getHourAngle(h1, phi, d),
Jnau = getSunsetJulianDate(w2, M, Lsun, lw, n),
Jciv2 = getSunriseJulianDate(Jtransit, Jnau);
var info = {
dawn: julianDateToDate(Jciv2),
sunrise: {
start: julianDateToDate(Jrise),
end: julianDateToDate(Jriseend)
},
transit: julianDateToDate(Jtransit),
sunset: {
start: julianDateToDate(Jsetstart),
end: julianDateToDate(Jset)
},
dusk: julianDateToDate(Jnau)
};
if (detailed) {
var w3 = getHourAngle(h2, phi, d),
w4 = getHourAngle(h3, phi, d),
Jastro = getSunsetJulianDate(w3, M, Lsun, lw, n),
Jdark = getSunsetJulianDate(w4, M, Lsun, lw, n),
Jnau2 = getSunriseJulianDate(Jtransit, Jastro),
Jastro2 = getSunriseJulianDate(Jtransit, Jdark);
info.morningTwilight = {
astronomical: {
start: julianDateToDate(Jastro2),
end: julianDateToDate(Jnau2)
},
nautical: {
start: julianDateToDate(Jnau2),
end: julianDateToDate(Jciv2)
},
civil: {
start: julianDateToDate(Jciv2),
end: julianDateToDate(Jrise)
}
};
info.nightTwilight = {
civil: {
start: julianDateToDate(Jset),
end: julianDateToDate(Jnau)
},
nautical: {
start: julianDateToDate(Jnau),
end: julianDateToDate(Jastro)
},
astronomical: {
start: julianDateToDate(Jastro),
end: julianDateToDate(Jdark)
}
};
}
return info;
},
getSunPosition: function( date, lat, lng ) {
return getSunPosition( dateToJulianDate(date), -lng * deg2rad, lat * deg2rad );
}
};
})();
/*
var di = SunCalc.getDayInfo(data, lat, lng);
var sunrisePos = SunCalc.getSunPosition(di.sunrise.start, lat, lng);
var sunsetPos = SunCalc.getSunPosition(di.sunset.end, lat, lng);
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment