Intereting Posts
Утечка памяти в собственном коде JNI AttributeError: объект ‘module’ не имеет атрибута при попытке импортировать c-код в python Что гарантирует считывание / запись операндов в желаемое время с расширенным ASM? Ошибка сегментации при использовании strcpy? Как ссылаться на статическую библиотеку в C? Учитывая дату / время в виде строки, каков наилучший способ узнать, был ли это DST в то время? Каковы различия между этими двумя стилями typedef в C? Почему этот пример застрял в бесконечном цикле в C? Сколько памяти calloc и malloc могут выделять? Консольное приложение Windows – сигнал для закрытия события Простая побитовая манипуляция для мало-endian целых чисел, в машинах большого размера? Каково правильное использование printf для отображения указателей, дополненных 0s Когда «sizeof» применяется к строке, почему она возвращает свой размер (как strlen)? Как работает хвостовая recursion? Типы варвардов в C с gcc

время восхода солнца в c

В моем приложении C я хочу рассчитать время восхода / захода солнца для заданной даты, широты и долготы. я искал в сети, но я не могу найти рабочий образец.

Я попытался реализовать этот образец: http://souptonuts.sourceforge.net/code/sunrise.c.html

Но этот образец не работал правильно.

Есть ли простой исходный код или метод C, которые я могу легко реализовать в своем приложении?

Редактировать:
Я реализую код по этой ссылке, но это дало мне неправильные значения захода / восхода солнца. Также я попробовал ссылку Саула здесь, но это тоже дало мне неправильный результат.
У меня 41N, 28E. Когда я пытаюсь использовать коды, оба образца говорят, что значение восхода примерно 10:13, а закат – 23:24. Но правильные значения – 06:06, 20:13.
Я не могу понять проблему.

Код примера работает в VC ++ 2010 с несколькими незначительными изменениями:

  • Скомпилируйте его как файл C ++, а не C.
  • Удалите строку #include .
  • Добавьте #define _USE_MATH_DEFINES в верхней части файла, чтобы определить M_PI.
  • Измените два %T в вызовах strftime() на %X

Теперь, когда у вас есть рабочий образец, вы можете отлаживать рабочую версию и вашу версию, чтобы увидеть, где расчёт начинает различаться и сужаться по проблеме. Любой шаг через программу или либеральное использование временного вызова printf() очень похож на образец.

Если вам нужна конкретная помощь, вам придется опубликовать свой код (либо ссылку на весь файл, либо определенные fragmentы, с которыми вам нужна помощь).

Десять простых шагов для расчета времени восхода / захода солнца с учетом даты, широты и долготы

  1. сначала рассчитать день года

    N1 = пол (275 * месяц / 9) N2 = пол ((месяц + 9) / 12) N3 = (1 + пол ((год – 4 * пол (год / 4) + 2) / 3)) N = N1 – (N2 * N3) + день – 30

  2. преобразовать значение долготы в час и рассчитать приблизительное время

    lngHour = долгота / 15

    если требуется время нарастания: t = N + ((6 – lngHour) / 24), если требуется время установки: t = N + ((18 – lngHour) / 24)

  3. вычислить среднюю аномалию Солнца

    M = (0,9856 * т) – 3,289

  4. вычислить истинную долготу Солнца

    L = M + (1,916 * sin (M)) + (0,020 * sin (2 * M)) + 282,634 ПРИМЕЧАНИЕ: L возможно необходимо отрегулировать в диапазоне [0,360) путем добавления / вычитания 360

5а. вычислить прямое восхождение Солнца

 RA = atan(0.91764 * tan(L)) NOTE: RA potentially needs to be adjusted into the range [0,360) by adding/subtracting 360 

5б. значение прямого восхождения должно быть в том же квадранте, что и L

 Lquadrant = (floor( L/90)) * 90 RAquadrant = (floor(RA/90)) * 90 RA = RA + (Lquadrant - RAquadrant) 

5с. значение прямого восхождения необходимо преобразовать в часы

 RA = RA / 15 
  1. рассчитать склонение Солнца

    sinDec = 0,399782 * sin (L) cosDec = cos (asin (sinDec))

7а. вычислить локальный часовой угол Солнца

 cosH = (cos(zenith) - (sinDec * sin(latitude))) / (cosDec * cos(latitude)) if (cosH > 1) the sun never rises on this location (on the specified date) if (cosH < -1) the sun never sets on this location (on the specified date) 

7b. завершить вычисление H и преобразовать в часы

 if if rising time is desired: H = 360 - acos(cosH) if setting time is desired: H = acos(cosH) H = H / 15 
  1. рассчитать местное среднее время подъема / установки

    T = H + RA - (0,06571 * т) - 6,622

  2. вернуться к UTC

    UT = T - lngHour ПРИМЕЧАНИЕ: UT может быть необходимо отрегулировать в диапазоне [0,24) путем добавления / вычитания 24

  3. конвертировать значение UT в местный часовой пояс широты / долготы

    localT = UT + localOffset

Это довольно легко реализовать:
http://edwilliams.org/sunrise_sunset_algorithm.htm

Существует решение ac с объектной c-оболочкой для восхода / установки: https://github.com/berkley/ObjectiveCUtil

Возможно, попробуйте этот кусок кода. Он протестирован и работает. Надеюсь, вам понравится …

 #include "stdafx.h" #include  #include  #include  using namespace std; //STANDARD CONSTANTS double pi = 3.1415926535; // Pi double solarConst = 1367; // solar constant Wm-2 // Function to convert radian to hours double RadToHours (double tmp) { //double pi = 3.1415926535; // Pi return (tmp * 12 / pi); } // Function to convert hours to radians double HoursToRads (double tmp) { //double pi = 3.1415926535; // Pi return (tmp * pi / 12); } // Function to calculate the angle of the day double AngleOfDay (int day, // number of the day int month, // number of the month int year // year ) { // local vars int i, leap; int numOfDays = 0; // number of Day 13 Nov=317 int numOfDaysofMonths[12] = {0,31,28,31,30,31,30,31,31,30,31,30}; // Number of days per month int AllYearDays; // Total number of days in a year 365 or 366 double DayAngle; // angle of the day (radian) //double pi = 3.1415926535; // Pi // leap year ?? leap = 0; if ((year % 400)==0) { AllYearDays = 366; leap = 1; } else if ((year % 100)==0) AllYearDays = 365; else if ((year % 4)==0) { AllYearDays = 366; leap = 1; } else AllYearDays = 365; // calculate number of day for (i=0;i 2) && leap) numOfDays++; numOfDays += day; // calculate angle of day DayAngle = (2*pi*(numOfDays-1)) / AllYearDays; return DayAngle; } // Function to calculate declination - in radian double Declination (double DayAngle // angle day in radian ) { double SolarDeclination; // Solar declination (radian) SolarDeclination = 0.006918 - 0.399912 * cos (DayAngle) + 0.070257 * sin (DayAngle) - 0.006758 * cos (2*DayAngle) + 0.000907 * sin (2*DayAngle) - 0.002697 * cos (3*DayAngle) + 0.00148 * sin (3*DayAngle); return SolarDeclination; } // Function to calculate Equation of time ( et = TSV - TU ) double EqOfTime (double DayAngle // angle day (radian) ) { double et; // Equation of time (radian) et = 0.000075 + 0.001868 * cos (DayAngle) - 0.032077 * sin (DayAngle) - 0.014615 * cos (2*DayAngle) - 0.04089 * sin (2*DayAngle); // Equation of time in hours et = RadToHours(et); return et; } // Calculation of the duration of the day in radian double DayDurationRadian (double _declination, // _declination in radian double lat // latitude in radian ) { double dayDurationj; dayDurationj = 2 * acos( -tan(lat) * tan(_declination) ); return dayDurationj; } // Function to calculate Day duration in Hours double DayDuratInHours (double _declination // _declination in radian , double lat // latitude in radian ) { double dayDurationj; dayDurationj = DayDurationRadian(_declination, lat); dayDurationj = RadToHours(dayDurationj); return dayDurationj; } // Function to calculate the times TSV-UTC double Tsv_Tu (double rlong // longitude en radian positive al est. ,double eqOfTime // Equation of times en heure ) { double diffUTC_TSV; double pi = 3.1415926535; // Pi // diffUTC_TSV Solar time as a function of longitude and the eqation of time diffUTC_TSV = rlong * (12 / pi) + eqOfTime; // difference with local time return diffUTC_TSV; } // Calculations of the orbital excentricity double Excentricity(int day, int month, int year) { double dayAngleRad, E0; // calculate the angle of day in radian dayAngleRad = AngleOfDay(day, month, year); // calculate the excentricity E0 = 1.000110 + 0.034221 * cos(dayAngleRad) + 0.001280 * sin(dayAngleRad) +0.000719 * cos(2*dayAngleRad) +0.000077 * sin(2*dayAngleRad); return E0; } // Calculate the theoretical energy flux for the day radiation double TheoreticRadiation(int day, int month, int year, double lat // Latitude in radian ! ) { double RGth; // Theoretical radiation double decli; // Declination double E0; double sunriseHourAngle; // Hour angle of sunset // Calculation of the declination in radian decli = Declination (AngleOfDay(day, month, year)); // Calcuate excentricity E0 = Excentricity(day, month, year); // Calculate hour angle in radian sunriseHourAngle = DayDurationRadian(decli, lat) / 2; // Calculate Theoretical radiation en Wm-2 RGth = solarConst * E0 * (cos(decli)*cos(lat)*sin(sunriseHourAngle)/sunriseHourAngle + sin(decli)*sin(lat)); return RGth; } // Function to calculate decimal hour of sunrise: result in local hour double CalclulateSunriseLocalTime(int day, int month, int year, double rlong, double rlat) { // local variables int h1, h2; time_t hour_machine; struct tm *local_hour, *gmt_hour; double result; // Calculate the angle of the day double DayAngle = AngleOfDay(day, month, year); // Declination double SolarDeclination = Declination(DayAngle); // Equation of times double eth = EqOfTime(DayAngle); // True solar time double diffUTC_TSV = Tsv_Tu(rlong,eth); // Day duration double dayDurationj = DayDuratInHours(SolarDeclination,rlat); // local time adjust time( &hour_machine ); // Get time as long integer. gmt_hour = gmtime( &hour_machine ); h1 = gmt_hour->tm_hour; local_hour = localtime( &hour_machine ); // local time. h2 = local_hour->tm_hour; // final result result = 12 - fabs(dayDurationj / 2) - diffUTC_TSV + h2-h1; return result; } // Function to calculate decimal hour of sunset: result in local hour double CalculateSunsetLocalTime(int day, int month, int year, double rlong, double rlat) { // local variables int h1, h2; time_t hour_machine; struct tm *local_hour, *gmt_hour; double result; // Calculate the angle of the day double DayAngle = AngleOfDay(day, month, year); // Declination double SolarDeclination = Declination(DayAngle); // Equation of times double eth = EqOfTime(DayAngle); // True solar time double diffUTC_TSV = Tsv_Tu(rlong,eth); // Day duration double dayDurationj = DayDuratInHours(SolarDeclination,rlat); // local time adjust time( &hour_machine ); // Get time as long integer. gmt_hour = gmtime( &hour_machine ); h1 = gmt_hour->tm_hour; local_hour = localtime( &hour_machine ); // local time. h2 = local_hour->tm_hour; // resultat result = 12 + fabs(dayDurationj / 2) - diffUTC_TSV + h2-h1; return result; } // Function to calculate decimal hour of sunrise: result universal time double CalculateSunriseUniversalTime(int day, int month, int year, double rlong, double rlat) { double result; // Calculate the angle of the day double DayAngle = AngleOfDay(day, month, year); // Declination double SolarDeclination = Declination(DayAngle); // Equation of times double eth = EqOfTime(DayAngle); // True solar time double diffUTC_TSV = Tsv_Tu(rlong,eth); // Day duration double dayDurationj = DayDuratInHours(SolarDeclination,rlat); // resultat result = 12 - fabs(dayDurationj / 2) - diffUTC_TSV; return result; } // Function to calculate decimal hour of sunset: result in universal time double CalculateSunsetUniversalTime(int day, int month, int year, double rlong, double rlat) { double result; // Calculate the angle of the day double DayAngle = AngleOfDay(day, month, year); // Declination double SolarDeclination = Declination(DayAngle); // Equation of times double eth = EqOfTime(DayAngle); // True solar time double diffUTC_TSV = Tsv_Tu(rlong,eth); // Day duration double dayDurationj = DayDuratInHours(SolarDeclination,rlat); // resultat result = 12 + fabs(dayDurationj / 2) - diffUTC_TSV; return result; } // Function to calculate the height of the sun in radians the day to day j and hour TU double SolarHeight (int tu, // universal times (0,1,2,.....,23) int day, int month, int year, double lat, // latitude in radian double rlong // longitude in radian ) { // local variables double pi = 3.1415926535; // Pi double result, tsvh; // angle of the day double DayAngle = AngleOfDay(day, month, year); // _declination double decli = Declination(DayAngle); // eq of time double eq = EqOfTime(DayAngle); // calculate the tsvh with rlong positiv for the east and negative for the west tsvh = tu + rlong*180/(15*pi) + eq; // hour angle per hour double ah = acos( -cos((pi/12)*tsvh) ); // final result result = asin( sin(lat)*sin(decli) + cos(lat)*cos(decli)*cos(ah) ); return result; } ///////////EXTRA FUNCTIONS///////////////////////////// //Julian day conversion for days calculations //Explanation for this sick formula...for the curious guys... //http://www.cs.utsa.edu/~cs1063/projects/Spring2011/Project1/jdn-explanation.html int julian(int year, int month, int day) { int a = (14 - month) / 12; int y = year + 4800 - a; int m = month + 12 * a - 3; if (year > 1582 || (year == 1582 && month > 10) || (year == 1582 && month == 10 && day >= 15)) return day + (153 * m + 2) / 5 + 365 * y + y / 4 - y / 100 + y / 400 - 32045; else return day + (153 * m + 2) / 5 + 365 * y + y / 4 - 32083; } int _tmain(int argc, _TCHAR* argv[]) { int day = 14; int month = 11; int year = 2013; double lat = 39.38; double lon = 22.75; double rlat = 39.38 * pi/180; double rlong = 22.75 * pi/180; double _AngleOfDay = AngleOfDay ( day , month , year ); cout << "Angle of day: " << _AngleOfDay << "\n"; double _Declinaison = Declination (_AngleOfDay); cout << "Declination (Delta): " << _Declinaison << "\n"; double _EqOfTime = EqOfTime (_AngleOfDay); cout << "Declination (Delta): " << _EqOfTime << "\n"; double _DayDuratInHours = DayDuratInHours (_Declinaison, rlat); cout << "Day duration: " << _DayDuratInHours << "\n"; double _Excentricity = Excentricity(day, month, year); cout << "Excentricity: " << _Excentricity << "\n"; double _TheoreticRadiation = TheoreticRadiation(day, month, year, rlat); cout << "Theoretical radiation: " << _TheoreticRadiation << "\n"; double _CalclulateSunriseLocalTime = CalclulateSunriseLocalTime (day, month, year, rlong, rlat); cout << "Sunrise Local Time: " << _CalclulateSunriseLocalTime << "\n"; double _CalculateSunsetLocalTime = CalculateSunsetLocalTime (day, month, year, rlong, rlat); cout << "Sunrise Local Time: " << _CalculateSunsetLocalTime << "\n"; return 0; } 

Чистые реализации C , по-видимому, недостаточны, но если вы готовы к отправке с C++ или C# то есть несколько вариантов:

  1. Расчеты Sunrise / Sunset на C ++
  2. C # Получите время восхода и захода солнца, основанное на широте и долготе

Используя это руководство (которое было впервые опубликовано в @BenjaminMonate, и я предполагаю, что это тот же самый @Geetha), я создал эту функцию C, которая, кажется, работает правильно.

 #include  #define PI 3.1415926 #define ZENITH -.83 float calculateSunrise(int year,int month,int day,float lat, float lng,int localOffset, int daylightSavings) { /* localOffset will be <0 for western hemisphere and >0 for eastern hemisphere daylightSavings should be 1 if it is in effect during the summer otherwise it should be 0 */ //1. first calculate the day of the year float N1 = floor(275 * month / 9); float N2 = floor((month + 9) / 12); float N3 = (1 + floor((year - 4 * floor(year / 4) + 2) / 3)); float N = N1 - (N2 * N3) + day - 30; //2. convert the longitude to hour value and calculate an approximate time float lngHour = lng / 15.0; float t = N + ((6 - lngHour) / 24); //if rising time is desired: //float t = N + ((18 - lngHour) / 24) //if setting time is desired: //3. calculate the Sun's mean anomaly float M = (0.9856 * t) - 3.289; //4. calculate the Sun's true longitude float L = fmod(M + (1.916 * sin((PI/180)*M)) + (0.020 * sin(2 *(PI/180) * M)) + 282.634,360.0); //5a. calculate the Sun's right ascension float RA = fmod(180/PI*atan(0.91764 * tan((PI/180)*L)),360.0); //5b. right ascension value needs to be in the same quadrant as L float Lquadrant = floor( L/90) * 90; float RAquadrant = 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 * sin((PI/180)*L); float cosDec = cos(asin(sinDec)); //7a. calculate the Sun's local hour angle float cosH = (sin((PI/180)*ZENITH) - (sinDec * sin((PI/180)*lat))) / (cosDec * cos((PI/180)*lat)); /* if (cosH > 1) the sun never rises on this location (on the specified date) if (cosH < -1) the sun never sets on this location (on the specified date) */ //7b. finish calculating H and convert into hours float H = 360 - (180/PI)*acos(cosH); // if if rising time is desired: //float H = acos(cosH) // if setting time is desired: 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 = fmod(T - lngHour,24.0); //10. convert UT value to local time zone of latitude/longitude return UT + localOffset + daylightSavings; } void printSunrise() { float localT = calculateSunrise(/*args*/); double hours; float minutes = modf(localT,&hours)*60; printf("%.0f:%.0f",hours,minutes); } 

код, предоставленный scottmrogowski, был полезен, однако два вопроса

  1. // float H = (180 / PI) * acos (cosH) // если требуется время установки:
  2. float localT = fmod (24 + calculateSunrise (/ * args * /), 24.0); // в функции printSunrise

Cheers Marek

Я поместил код C Tomoyose на C #. Он отлично работает, хотя требуется исправление с исправлением вручную из-за постоянного несоответствия около 4 минут онлайн-источникам. Это может быть связано с различием в том, что составляет закат или подъем, хотя официально это должно быть, когда солнце просто касается горизонта из-под него. Я ожидаю, что детали где-то похоронены в постоянных параметрах – вне меня, чтобы попытаться правильно исправить. Если другие управляют этим, я хотел бы знать 😉

Он использует NodaTime, который является реализацией Java JakeTime от Джона Скита. NodaTime доступен в nuGet.

 using System; using NodaTime; namespace YourNamespaceHere { public static class MySunset { // Based on Tomoyose's // http://stackoverflow.com/questions/7064531/sunrise-sunset-times-in-c private static DateTimeZone mUtcZone = DateTimeZoneProviders.Tzdb["Etc/UTC"]; private static int mSecondsInDay = 24 * 60 * 60; // Convert radian to hours private static double RadiansToHours(double radians) { return (radians * 12.0 / Math.PI); } // Convert hours to radians private static double HoursToRadians(double hours) { return (hours * Math.PI / 12.0); } // Calculate the angle of the day private static double AngleOfDay(int year, int month, int day) { DateTime date = new DateTime(year, month, day); int daysInYear = DateTime.IsLeapYear(year) ? 366 : 365; // Return angle of day in radians return (2.0 * Math.PI * ((double)date.DayOfYear - 1.0)) / (double)daysInYear; } // Calculate declination in radians private static double SolarDeclination(double angleOfDayRadians) { // Return solar declination in radians return 0.006918 - 0.399912 * Math.Cos(angleOfDayRadians) + 0.070257 * Math.Sin(angleOfDayRadians) - 0.006758 * Math.Cos(2.0 * angleOfDayRadians) + 0.000907 * Math.Sin(2.0 * angleOfDayRadians) - 0.002697 * Math.Cos(3.0 * angleOfDayRadians) + 0.00148 * Math.Sin(3.0 * angleOfDayRadians); } // Calculate Equation of time ( eot = TSV - TU ) private static double EquationOfTime(double angleOfDayRadians) { // Equation of time (radians) double et = 0.000075 + 0.001868 * Math.Cos(angleOfDayRadians) - 0.032077 * Math.Sin(angleOfDayRadians) - 0.014615 * Math.Cos(2.0 * angleOfDayRadians) - 0.04089 * Math.Sin(2.0 * angleOfDayRadians); // Return equation-of-time in hours return RadiansToHours(et); } // Calculate the duration of the day in radians private static double DayDurationRadians(double declinationRadians, double latitudeRadians) { return 2.0 * Math.Acos(-Math.Tan(latitudeRadians) * Math.Tan(declinationRadians)); } // Calculate day duration in hours private static double DayDurationHours(double declinationRadians, double latitudeRadians) { return RadiansToHours( DayDurationRadians(declinationRadians, latitudeRadians) ); } // Calculate the times TSV-UTC private static double Tsv_Tu(double longitudeRadians, double equationOfTime) { // Solar time as a function of longitude and the equation of time return longitudeRadians * (12.0 / Math.PI) + equationOfTime; } private static void GetDayParameters(int year, int month, int day, double latitude, double longitude, out double dayDuration, out double diffUTC_TSV) { double latitudeRadians = latitude * Math.PI / 180.0; double longitudeRadians = longitude * Math.PI / 180.0; // Calculate the angle of the day double dayAngle = AngleOfDay(year, month, day); // Declination double solarDeclination = SolarDeclination(dayAngle); // Equation of times double equationOfTime = EquationOfTime(dayAngle); // True solar time diffUTC_TSV = Tsv_Tu(longitudeRadians, equationOfTime); // Day duration dayDuration = DayDurationHours(solarDeclination, latitudeRadians); } // Calculate decimal UTC hour of sunrise. private static double CalculateSunriseUTC(int year, int month, int day, double latitude, double longitude) { double dayDuration; double diffUTC_TSV; GetDayParameters(year, month, day, latitude, longitude, out dayDuration, out diffUTC_TSV); return 12.0 - Math.Abs(dayDuration / 2.0) - diffUTC_TSV; } // Calculate decimal UTC hour of sunset. private static double CalculateSunsetUTC(int year, int month, int day, double latitude, double longitude) { double dayDuration; double diffUTC_TSV; GetDayParameters(year, month, day, latitude, longitude, out dayDuration, out diffUTC_TSV); return 12.0 + Math.Abs(dayDuration / 2.0) - diffUTC_TSV; } // Public methods to return sun rise and set times. public static Tuple GetSunRiseSet(LocalDate dateAtLocation, DateTimeZone locationZone, double latitude, double longitude) { // latitude-longitude must lie within zone of locationZone // Get UTC rise and set double dayDuration; double diffUTC_TSV; GetDayParameters(dateAtLocation.Year, dateAtLocation.Month, dateAtLocation.Day, latitude, longitude, out dayDuration, out diffUTC_TSV); double sunriseUtcDecimal = 12.0 - Math.Abs(dayDuration / 2.0) - diffUTC_TSV; double sunsetUtcDecimal = 12.0 + Math.Abs(dayDuration / 2.0) - diffUTC_TSV; // Convert decimal UTC to UTC dates // If a UTC time is negative then it means the date before in the UTC timezone. // So if negative need to minus 1 day from date and set time as 24 - decimal_time. LocalDateTime utcRiseLocal; LocalDateTime utcSetLocal; if (sunriseUtcDecimal < 0) { LocalDate utcDateAdjusted = dateAtLocation.PlusDays(-1); // Normalize() is important here; otherwise only have access to seconds. Period utcTimeAdjusted = Period.FromSeconds((long)((24.0 + sunriseUtcDecimal) / 24.0 * mSecondsInDay)).Normalize(); // + a negative utcRiseLocal = new LocalDateTime(utcDateAdjusted.Year, utcDateAdjusted.Month, utcDateAdjusted.Day, (int)utcTimeAdjusted.Hours, (int)utcTimeAdjusted.Minutes, (int)utcTimeAdjusted.Seconds); } else { Period utcTime = Period.FromSeconds((long)(sunriseUtcDecimal / 24.0 * mSecondsInDay)).Normalize(); utcRiseLocal = new LocalDateTime(dateAtLocation.Year, dateAtLocation.Month, dateAtLocation.Day, (int)utcTime.Hours, (int)utcTime.Minutes, (int)utcTime.Seconds); } if (sunsetUtcDecimal < 0) // Maybe not possible? { LocalDate utcDateAdjusted = dateAtLocation.PlusDays(-1); Period utcTimeAdjusted = Period.FromSeconds((long)((24.0 + sunsetUtcDecimal) / 24.0 * mSecondsInDay)).Normalize(); utcSetLocal = new LocalDateTime(utcDateAdjusted.Year, utcDateAdjusted.Month, utcDateAdjusted.Day, (int)utcTimeAdjusted.Hours, (int)utcTimeAdjusted.Minutes, (int)utcTimeAdjusted.Seconds); } else { Period utcTime = Period.FromSeconds((long)(sunsetUtcDecimal / 24.0 * mSecondsInDay)).Normalize(); utcSetLocal = new LocalDateTime(dateAtLocation.Year, dateAtLocation.Month, dateAtLocation.Day, (int)utcTime.Hours, (int)utcTime.Minutes, (int)utcTime.Seconds); } // FIX: always about 4 minutes later/earlier than other sources utcRiseLocal = utcRiseLocal.PlusMinutes(-4); utcSetLocal = utcSetLocal.PlusMinutes(4); // Get zoned datetime from UTC local datetimes ZonedDateTime utcRiseZoned = new LocalDateTime(utcRiseLocal.Year, utcRiseLocal.Month, utcRiseLocal.Day, utcRiseLocal.Hour, utcRiseLocal.Minute, utcRiseLocal.Second).InZoneLeniently(mUtcZone); ZonedDateTime utcSetZoned = new LocalDateTime(utcSetLocal.Year, utcSetLocal.Month, utcSetLocal.Day, utcSetLocal.Hour, utcSetLocal.Minute, utcSetLocal.Second).InZoneLeniently(mUtcZone); // Return zoned UTC to zoned local return new Tuple ( new ZonedDateTime(utcRiseZoned.ToInstant(), locationZone), new ZonedDateTime(utcSetZoned.ToInstant(), locationZone) ); } public static Tuple GetSunRiseSet(int year, int month, int day, string locationZone, double latitude, double longitude) { return GetSunRiseSet(new LocalDate(year, month, day), DateTimeZoneProviders.Tzdb[locationZone], latitude, longitude); } public static Tuple GetSunRiseSet(ZonedDateTime zonedDateAtLocation, double latitude, double longitude) { return GetSunRiseSet(zonedDateAtLocation.LocalDateTime.Date, zonedDateAtLocation.Zone, latitude, longitude); } } } 

Это адаптируется и довольно точно. Вы получите все компоненты, а затем все, что вам нужно вычислить, – это косинус дуги для угла Zenith to Horizon. Да, есть более простые способы, но разве вы в основном не хотите отслеживать Солнце? Это может пригодиться когда-нибудь. http://www.nrel.gov/midc/spa/

 //a practical approximation for a microcontroller using lookup table //seems to only use a small fraction of the resources required by the trigonometric functions //ignores daylight saving: idea is for the device to approximate and trigger actual sunrise, sunset event as opposed to actual (politically correct local hhmm) //using globals gps.Lat gps.LatDir(0:S 1:N) gps.Day (day of month) gps.Mth //needs solar noon offset,latitude,dayOfMonth,Month //LocalNoon-SolarNoon (may be off +/- up to ?? 2 hours) depending on local timezone and longitude (? typical discrepancy about 20min) void SunriseSunsetCalculations(u8 SolarNoonOffsetInDeciHours,u8 SolarNoonOffsetDirection){ if(SolarNoonOffsetInDeciHours>20){SolarNoonOffsetInDeciHours=0;}//limit offest to 2 hours: discard offset on error //--------references: //https://www.orchidculture.com/COD/daylength.html //http://aa.usno.navy.mil/data/docs/Dur_OneYear.php //SolarTime is up two two hours off in either direction depending on timezone: //http://blog.poormansmath.net/how-much-is-time-wrong-around-the-world/ //------------------ //lookUpTable Of daylength in decihours(6min)(fits well in u8) - 15day And 5 DegLat resolution //SolarNoonOffsetDirection: 0: negative(b4 local noon), 1: +ve (solar noon after local noon) u8 a[13][12]={//length of day in decihours // Dec Nov Oct Sep Aug Jul //Jan Feb Mar Apr May June {120,120,120,120,120,120,120,120,120,120,120,120}, //lat 0____0 {126,125,124,123,122,121,119,118,116,115,115,114}, //lat 10____1 {129,128,127,125,123,121,119,117,115,113,112,111}, //lat 15____2 {132,131,129,127,124,121,118,115,113,110,109,108}, //lat 20____3 {135,134,131,128,125,122,118,114,111,108,106,105}, //lat 25____4 {139,137,134,130,127,122,117,113,108,105,102,101}, //lat 30____5 {143,141,137,133,128,123,117,111,106,102, 98, 97}, //lat 35____6 {148,145,141,135,130,123,116,109,103, 98, 94, 92}, //lat 40____7 {154,150,145,138,132,124,115,107,100, 93, 88, 86}, //lat 45____8 {161,157,150,142,134,124,114,105, 96, 88, 82, 79}, //lat 50____9 {170,165,156,146,137,125,113,102, 91, 81, 73, 69}, //lat 55___10 {183,176,165,152,140,126,112, 98, 84, 72, 61, 56}, //lat 60___11 {200,185,171,152,134,121,101, 84, 65, 53, 40, 33} //lat 65___12 }; u8 b[]={6,12,17,22,27,32,37,42,47,52,57,62,90}; // latitude limit cutoffs to get index of lookUpTable u8 lat=gps.Lat/10000000; //lat stored in u32 to 7 decimals resolution (32bit unsigned integer) u8 i=0; while(b[i]