Sun Calculation Function
Friday, October 29, 2021 1:50pm
Here is a JavaScript function that calculates the civil twilight start/end and sunrise/sunset times for a given latitude, longitude, and unix timestamp. (Note: the timestamp is in seconds, so the result of Date.now() needs to be divided by 1000 for this to work properly.) I use this function along with IP geolocation to change the colors on the page as the visitor's day shifts from daylight to dark.
This code was adapted from the information provided here.
function calcSunset( lat, lon, timestamp ) { function fmod( f, d ) { let i = Math.floor( f / d ); return f - i * d; } function deg2rad( r ) { return r * ( Math.PI / 180 ); } function rad2deg( r ) { return r * 180 / Math.PI; } let jDate = ( timestamp / 86400.0 ) + 2440587.5; let n = Math.round( ( jDate - 2451545 - 0.0009 ) - ( lon / 360 ) ); let jp = 2451545 + 0.0009 + ( lon / 360 ) + n; let rjp = jp; let l = null; let jTrans = null; let M = null; for( let i = 0; i < 5; i++ ) { M = fmod( 357.5291 + 0.98560028 * ( rjp - 2451545 ), 360 ); let C = ( 1.9148 * Math.sin( deg2rad( M ) ) ) + ( 0.0200 * Math.sin( deg2rad( 2 * M ) ) ) + ( 0.0003 * Math.sin( deg2rad( 3 * M ) ) ); l = fmod( M + 102.9372 + C + 180, 360 ); jTrans = jp + ( 0.0053 * Math.sin( deg2rad( M ) ) ) - ( 0.0069 * Math.sin( deg2rad( 2 * l ) ) ); rjp = jTrans; } let theta = rad2deg( Math.asin( Math.sin( deg2rad( l ) ) * Math.sin( deg2rad( 23.45 ) ) ) ); let H = rad2deg( Math.acos( ( Math.sin( deg2rad( -0.83 ) ) - Math.sin( deg2rad( lat ) ) * Math.sin( deg2rad( theta ) ) ) / ( Math.cos( deg2rad( lat ) ) * Math.cos( deg2rad( theta ) ) ) ) ); let jpp = 2451545 + 0.0009 + (( H + lon ) / 360 ) + n; let jSet = jpp + ( 0.0053 * Math.sin( deg2rad( M ) ) ) - ( 0.0069 * Math.sin( deg2rad( 2 * l ) ) ); let jRise = jTrans - ( jSet - jTrans ); let sunset = ( jSet - 2440587.5 ) * 86400; let sunrise = ( jRise - 2440587.5 ) * 86400; H = rad2deg( Math.acos( ( Math.sin( deg2rad( -6.83 ) ) - Math.sin( deg2rad( lat ) ) * Math.sin( deg2rad( theta ) ) ) / ( Math.cos( deg2rad( lat ) ) * Math.cos( deg2rad( theta ) ) ) ) ); jpp = 2451545 + 0.0009 + (( H + lon ) / 360 ) + n; jSet = jpp + ( 0.0053 * Math.sin( deg2rad( M ) ) ) - ( 0.0069 * Math.sin( deg2rad( 2 * l ) ) ); jRise = jTrans - ( jSet - jTrans ); let eveningTwilight = ( jSet - 2440587.5 ) * 86400; let morningTwilight = ( jRise - 2440587.5 ) * 86400; return { morningTwilight: morningTwilight; sunrise: sunrise; sunset: sunset; eveningTwilight: eveningTwilight; }; }