31QPair<QDateTime, QDateTime> 
calculateSunTimings(
const QDateTime &dateTime, 
double latitude, 
double longitude, 
bool morning)
 
   37    const double rad = M_PI / 180.;
 
   38    const double earthObliquity = 23.4397; 
 
   40    const double lat = latitude; 
 
   41    const double lng = -longitude; 
 
   44    const QDateTime utcDateTime = dateTime.toUTC();
 
   45    const double juPrompt = utcDateTime.date().toJulianDay(); 
 
   46    const double ju2000 = 2451545.; 
 
   49    auto mod360 = [](
double number) -> 
double {
 
   50        return std::fmod(number, 360.);
 
   53    auto sin = [&rad](
double angle) -> 
double {
 
   54        return std::sin(angle * rad);
 
   56    auto cos = [&rad](
double angle) -> 
double {
 
   57        return std::cos(angle * rad);
 
   59    auto asin = [&rad](
double val) -> 
double {
 
   60        return std::asin(val) / rad;
 
   62    auto acos = [&rad](
double val) -> 
double {
 
   63        return std::acos(val) / rad;
 
   66    auto anomaly = [&](
const double date) -> 
double { 
 
   67        return mod360(357.5291 + 0.98560028 * (date - ju2000));
 
   70    auto center = [&sin](
double anomaly) -> 
double { 
 
   71        return 1.9148 * sin(anomaly) + 0.02 * sin(2 * anomaly) + 0.0003 * sin(3 * anomaly);
 
   74    auto ecliptLngMean = [](
double anom) -> 
double { 
 
   75        return anom + 282.9372; 
 
   78    auto ecliptLng = [&](
double anom) -> 
double { 
 
   79        return ecliptLngMean(anom) + center(anom);
 
   82    auto declination = [&](
const double date) -> 
double { 
 
   83        const double anom = anomaly(date);
 
   84        const double eclLng = ecliptLng(anom);
 
   86        return mod360(asin(sin(earthObliquity) * sin(eclLng)));
 
   90    auto hourAngle = [&](
const double date, 
double angle) -> 
double { 
 
   91        const double decl = declination(date);
 
   92        const double ret0 = (sin(angle) - sin(lat) * sin(decl)) / (cos(lat) * cos(decl));
 
   94        double ret = mod360(acos(ret0));
 
  106    auto getTransit = [&](
const double date) -> 
double { 
 
  107        const double juMeanSolTime = juPrompt - ju2000 - 0.0009 - lng / 360.; 
 
  108        const double juTrEstimate = date + qRound64(juMeanSolTime) - juMeanSolTime; 
 
  109        const double anom = anomaly(juTrEstimate); 
 
  110        const double eclLngM = ecliptLngMean(anom); 
 
  112        return juTrEstimate + 0.0053 * sin(anom) - 0.0068 * sin(2 * eclLngM);
 
  115    auto getSunMorning = [&hourAngle](
const double angle, 
const double transit) -> 
double {
 
  116        return transit - hourAngle(transit, angle) / 360.;
 
  119    auto getSunEvening = [&hourAngle](
const double angle, 
const double transit) -> 
double {
 
  120        return transit + hourAngle(transit, angle) / 360.;
 
  128    const double juNoon = getTransit(juPrompt);
 
  133        end = getSunMorning(
SUN_HIGH, juNoon);
 
  135        begin = getSunEvening(
SUN_HIGH, juNoon);
 
  142    QDateTime dateTimeBegin;
 
  143    QDateTime dateTimeEnd;
 
  145    if (!std::isnan(begin)) {
 
  146        const double dayFraction = begin - int(begin);
 
  147        const QTime utcTime = QTime::fromMSecsSinceStartOfDay(dayFraction * MSC_DAY);
 
  148        const QTime localTime = convertToLocalTime(dateTime, utcTime);
 
  149        dateTimeBegin = QDateTime(dateTime.date(), localTime);
 
  152    if (!std::isnan(end)) {
 
  153        const double dayFraction = end - int(end);
 
  154        const QTime utcTime = QTime::fromMSecsSinceStartOfDay(dayFraction * MSC_DAY);
 
  155        const QTime localTime = convertToLocalTime(dateTime, utcTime);
 
  156        dateTimeEnd = QDateTime(dateTime.date(), localTime);
 
  159    return {dateTimeBegin, dateTimeEnd};