12#include "sunriseset.h"
17static const double MaxLat = 89.99;
18static const double MaxLong = 179.99;
20using namespace KHolidays;
21using namespace SunRiseSet;
25 return (degree * std::numbers::pi) / 180.00;
30 return (rad * 180.0) / std::numbers::pi;
34static double calcTimeJulianCent(
int jday)
36 return (
double(jday) - 2451545.0) / 36525.0;
40static double calcMeanObliquityOfEcliptic(
double t)
42 double seconds = 21.448 - t * (46.8150 + t * (0.00059 - t * 0.001813));
43 double e0 = 23.0 + (26.0 + (seconds / 60.0)) / 60.0;
48static double calcObliquityCorrection(
double t)
50 double e0 = calcMeanObliquityOfEcliptic(t);
51 double omega = 125.04 - 1934.136 * t;
52 double e = e0 + 0.00256 * cos(
degToRad(omega));
57static double calcGeomMeanLongSun(
double t)
59 double L0 = 280.46646 + t * (36000.76983 + 0.0003032 * t);
70static double calcGeomMeanAnomalySun(
double t)
72 double M = 357.52911 + t * (35999.05029 - 0.0001537 * t);
77static double calcSunEqOfCenter(
double t)
79 double m = calcGeomMeanAnomalySun(t);
81 double sinm = sin(mrad);
82 double sin2m = sin(mrad + mrad);
83 double sin3m = sin(mrad + mrad + mrad);
84 double C = (sinm * (1.914602 - t * (0.004817 + 0.000014 * t))
85 + sin2m * (0.019993 - 0.000101 * t)
91static double calcSunTrueLong(
double t)
93 double l0 = calcGeomMeanLongSun(t);
94 double c = calcSunEqOfCenter(t);
100static double calcSunApparentLong(
double t)
102 double o = calcSunTrueLong(t);
103 double omega = 125.04 - 1934.136 * t;
104 double lambda = o - 0.00569 - 0.00478 * sin(
degToRad(omega));
109static double calcSunDeclination(
double t)
111 double e = calcObliquityCorrection(t);
112 double lambda = calcSunApparentLong(t);
115 double theta =
radToDeg(asin(sint));
120static double calcEccentricityEarthOrbit(
double t)
122 double e = 0.016708634 - t * (0.000042037 + 0.0000001267 * t);
128static double calcEquationOfTime(
double t)
130 double epsilon = calcObliquityCorrection(t);
131 double l0 = calcGeomMeanLongSun(t);
132 double e = calcEccentricityEarthOrbit(t);
133 double m = calcGeomMeanAnomalySun(t);
135 double y = tan(
degToRad(epsilon) / 2.0);
138 double sin2l0 = sin(2.0 *
degToRad(l0));
140 double cos2l0 = cos(2.0 *
degToRad(l0));
141 double sin4l0 = sin(4.0 *
degToRad(l0));
142 double sin2m = sin(2.0 *
degToRad(m));
145 double Etime = (y * sin2l0
147 + 4.0 * e * y * sinm * cos2l0
148 - 0.5 * y * y * sin4l0
149 - 1.25 * e * e * sin2m);
155static constexpr const double Sunrise = -0.833;
156static constexpr const double CivilTwilight = -6.0;
158static constexpr const double Up = 1.0;
159static constexpr const double Down = -1.0;
162static double calcHourAngleSunrise(
double latitude,
double solarDec,
double sunHeight)
166 double HAarg = (cos(
degToRad(90.0 - sunHeight)) / (cos(latRad) * cos(sdRad)) - tan(latRad) * tan(sdRad));
167 double HA = acos(HAarg);
171static QTime calcSunEvent(
const QDate &date,
double latitude,
double longitude,
double sunHeight,
double direction)
173 latitude = qMax(qMin(MaxLat, latitude), -MaxLat);
174 longitude = qMax(qMin(MaxLong, longitude), -MaxLong);
177 double eqTime = calcEquationOfTime(t);
178 double solarDec = calcSunDeclination(t);
179 double hourAngle = direction * calcHourAngleSunrise(latitude, solarDec, sunHeight);
180 double delta = longitude +
radToDeg(hourAngle);
181 if (std::isnan(delta)) {
185 timeUTC = timeUTC.addSecs((720 - (4.0 * delta) - eqTime) * 60);
188 if (timeUTC.second() > 29) {
189 return QTime(timeUTC.hour(), timeUTC.minute()).
addSecs(60);
191 return QTime(timeUTC.hour(), timeUTC.minute());
196 return calcSunEvent(date, latitude, longitude, Sunrise, Up);
201 return calcSunEvent(date, latitude, longitude, Sunrise, Down);
206 return calcSunEvent(date, latitude, longitude, CivilTwilight, Up);
211 return calcSunEvent(date, latitude, longitude, CivilTwilight, Down);
217 const double t = calcTimeJulianCent(date.
toJulianDay());
218 const double solarDec = calcSunDeclination(t);
219 const double maxSolarZenithAngle = 180.0 - std::abs(latitude + solarDec);
221 return maxSolarZenithAngle <= 90.0 - Sunrise;
226 const double t = calcTimeJulianCent(date.
toJulianDay());
227 const double solarDec = calcSunDeclination(t);
228 const double minSolarZenithAngle = std::abs(latitude - solarDec);
230 return minSolarZenithAngle > 90.0 - Sunrise && minSolarZenithAngle <= 90.0 - CivilTwilight;
235 const double t = calcTimeJulianCent(date.
toJulianDay());
236 const double solarDec = calcSunDeclination(t);
237 const double minSolarZenithAngle = std::abs(latitude - solarDec);
239 return minSolarZenithAngle > 90.0 - CivilTwilight;
KHOLIDAYS_EXPORT bool isPolarTwilight(const QDate &date, double latitude)
Checks whether it is polar twilight on day date at latitude.
KHOLIDAYS_EXPORT QTime utcSunset(const QDate &date, double latitude, double longitude)
Compute the sunset time (UTC) for a date and Earth location.
KHOLIDAYS_EXPORT QTime utcSunrise(const QDate &date, double latitude, double longitude)
Compute the sunrise time (UTC) for a date and Earth location.
KHOLIDAYS_EXPORT bool isPolarDay(const QDate &date, double latitude)
Checks whether it is polar day on day date at latitude.
KHOLIDAYS_EXPORT bool isPolarNight(const QDate &date, double latitude)
Checks whether it is polar night on day date at latitude.
KHOLIDAYS_EXPORT QTime utcDawn(const QDate &date, double latitude, double longitude)
Compute the civil dawn time (UTC) for a date and Earth location.
KHOLIDAYS_EXPORT QTime utcDusk(const QDate &date, double latitude, double longitude)
Compute the civil dawn time (UTC) for a date and Earth location.
constexpr double radToDeg(double rad)
constexpr double degToRad(double deg)
qint64 toJulianDay() const const
QTime addSecs(int s) const const