/ src / modules / LightSwitch / LightSwitchService / ThemeScheduler.cpp
ThemeScheduler.cpp
 1  #include "ThemeScheduler.h"
 2  #include <utility>
 3  
 4  SunTimes CalculateSunriseSunset(double latitude, double longitude, int year, int month, int day)
 5  {
 6      double zenith = 90.833;
 7      int N1 = static_cast<int>(floor(275.0 * month / 9.0));
 8      int N2 = static_cast<int>(floor((static_cast<double>(month) + 9) / 12.0));
 9      int N3 = static_cast<int>(floor((1.0 + floor((year - 4.0 * floor(year / 4.0) + 2.0) / 3.0))));
10      int N = N1 - (N2 * N3) + day - 30;
11  
12      auto calcTime = [&](bool sunrise) -> double {
13          double lngHour = longitude / 15.0;
14          double t = sunrise ? N + ((6 - lngHour) / 24) : N + ((18 - lngHour) / 24);
15  
16          double M = (0.9856 * t) - 3.289;
17          double L = M + (1.916 * sin(deg2rad(M))) + (0.020 * sin(2 * deg2rad(M))) + 282.634;
18          if (L < 0)
19              L += 360;
20          if (L > 360)
21              L -= 360;
22  
23          double RA = rad2deg(atan(0.91764 * tan(deg2rad(L))));
24          if (RA < 0)
25              RA += 360;
26          if (RA > 360)
27              RA -= 360;
28  
29          double Lquadrant = floor(L / 90) * 90;
30          double RAquadrant = floor(RA / 90) * 90;
31          RA = RA + (Lquadrant - RAquadrant);
32          RA /= 15;
33  
34          double sinDec = 0.39782 * sin(deg2rad(L));
35          double cosDec = cos(asin(sinDec));
36  
37          double cosH = (cos(deg2rad(zenith)) - (sinDec * sin(deg2rad(latitude)))) / (cosDec * cos(deg2rad(latitude)));
38          if (cosH > 1 || cosH < -1)
39              return -1;
40  
41          double H = sunrise ? 360 - rad2deg(acos(cosH)) : rad2deg(acos(cosH));
42          H /= 15;
43  
44          double T = H + RA - (0.06571 * t) - 6.622;
45          double UT = T - lngHour;
46          while (UT < 0)
47              UT += 24;
48          while (UT >= 24)
49              UT -= 24;
50  
51          return UT;
52      };
53  
54      double riseUT = calcTime(true);
55      double setUT = calcTime(false);
56  
57      auto toLocal = [](double UT) {
58          TIME_ZONE_INFORMATION tz;
59          DWORD state = GetTimeZoneInformation(&tz);
60          double totalBias = tz.Bias;
61  
62          if (state == TIME_ZONE_ID_DAYLIGHT)
63              totalBias += tz.DaylightBias;
64          else if (state == TIME_ZONE_ID_STANDARD)
65              totalBias += tz.StandardBias;
66  
67          double biasHours = -(totalBias / 60.0);
68          double localTime = UT + biasHours;
69  
70          while (localTime < 0)
71              localTime += 24;
72          while (localTime >= 24)
73              localTime -= 24;
74  
75          int hour = static_cast<int>(localTime);
76          int minute = static_cast<int>((localTime - hour) * 60);
77          return std::pair<int, int>{ hour, minute };
78      };
79  
80      auto [riseHour, riseMinute] = toLocal(riseUT);
81      auto [setHour, setMinute] = toLocal(setUT);
82  
83      SunTimes result;
84      result.sunriseHour = riseHour;
85      result.sunriseMinute = riseMinute;
86      result.sunsetHour = setHour;
87      result.sunsetMinute = setMinute;
88      return result;
89  }