float my_atan(float x) { if (x>0) { return (M_PI/2)*(0.596227*x + x*x)/(1 + 2*0.596227*x + x*x); } else { return -(my_atan(-x)); } }
float calcSun(int year, int month, int day, float latitude, float longitude, int sunset, float zenith) { int N1 = my_floor(275 * month / 9); int N2 = my_floor((month + 9) / 12); int N3 = (1 + my_floor((year - 4 * my_floor(year / 4) + 2) / 3)); int N = N1 - (N2 * N3) + day - 30; float lngHour = longitude / 15; float t; if (!sunset) { //if rising time is desired: t = N + ((6 - lngHour) / 24); } else { //if setting time is desired: t = N + ((18 - lngHour) / 24); } float M = (0.9856 * t) - 3.289; //calculate the Sun's true longitude //L = M + (1.916 * sin(M)) + (0.020 * sin(2 * M)) + 282.634 float L = M + (1.916 * my_sin((M_PI/180.0f) * M)) + (0.020 * my_sin((M_PI/180.0f) * 2 * M)) + 282.634; if (L<0) L+=360.0f; if (L>360) L-=360.0f; //5a. calculate the Sun's right ascension //RA = atan(0.91764 * tan(L)) float RA = (180.0f/M_PI) * my_atan(0.91764 * my_tan((M_PI/180.0f) * L)); if (RA<0) RA+=360; if (RA>360) RA-=360; //5b. right ascension value needs to be in the same quadrant as L float Lquadrant = (my_floor( L/90)) * 90; float RAquadrant = (my_floor(RA/90)) * 90; RA = RA + (Lquadrant - RAquadrant); //5c. right ascension value needs to be converted into hours RA = RA / 15; //6. calculate the Sun's declination float sinDec = 0.39782 * my_sin((M_PI/180.0f) * L); float cosDec = my_cos(my_asin(sinDec)); //7a. calculate the Sun's local hour angle //cosH = (cos(zenith) - (sinDec * sin(latitude))) / (cosDec * cos(latitude)) float cosH = (my_cos((M_PI/180.0f) * zenith) - (sinDec * my_sin((M_PI/180.0f) * latitude))) / (cosDec * my_cos((M_PI/180.0f) * latitude)); if (cosH > 1) { return 0; } else if (cosH < -1) { return 0; } //7b. finish calculating H and convert into hours float H; if (!sunset) { //if rising time is desired: H = 360 - (180.0f/M_PI) * my_acos(cosH); } else { //if setting time is desired: H = (180.0f/M_PI) * my_acos(cosH); } H = H / 15; //8. calculate local mean time of rising/setting float T = H + RA - (0.06571 * t) - 6.622; //9. adjust back to UTC float UT = T - lngHour; if (UT<0) {UT+=24;} if (UT>24) {UT-=24;} time_t now = time(NULL); struct tm *tick_time = localtime(&now); struct tm *gm_time = gmtime(&now); int timezoneoffset = 60 * (60 * (24 * (tick_time->tm_wday - gm_time->tm_wday) + tick_time->tm_hour - gm_time->tm_hour) + tick_time->tm_min - gm_time->tm_min); // Correct for transitions at the end of the week. int SECONDS_IN_WEEK=604800; if (timezoneoffset > SECONDS_IN_WEEK/2) timezoneoffset -= SECONDS_IN_WEEK; if (timezoneoffset < -SECONDS_IN_WEEK/2) timezoneoffset += SECONDS_IN_WEEK; timezoneoffset /= 3600; APP_LOG(APP_LOG_LEVEL_DEBUG, "timezone offset %d", timezoneoffset); APP_LOG(APP_LOG_LEVEL_DEBUG, "other timezone offset %d", (tick_time-gm_time)); // return UT+(tick_time-gm_time); return UT; }
float calcSun(int year, int month, int day, float latitude, float longitude, int sunset, float zenith) { int N1 = my_floor(275 * month / 9); int N2 = my_floor((month + 9) / 12); int N3 = (1 + my_floor((year - 4 * my_floor(year / 4) + 2) / 3)); int N = N1 - (N2 * N3) + day - 30; float lngHour = longitude / 15; float t; if (!sunset) { //if rising time is desired: t = N + ((6 - lngHour) / 24); } else { //if setting time is desired: t = N + ((18 - lngHour) / 24); } float M = (0.9856 * t) - 3.289; //calculate the Sun's true longitude //L = M + (1.916 * sin(M)) + (0.020 * sin(2 * M)) + 282.634 float L = M + (1.916 * my_sin((M_PI/180.0f) * M)) + (0.020 * my_sin((M_PI/180.0f) * 2 * M)) + 282.634; if (L<0) L+=360.0f; if (L>360) L-=360.0f; //5a. calculate the Sun's right ascension //RA = atan(0.91764 * tan(L)) float RA = (180.0f/M_PI) * my_atan(0.91764 * my_tan((M_PI/180.0f) * L)); if (RA<0) RA+=360; if (RA>360) RA-=360; //5b. right ascension value needs to be in the same quadrant as L float Lquadrant = (my_floor( L/90)) * 90; float RAquadrant = (my_floor(RA/90)) * 90; RA = RA + (Lquadrant - RAquadrant); //5c. right ascension value needs to be converted into hours RA = RA / 15; //6. calculate the Sun's declination float sinDec = 0.39782 * my_sin((M_PI/180.0f) * L); float cosDec = my_cos(my_asin(sinDec)); //7a. calculate the Sun's local hour angle //cosH = (cos(zenith) - (sinDec * sin(latitude))) / (cosDec * cos(latitude)) float cosH = (my_cos((M_PI/180.0f) * zenith) - (sinDec * my_sin((M_PI/180.0f) * latitude))) / (cosDec * my_cos((M_PI/180.0f) * latitude)); if (cosH > 1) { // no sunrise here on this day return 100; // watchface won't draw indicator if this value is found } else if (cosH < -1){ // no sunset here on this day return 100; // watchface won't draw indicator if this value is found } //7b. finish calculating H and convert into hours float H; if (!sunset) { //if rising time is desired: H = 360 - (180.0f/M_PI) * my_acos(cosH); } else { //if setting time is desired: H = (180.0f/M_PI) * my_acos(cosH); } H = H / 15; //8. calculate local mean time of rising/setting float T = H + RA - (0.06571 * t) - 6.622; //9. adjust back to UTC float UT = T - lngHour; if (UT<0) {UT+=24;} if (UT>24) {UT-=24;} return UT; }