Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/62.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
c中的日出日落时间_C_Time - Fatal编程技术网

c中的日出日落时间

c中的日出日落时间,c,time,C,Time,在我的C应用程序中,我想计算给定日期、纬度和经度的日出/日落时间。我一直在网上搜索,但找不到有效的样品 我尝试实现此示例: 但是这个样本没有正确工作 #include <math.h> #define PI 3.1415926 #define ZENITH -.83 float calculateSunrise(int year,int month,int day,float lat, float lng,int localOffset, int daylightSavings)

在我的C应用程序中,我想计算给定日期、纬度和经度的日出/日落时间。我一直在网上搜索,但找不到有效的样品

我尝试实现此示例:

但是这个样本没有正确工作

#include <math.h>
#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);
    }
是否有一个简单的C源代码或方法可以在我的应用程序中轻松实现

编辑:
我实现了这个代码,但它给了我错误的日落/日出值。我也尝试了索尔的链接,但它也给了我错误的结果
我有41N,28E的位置。当我尝试代码时,两个示例都表示日出值大约为10:13,日落值为23:24。但正确的值是06:06、20:13。

我无法理解这个问题。

这似乎很容易实现:

C
实现显然很少,但如果您愿意从
C++
C#
进行移植,则有两种选择:

  • C++
  • C#

  • 示例代码似乎在VC++2010中工作,但有一些小改动:

      < LI>编译为C++文件,而不是C.
    • 删除
      #include
    • 在文件顶部添加一个
      #define\u USE_MATH\u DEFINES
      ,以便定义M#PI
    • strftime()
      调用中的两个
      %T
      更改为
      %X
    现在您已经有了一个工作示例,您可以调试工作版本和您的版本,以查看计算的不同之处,并缩小问题的范围。可以单步执行程序,也可以像示例一样自由地使用临时
    printf()
    调用


    如果您需要特定的帮助,您必须发布您的代码(指向整个文件的链接或需要帮助的特定代码片段)。

    有一个c解决方案,它为sunrise/set提供了一个objective c包装器:

    计算给定日期、纬度和经度需要遵循的十个简单步骤

  • 首先计算一年中的哪一天

    N1=楼层(275*月/9) N2=楼层((月+9)/12) N3=(1+楼层((第4年*楼层(第4年)+2)/3)) N=N1-(N2*N3)+第30天

  • 将经度转换为小时值并计算近似时间

    lngHour=经度/15

    如果需要上升时间: t=N+((6-lngHour)/24) 如果需要设置时间: t=N+((18-lngHour)/24)

  • 计算太阳的平均异常

    M=(0.9856*t)-3.289

  • 计算太阳的真实经度

    L=M+(1.916*sin(M))+(0.020*sin(2*M))+282.634 注:L可能需要通过加/减360调整到范围[0360]

  • 5a.计算太阳的赤经

    RA = atan(0.91764 * tan(L))
    NOTE: RA potentially needs to be adjusted into the range [0,360) by adding/subtracting 360
    
    5b.赤经值需要与L位于同一象限

    Lquadrant  = (floor( L/90)) * 90
    RAquadrant = (floor(RA/90)) * 90
    RA = RA + (Lquadrant - RAquadrant)
    
    5c.赤经值需要转换成小时

    RA = RA / 15
    
    if if rising time is desired:
      H = 360 - acos(cosH)
    if setting time is desired:
      H = acos(cosH)
    
    H = H / 15
    
  • 计算太阳的赤纬

    sinDec=0.39782*sin(L) cosDec=cos(asin(sinDec))

  • 7a.计算太阳的本地时角

    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)
    
  • 计算上升/设定的本地平均时间

    T=H+RA-(0.06571*T)-6.622

  • 调整回UTC

    UT=T-lngHour 注:UT可能需要通过加/减24调整到范围[0,24]

  • 将UT值转换为纬度/经度的本地时区

    localT=UT+localOffset

  • 使用这个(由@BenjaminMonate首先发布,我假设是@Geetha使用的那个),我构建了这个C函数,它似乎工作正常

    #include <math.h>
    #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);
        }
    
    #包括
    #定义PI 3.1415926
    #定义天顶-.83
    浮动计算取消利率(整数年、整数月、整数日、浮动lat、浮动lng、整数本地偏移、整数日光节约){
    /*
    东半球的localOffset将为0
    如果daylightSavings在夏季生效,则应为1,否则应为0
    */
    //1.首先计算一年中的哪一天
    浮动N1=地板(275*月/9);
    浮动N2=地板((月+9)/12);
    浮动N3=(1+楼层((第-4年*楼层(第/4年)+2)/3年));
    浮点数N=N1-(N2*N3)+第30天;
    //2.将经度转换为小时值并计算近似时间
    浮子lngHour=lng/15.0;
    浮点t=N+((6-lngHour)/24);//如果需要上升时间:
    //浮动t=N+((18-lngHour)/24)//如果需要设置时间:
    //3.计算太阳的平均异常
    浮点数M=(0.9856*t)-3.289;
    //4.计算太阳的真实经度
    浮点数L=fmod(M+(1.916*sin((PI/180)*M))+(0.020*sin(2*(PI/180)*M))+282.634360.0);
    //5a.计算太阳的赤经
    浮点数RA=fmod(180/PI*atan(0.91764*tan((PI/180)*L)),360.0);
    //5b.赤经值需要与L位于同一象限
    浮动象限=地板(L/90)*90;
    浮动象限=地板(RA/90)*90;
    RA=RA+(1象限-RA象限);
    //5c.赤经值需要转换成小时
    RA=RA/15;
    //6.计算太阳的赤纬
    浮点数sinDec=0.39782*sin((π/180)*L);
    浮点数cosDec=cos(asin(sinDec));
    //7a.计算太阳的本地时角
    浮动cosH=(sin((PI/180)*天顶)-(sinDec*sin((PI/180)*lat))/(cosDec*cos((PI/180)*lat));
    /*   
    如果(cosH>1)
    太阳永远不会在这个位置升起(在指定的日期)
    如果(cosH<-1)
    太阳永远不会落在此位置(在指定日期)
    */
    //7b.完成H的计算并转换为小时
    浮点H=360-(180/PI)*acos(cosH);//如果需要上升时间:
    //浮点H=acos(cosH)//如果需要设置时间:
    H=H/15;
    //8.计算本地平均上升/设定时间
    浮球T=H+RA-(0.06571*T)-6.622;
    //9.调整回UTC
    浮点数UT=fmod(T-lngHour,24.0);
    //10.将UT值转换为纬度/经度的本地时区
    返回UT
    
    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<ZonedDateTime, ZonedDateTime> 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<ZonedDateTime, ZonedDateTime>
                (
                    new ZonedDateTime(utcRiseZoned.ToInstant(), locationZone),
                    new ZonedDateTime(utcSetZoned.ToInstant(), locationZone)
                );
            }
            public static Tuple<ZonedDateTime, ZonedDateTime> 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<ZonedDateTime, ZonedDateTime> GetSunRiseSet(ZonedDateTime zonedDateAtLocation, double latitude, double longitude)
            {
                return GetSunRiseSet(zonedDateAtLocation.LocalDateTime.Date, zonedDateAtLocation.Zone, latitude, longitude);
            }
        }
    }
    
    //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]<lat){i++;}  //get row index for daylength table
        u8 k,ix; //k: 15 day offset;    ix: column index for daylength table
        k=gps.Day/15;if(k){k=1;}//which half of the month (avoid k=2 eg:31/15)
        if(!gps.LatDir){ //0:southern latitudes
            if(gps.Mth<7){
                ix=(gps.Mth-1)*2+k;     //2 fields per month (k to select)
            }else{                      //beyond june, use row in reverse
                ix=11-(gps.Mth-7)*2-k;  //2 fields per month (k to select)
            }
        }else{           //1:northern latitudes
            if(gps.Mth<7){              //with first six month read rows in reverse
                ix=11-(gps.Mth-1)*2-k;  //2 fields per month (k to select)
            }else{                      //beyond june, use same row forward
                ix=(gps.Mth-7)*2+k;     //2 fields per month (k to select)
            }
        }
        //debug only:...dcI("\r\ni", i ,Blue,Red,1);dcI("ix", ix ,Blue,Red,1);dcI("a[i][ix]", a[i][ix] ,Blue,Red,1);
        u8 h=a[i][ix]/2; //HalfTheDayLightLength in deciHours
        u8 j[]={-1,1};   //multiplier: 0:(-)  1:(+)
        u8 sn=120+SolarNoonOffsetInDeciHours*j[SolarNoonOffsetDirection]; //Solar noon
        u8 srdh=sn-h;    //sunrise in deciHours = solarNoon minus HalfTheDayLightLength
        u8 ssdh=sn+h;    //sunset  in deciHours = solarNoon  plus HalfTheDayLightLength
        //debug only:...dcI("\r\nSunRiseDeciHours", srdh ,Blue,Red,1);dcI("SunSetDeciHours", ssdh ,Blue,Red,1);
        gps.HmSunRise=deciHourTohhmm(srdh);
        gps.HmSunSet =deciHourTohhmm(ssdh);
    }
    u16 deciHourTohhmm(u8 dh){ //return unsigned integer from 0 to 2400
       u16 h=(dh/10)*100; //hours: hh00
       u8  r= dh%10;      //fraction hour remainder to be converted to minutes
       u8  m= 6*r;        //60*r/10
       return(h+m);
    }
    
    
    /*
    Example Output: (!!! solarNoonOffset kept at 0(ignored) for the below example)
    
    :_(08474300)___:_(A)___:_(381234567)___:_(S)___:_(1431234567)___:_(E)___
    :_(GPS OK)___:_(Sat)___:_(12)___:_(Aug)___:_(2017)___hhmm:_(847)___
    //...........
    i:_(7)___ix:_(9)___a[i][ix]:_(98)___
    SunRiseDeciHours:_(71)___SunSetDeciHours:_(169)___
    HmSunRise:_(706)___
    HmSunSet:_(1654)___
    //............same as above but change LatDir to 1 (northern hemisphere)
    i:_(7)___ix:_(2)___a[i][ix]:_(141)___
    SunRiseDeciHours:_(50)___SunSetDeciHours:_(190)___
    HmSunRise:_(500)___
    HmSunSet:_(1900)___
    ..........ignore dcI(...) it's just a custom function printing through the serial port
    */
    
    time_t Sunclock::sunrise(time_t date) {
      date = date + tz_offset * 60 * 60;
      struct tm *t = gmtime(&date);
      double _time_of_day = time_of_day(date);
      double _julian_day = julian_day(t, _time_of_day, tz_offset);
      double _julian_century = julian_century(_julian_day);
      double _mean_obliq_ecliptic = mean_obliq_ecliptic(_julian_century);
      double _mean_long_sun = mean_long_sun(_julian_century);
      double _mean_anom_sun = mean_anom_sun(_julian_century);
      double _sun_eq_of_centre = sun_eq_of_centre(_mean_anom_sun, _julian_century);
      double _sun_true_long = sun_true_long(_mean_long_sun, _sun_eq_of_centre);
      double _obliq_corr = obliq_corr(_mean_obliq_ecliptic, _julian_century);
      double _sun_app_long = sun_app_long(_sun_true_long, _julian_century);
      double _eccent_earth_orbit = eccent_earth_orbit(_julian_century);
      double _var_y = var_y(_obliq_corr);
      double _eq_of_time =
          eq_of_time(_var_y, _mean_long_sun, _eccent_earth_orbit, _mean_anom_sun);
      double _declination = declination(_obliq_corr, _sun_app_long);
      double _hour_angle_sunrise = hour_angle_sunrise(_declination);
    
      double noon_decimal_day =
          (720 - 4 * longitude - _eq_of_time + tz_offset * 60) / 1440;
      double decimal_day = noon_decimal_day - _hour_angle_sunrise * 4 / 1440;
      return time_from_decimal_day(date, decimal_day) - tz_offset * 60 * 60;
    }