Example #1
0
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;
}
/* not quite rint(), i.e. results not properly rounded to nearest-or-even */
float my_rint (float x)
{
  float t = my_floor (my_fabs(x) + 0.5);
  return (x < 0.0) ? -t : t;
}
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;
}