private static double CalculateSunTime(int day, double latitude, double longitude, double zenith, bool getSunrise)
{
double lngHour, t, M, L, Lx, RA, RAx, Lquadrant, RAquadrant, sinDec, cosDec, cosH, H, T, UT, UTx;
// convert the longitude to hour value and calculate an approximate time
lngHour = longitude / 15;
if (getSunrise)
t = (double)day + ((6 - lngHour) / 24);
else
t = (double)day + ((18 - lngHour) / 24);
// calculate the sun's mean anomaly:
M = (0.9856 * t) - 3.289;
// step 4: calculate the sun's true longitude:
L = M + (1.916 * Math.Sin(ToRadians(M))) + (0.020 * Math.Sin(ToRadians(2 * M))) + 282.634;
while (L < 0)
{
Lx = L + 360;
Debug.Assert(Lx != L);
L = Lx;
}
while (L >= 360)
{
Lx = L - 360;
Debug.Assert(Lx != L);
L = Lx;
}
// calculate the sun's right ascension:
RA = ToDegrees(Math.Atan(0.91764 * Math.Tan(ToRadians(L))));
while (RA < 0)
{
RAx = RA + 360;
Debug.Assert(RAx != RA);
RA = RAx;
}
while (RA >= 360)
{
RAx = RA - 360;
Debug.Assert(RAx != RA);
RA = RAx;
}
// right ascension value needs to be in the same quadrant as L:
Lquadrant = Math.Floor(L / 90) * 90;
RAquadrant = Math.Floor(RA / 90) * 90;
RA = RA + (Lquadrant - RAquadrant);
// right ascension value needs to be converted into hours:
RA /= 15;
// calculate the sun's declination:
sinDec = 0.39782 * Math.Sin(ToRadians(L));
cosDec = Math.Cos(Math.Asin(sinDec));
// calculate the sun's local hour angle:
cosH = (Math.Cos(ToRadians(zenith)) - (sinDec * Math.Sin(ToRadians(latitude)))) / (cosDec * Math.Cos(ToRadians(latitude)));
// finish calculating H and convert into hours:
if (getSunrise)
H = 360 - ToDegrees(Math.Acos(cosH));
else
H = ToDegrees(Math.Acos(cosH));
H = H / 15;
// calculate local mean time:
T = H + RA - (0.06571 * t) - 6.622;
// convert to UTC:
UT = T - lngHour;
while (UT < 0)
{
UTx = UT + 24;
Debug.Assert(UTx != UT);
UT = UTx;
}
while (UT >= 24)
{
UTx = UT - 24;
Debug.Assert(UTx != UT);
UT = UTx;
}
return UT;
}