Celestial Programming : Rise and Set Algorithm

Julian Date:
Right Ascension:

\(\cos H_0 = \dfrac{\sin h_0 - \sin \varphi \sin \delta }{\cos \varphi \cos \delta}\)

If \(\cos H_0\) < -1 or > 1, the point is either always above or below the horizon.

\(T=(jd-2451545.0)/36525.0 \)

\(\Theta_0 = 280.46061837+360.98564736629*(jd-2451545.0)+0.000387933T^2 - T^3/38710000.0\)

\( \begin{cases} transit & \dfrac{\alpha + L - \Theta_0 }{360^{\circ}} \\ \\ rise & transit - \dfrac{H_0}{360^{\circ}} \\ \\ set & transit + \dfrac{H_0}{360^{\circ}} \end{cases} \)

\(jd\) is the Julian Date for the date in question.
\(\alpha\) Right Ascension
\(\delta\) Declination
\(L\) Longitude
\(\varphi\) Latitude
\(h_0\) Apparent rise or set angle, -0.8333 for the Sun, +0.125 for the Moon, and -0.5667 for most other objects.
\(\Theta_0\) Greenwich sidereal time at 0h for the day in question.

Below are common values of \(h_0\) for different events. While the twilight definitions are standardized, even legally defined in some places, the exact atmospheric effects will vary. The Golden Hour and Blue Hour are very loosely defined terms used in photography, so definitions may vary.

Sun Rise/Set-0.8333°
Moon Rise/Set+0.125°
Other Objects-0.5667°
Civil Twilight-6°
Nautical Twilight-12°
Astronomical Twilight-18°
Golden Hour+5° to -5°
Blue Hour-4° to -8°

The following equations are from "Easy PC Astronomy" by Peter Duffett-Smith.

\(A_s\) is the setting azimuth. \(A_r\) is the rising azimuth.

\(\cos A_r = \dfrac{\sin \delta + \sin h_0 \sin \varphi}{\cos h_0 \cos \varphi}\)

\(\cos A_s = 360 - A_r\)

The output is adjusted for the current time zone, which may differ from the time zone in effect for a different date (e.g. Daylight Saving Time)

A simplified implementation of the Rise, Set, and Transit algorithm from the book Astronomical Algorithms by Jean Meeus. For objects whose position changes significantly over the course of they day (e.g. the Sun or Moon) it's more accurate to iteravley re-compute the object's position for each specific time for the event you're interested in. The Sun is considered to be set when the entire Sun is below the horizon, not the center of it like for other objects. Also atmospheric refraction causes the visual setting of an object to be later than the actual, geometric setting. Meeus' recommeneded values for h0 are included in the code to correct for these effects, here I have hard coded the value for the Sun.

One important note, is that Meeus considers Longitudes in the West to be positive, and East negative, which is the opposite of how pretty much everything else works. So, if you're using GPS coordinates, remember to negate the longitude.

//By Greg Miller gmiller@gregmiller.net celestialprogramming.com
//Released as public domain
const toRad=Math.PI/180.0;
const toDeg=180.0/Math.PI;

//Corrects values to make them between 0 and 1
function constrain(v){
	if(v<0){return v+1;}
	if(v>1){return v-1;}
	return v;

//All angles must be in radians
//Outputs are times in hours GMT (not accounting for daylight saving time)
//From Meeus Page 101
function getRiseSet(jd,lat,lon,ra,dec){
	const h0=-0.8333 //For Sun
	//const h0=-0.5667 //For stars and planets
	//const h0=0.125   //For Moon

	const cosH=(Math.sin(h0*Math.PI/180.0)-Math.sin(lat)*Math.sin(dec)) / (Math.cos(lat)*Math.cos(dec));
	const H0=Math.acos(cosH)*180.0/Math.PI;

	const gmst=GMST(Math.floor(jd)+.5);

	const transit=(ra*toDeg+lon*toDeg-gmst)/360.0;
	const rise=transit-(H0/360.0);
	const set=transit+(H0/360.0);

	return [constrain(transit)*24.0,constrain(rise)*24.0,constrain(set)*24.0];

//Greenwhich mean sidreal time from Meeus page 87
//Input is julian date, does not have to be 0h
//Output is angle in degrees
function GMST(jd){
	const T=(jd-2451545.0)/36525.0;
	let st=280.46061837+360.98564736629*(jd-2451545.0)+0.000387933*T*T - T*T*T/38710000.0;

	return st;
	//return st*Math.PI/180.0;