c日出日落时间

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c日出日落时间相关的知识,希望对你有一定的参考价值。

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

我试图实现这个样本:http://souptonuts.sourceforge.net/code/sunrise.c.html

但是这个样本没有正常工作。

是否有一个简单的C源代码或方法,我可以在我的应用程序中轻松实现?

编辑: 我在这个link上实现了代码,但它给了我错误的日落/日出值。我也尝试了Saul的链接here,但它也给了我错误的结果。 我有41N,28E的位置。当我尝试这些代码时,两个样本都说日出值大约是10:13而日落是23:24。但正确的值是06:06,20:13。 我无法理解这个问题。

答案

示例代码似乎在VC ++ 2010中有一些小的更改:

  • 将其编译为C ++文件而不是C.
  • 删除#include <sys/time.h>线。
  • 在文件顶部添加#define _USE_MATH_DEFINES,以便定义M_PI。
  • %T调用中的两个strftime()更改为%X

既然您有一个工作样本,您可以调试工作版本和您的版本,以查看计算开始不同的地方并缩小问题范围。无论是单步执行程序还是自由使用临时printf()调用就像样本一样。

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

另一答案

这是适应性的,非常准确。您将获得所有组件,然后您需要计算的是Zenith到Horizo​​n角度的反余弦。是的,有更简单的方法,但你不是基本上想跟踪太阳?它有朝一日会派上用场。 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]<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("
i", 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("
SunRiseDeciHours", 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
*/
另一答案

给出日期,纬度和经度,计算sunrise / sunset time的十个简单步骤

  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 * t) - 3.289
  4. 计算太阳的真实经度 L = M +(1.916 * sin(M))+(0.020 * sin(2 * M))+ 282.634注:L可能需要通过加/减360调整到[0,360]范围内

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
  1. 计算太阳的赤纬 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)

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 * t) - 6.622
  2. 调整回UTC UT = T - lngHour注意:UT可能需要通过添加/减去24来调整到[0,24]范围内
  3. 将UT值转换为纬度/经度的本地时区 localT = UT + localOffset
另一答案

这似乎很容易实现: http://edwilliams.org/sunrise_sunset_algorithm.htm

另一答案

有一个c解决方案,其中包含日出/设置的目标c包装:https://gith

以上是关于c日出日落时间的主要内容,如果未能解决你的问题,请参考以下文章

昼长和日出日落时间的计算

通过日出日落时间怎判断当天太阳直射点位于啥位置?

日出时间和日落时间怎么计算?

浅谈日出日落的计算方法以及替代工具

Swift4 经纬度计算日出日落时间

如何在javascript中计算日出和日落?