#include <math.h>
#include <time.h>
#define PI 3.14159265358979323846
double calculateSunriseOrSunset(int year, int month, int day, double latitude, double longitude, int isSunrise)
{
struct tm *timeStruct;
time_t unixTime;
double daylightSaving;
// set time struct to local time
timeStruct = localtime(&unixTime);
timeStruct->tm_year = year - 1900;
timeStruct->tm_mon = month - 1;
timeStruct->tm_mday = day;
// calculate Julian date (days since Jan 1, 4713 B.C. Greenwich noon) at local noon
unixTime = mktime(timeStruct);
double julianDate = unixTime / 86400.0 + 2440587.5 - longitude / 360.0;
// calculate solar noon
double julianCenturies = (julianDate - 2451545) / 36525.0;
double meanSolarNoon = 12.0;
double eqOfTime = 229.18 * (0.000075 + 0.001868 * cos(julianCenturies * 2 * PI) - 0.032077 * sin(julianCenturies * 2 * PI) - 0.014615 * cos(julianCenturies * 4 * PI) - 0.040849 * sin(julianCenturies * 4 * PI));
double solarNoon = meanSolarNoon - longitude / 15.0 - eqOfTime / 60.0;
// calculate sunrise or sunset
double hourAngle = acos(-tan(latitude * PI / 180.0) * tan(23.45 * PI / 180.0 * cos(2 * PI * (julianDate - 2451545) / 365.0)));
if (isSunrise) {
daylightSaving = 1.0;
} else {
daylightSaving = -1.0;
}
double riseOrSetTime = 12.0 + daylightSaving * (hourAngle / PI) * 180.0 / 15.0 - (4.0 * (longitude / 15.0) - solarNoon);
return riseOrSetTime;
}
int main()
{
double latitude = 37.7749; // example latitude in degrees (San Francisco)
double longitude = -122.4194; // example longitude in degrees (San Francisco)
int year = 2022; // example year
int month = 1; // example month (January)
int day = 10; // example day
double sunriseTime = calculateSunriseOrSunset(year, month, day, latitude, longitude, 1); // calculate sunrise time
double sunsetTime = calculateSunriseOrSunset(year, month, day, latitude, longitude, 0); // calculate sunset time
return 0;
}
void GetSunRiseSunSet(double latitude, double longitude)
{
localtime.year = 23;
localtime.month = 7;
localtime.day = 13;
int DaysFromJan1 = localtime.day;
for(uint8_t i = 1; i < localtime.month; i++)
{
DaysFromJan1 += DaysOfMonth[i];
if((i == 2) && LeapYear(localtime.year))
{
DaysFromJan1++;
}
}
double g = RAD(357.528 + 0.9856 * DaysFromJan1);
double equation = (229.18 / 60) * (0.000075 + 0.001868 * cos(g) - 0.032077 * sin(g) - 0.014615 * cos(2 * g) - 0.040849 * sin(2 * g));
solarNoon = 12 - (longitude / 15) - equation; //太阳正午
double hour_angle = 57.29578 * acos(-tan(RAD(latitude)) * tan(RAD(23.45 * sin(2 * PI * (284 + DaysFromJan1) / 365.25))));
//double day_length = 2 * hour_angle;
timeDiff = hour_angle / 15;
//timeDiff = (4 * acos(-tan(RAD(latitude)) * tan(RAD(-23.44) * cos(2 * PI * (DaysFromJan1 - 81) / 365.25))) / PI) / 60;
sunriseTime = solarNoon - timeDiff; //日出时间
sunsetTime = solarNoon + timeDiff; //日落时间
sunriseTime = force_range(sunriseTime, 24);
sunsetTime = force_range(sunsetTime, 24);
sunrise[0] = (int)sunriseTime;
sunrise[1] = (int)((sunriseTime - sunrise[0])*60);
sunset[0] = (int)sunsetTime;
sunset[1] = (int)((sunsetTime - sunset[0])*60);
}
#define PI 3.14159265358979323846
double rad(double d)
{
return d * PI / 180.0;
}
int main()
{
double lat, decl, ha, sunrise, sunset;
int month, day, h, m, s;
printf("Enter latitude (positive for N, negative for S): ");
scanf("%lf", &lat);
printf("Enter month (1-12): ");
scanf("%d", &month);
printf("Enter day (1-31): ");
scanf("%d", &day);
double J = (month > 2 ? 1 : -1) * ((int)(365.25 * 4713) + (int)(30.6001 * 14) + day + 1720996.5) + ((int)(0.01 * (month > 2 ? 4713 : 4712))) - ((int)(0.01 * (month > 2 ? 4713 : 4712)) / 4);
double N = J - 2451545.0 + 0.0008;
double g = rad((357.5291 + 0.98560028 * N));
double c = rad((1.9148 * sin(g)) + (0.02 * sin(2 * g)) + (0.0003 * sin(3 * g)));
double lambda = rad((280.4603 + c + 0.9856474 * N));
double delta = asin(sin(lambda) * sin(rad(23.45)));
decl = (180.0 / PI) * delta;
ha = acos(cos(rad(90.833)) / (cos(rad(lat)) * cos(delta)) - tan(rad(lat)) * tan(delta));
sunrise = 12.0 - (ha / PI) * 12.0;
sunset = 12.0 + (ha / PI) * 12.0;
h = (int)sunrise;
m = (int)((sunrise - h) * 60);
s = (int)((((sunrise - h) * 60) - m) * 60);
printf("Sunrise time: %02d:%02d:%02d\\n", h, m, s);
h = (int)sunset;
m = (int)((sunset - h) * 60);
s = (int)((((sunset - h) * 60) - m) * 60);
printf("Sunset time: %02d:%02d:%02d\\n", h, m, s);
return 0;
}
UTC时间转当地时间
一、首先通过经纬度来计算出所在地时区
// 计算时区函数,根据经度来计算
static int calculateTimezone(double lat,double lon){
int a,b,c,timezone;
a = (int)(fabs(lon)+0.5);// 对经度进行四舍五入,且取正整数
b = a/15; // 商
c = a%15; // 余数
if((lat >=17.9 && lat <=53 && lon>=75 && lon<=125) || (lat>=40 && lat <=53 && lon>=125 && lon<= 135)){// 如果经纬度处于中国版图内,则都划为东8区,为什么要这样划分详见第三节
timezone = 8;
}
else{
if(c > 7.5)
timezone = b+1;
else
timezone = b;
if(lon > 0.0f)
timezone = timezone;
else
timezone = (-1)*timezone;
}
return timezone;
}
二、将UTC时间转换为本地时间
// UTC时间转换为本地时间函数
static void UTCTOLocalTime(int timezone){
int year,month,day,hour;
int lastday = 0;// 月的最后一天的日期
int lastlastday = 0;// 上月的最后一天的日期
year = gpsData.UTCTime.year; //已知的UTC时间
month = gpsData.UTCTime.month;//已知的UTC时间
day = gpsData.UTCTime.day;//已知的UTC时间
hour = gpsData.UTCTime.hour + timezone; //已知的UTC时间
if(month==1 || month==3 || month==5 || month==7 || month==8 || month==10 || month==12){
lastday = 31;
lastlastday = 30;
if(month == 3){
if((year%400 == 0)||(year%4 == 0 && year%100 != 0))//判断是否为闰年,年号能被400整除或年号能被4整除,而不能被100整除为闰年
lastlastday = 29;// 闰年的2月为29天,平年为28天
else
lastlastday = 28;
}
if(month == 8)
lastlastday = 31;
}
else if(month == 4 || month == 6 || month == 9 || month == 11){
lastday = 30;
lastlastday = 31;
}
else{
lastlastday = 31;
if((year%400 == 0)||(year%4 == 0 && year%100 != 0))// 闰年的2月为29天,平年为28天
lastday = 29;
else
lastday = 28;
}
if(hour >= 24){// 当算出的区时大于或等于24:00时,应减去24:00,日期加一天
hour -= 24;
day += 1;
if(day > lastday){ // 当算出的日期大于该月最后一天时,应减去该月最后一天的日期,月份加上一个月
day -= lastday;
month += 1;
if(month > 12){// 当算出的月份大于12时,应减去12,年份加上一年
month -= 12;
year += 1;
}
}
}
if(hour < 0){// 当算出的区时为负数时,应加上24:00,日期减一天
hour += 24;
day -= 1;
if(day < 1){ // 当算出的日期为0时,日期变为上一月的最后一天,月份减去一个月
day = lastlastday;
month -= 1;
if(month < 1){ // 当算出的月份为0时,月份变为12月,年份