public static void GetSunRiseSet(TimeZoneInfo tz, DateTime dt, double longitude, double latitude, out float sunRiseStart, out float sunRiseEnd, out float sunSetStart, out float sunSetEnd) { // get julian day at noon var utcNoon = TimeZoneInfo.ConvertTimeToUtc(new DateTime(dt.Year, dt.Month, dt.Day, 12, 0, 0, DateTimeKind.Unspecified), tz); double jdayNoon = GetJulianDayFromGregorianDateTime(utcNoon); float sunUpperLimb = -0.833f; float sunLowerLimb = 3f; // more than lower limb at horizon to look better // magic double d = jdayNoon - 2451543.5; double w = 282.9404 + 4.70935E-5 * d; double e = 0.016709 - 1.151E-9 * d; double M = Degrees.Normalize(356.0470 + 0.9856002585 * d); double E = Degrees.Normalize(M + Radians.ToDegrees(e) * Degrees.Sin(M) * (1 + e * Degrees.Cos(M))); double xv = Degrees.Cos(E) - e; double yv = Degrees.Sin(E) * Math.Sqrt(1 - e * e); double lon = Degrees.Atan2(yv, xv) + w; double lat = 0; double rasc, decl; ConvertEclipticToEquatorial(jdayNoon, lon, lat, out rasc, out decl); double Ls = Degrees.Normalize(w + M); double GMST = Degrees.Normalize(Ls + 180); double UTSunInSouth = Degrees.Normalize(rasc - GMST - longitude) / 15.0f; var noonUtc = new DateTime(dt.Year, dt.Month, dt.Day, 12, 0, 0, DateTimeKind.Utc); var offset = tz.GetUtcOffset(noonUtc); double cosLHA = (Degrees.Sin(sunUpperLimb) - Degrees.Sin(latitude) * Degrees.Sin(decl)) / (Degrees.Cos(latitude) * Degrees.Cos(decl)); if (cosLHA < -1) { // never set sunRiseStart = 0; sunSetEnd = 24; } else if (cosLHA > 1) { // never rise sunRiseStart = 24; sunSetEnd = 0; } else { double LHA = Degrees.Acos(cosLHA); double convert = LHA / 15f; sunRiseStart = (float)(UTSunInSouth - convert + offset.TotalHours); sunSetEnd = (float)(UTSunInSouth + convert + offset.TotalHours); } cosLHA = (Degrees.Sin(sunLowerLimb) - Degrees.Sin(latitude) * Degrees.Sin(decl)) / (Degrees.Cos(latitude) * Degrees.Cos(decl)); if (cosLHA < -1) { // never set sunRiseEnd = 0; sunSetStart = 24; } else if (cosLHA > 1) { // never rise sunRiseEnd = 24; sunSetStart = 0; } else { double LHA = Degrees.Acos(cosLHA); double convert = LHA / 15f; sunRiseEnd = (float)(UTSunInSouth - convert + offset.TotalHours); sunSetStart = (float)(UTSunInSouth + convert + offset.TotalHours); } }