#include <stdint.h>
#include <math.h>
#define tl_hour 0
#define tl_minute 1
#define tl_second 2
#define tl_day 3
#define tl_month 4
#define tl_year 5
// Часы, Минуты, Секунды, Число, Месяц, Год
uint16_t dt[] = {0, 0, 0, 5, 5, 2019};
// Широта и долгота
float latitude=55.708102, longitude=36.794008;
// Часовая зона в минутах (часы * 60)
int timezone=3*60;
uint8_t ComputeSun(uint8_t rs);
int main()
{
ComputeSun(1); // Восход
ComputeSun(0); // Заход
return 0;
}
uint8_t IsLeapYear(int yr){
return ( (yr % 4 == 0 && yr % 100 != 0) || yr % 400 == 0);
}
uint8_t LengthOfMonth(uint16_t * when){
uint8_t odd, mnth;
int yr;
yr=when[tl_year]+2000;
mnth=when[tl_month];
if(mnth==2){
if(IsLeapYear(yr) ) return 29;
return 28;
}
odd=(mnth & 1) == 1;
if (mnth > 7) odd = !odd;
if (odd) return 31;
return 30;
}
int Absolute(int n){
if(n<0) return 0-n;
return n;
}
char Signum(int n){
if(n<0) return -1;
return 1;
}
long DayNumber(uint16_t y, uint8_t m, uint8_t d){
m = (m + 9) % 12;
y = y - m/10;
return 365*y + y/4 - y/100 + y/400 + (m*306 + 5)/10 + d - 1 ;
}
void Adjust(long offset){
long tmp, mod, nxt;
// offset is in minutes
tmp=dt[tl_minute]+offset; // minutes
nxt=tmp/60; // hours
mod=Absolute(tmp) % 60;
mod=mod*Signum(tmp)+60;
mod %= 60;
dt[tl_minute]=mod;
tmp=nxt+dt[tl_hour];
nxt=tmp/24; // days
mod=Absolute(tmp) % 24;
mod=mod*Signum(tmp)+24;
mod %= 24;
dt[tl_hour]=mod;
tmp=nxt+dt[tl_day];
mod=LengthOfMonth(dt);
dt[tl_day] = tmp;
if(tmp>mod){
while (tmp>mod) {
tmp -= mod;
dt[tl_month]++;
if (dt[tl_month] > 12) {
dt[tl_month] = 1;
dt[tl_year]++;
dt[tl_year] += 100;
dt[tl_year] %= 100;
}
mod = LengthOfMonth(dt);
}
dt[tl_day]=tmp;
} else if (tmp<1) {
while (tmp<1) {
dt[tl_month]--;
if (dt[tl_month] < 1) {
dt[tl_month] = 12;
dt[tl_year] --;
dt[tl_year] += 100;
dt[tl_year] %= 100;
}
mod=LengthOfMonth(dt);
dt[tl_day]=tmp+mod;
tmp += mod;
}
}
}
uint8_t ComputeSun(uint8_t rs) {
uint8_t month, day;
float y, decl, eqt, ha, lon, lat;
uint8_t a;
int minutes;
month=dt[tl_month]-1;
day=dt[tl_day]-1;
lon=-longitude/57.295779513082322;
lat=latitude/57.295779513082322;
//approximate hour;
a=6;
if(rs) a=18;
// approximate day of year
y= month * 30.4375 + day + a/24.0; // 0... 365
// compute fractional year
y *= 1.718771839885e-02; // 0... 1
// compute equation of time... .43068174
eqt=229.18 * (0.000075+0.001868*cos(y) -0.032077*sin(y) -0.014615*cos(y*2) -0.040849*sin(y* 2) );
// compute solar declination... -0.398272
decl=0.006918-0.399912*cos(y)+0.070257*sin(y)-0.006758*cos(y*2)+0.000907*sin(y*2)-0.002697*cos(y*3)+0.00148*sin(y*3);
//compute hour angle
ha=( cos(1.585340737228125) / (cos(lat)*cos(decl)) -tan(lat) * tan(decl) );
if(fabs(ha)>1.0){// we're in the (ant)arctic and there is no rise(or set) today!
return 0;
}
ha=acos(ha);
if(rs==0) ha=-ha;
// compute minutes from midnight
minutes=(int) (720+4*(lon-ha)*57.295779513082322-eqt);
// convert from UTC back to our timezone
minutes+= timezone;
// adjust the time array by minutes
dt[tl_hour]=0;
dt[tl_minute]=0;
dt[tl_second]=0;
Adjust(minutes);
return 1;
}