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); */