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

Posted smartgirlintown

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了浅谈日出日落的计算方法以及替代工具相关的知识,希望对你有一定的参考价值。

引言

如果你想知道精确的日落日出时间,又或者你想设计一个日出日落时间查询的应用,又或者你只是好奇点进来了,还是可以过来围观一下涨涨知识,今天想跟大家聊一聊的是日出日落的计算方法以及替代工具 - 日出日落 API 。

日出日落 API 是一种可以获取指定城市或地点每日日出时间和日落时间的接口。该 API 基于全球日出日落计算公式和高精度天文算法,可以为用户提供准确的日出日落时间数据,覆盖全球3400+个城市和4万个地点。

日出日落的计算方法

日出日落时间的计算涉及到地球的自转、公转、地球的形状、大气折射等多个因素,因此需要使用天文学公式和计算方法。以下是一些常用的计算方法:

1.简化公式法:使用经度、纬度、日期等简单参数,通过一些近似公式计算日出日落时间。这种方法比较简单,但是精度不高,只适用于一般的应用。

日出时间 = 12:00 - (时差 + 地方时) - α

日落时间 = 12:00 + (时差 - 地方时) - α

其中,时差表示当地时间和世界时之间的差异;地方时表示当地的时间差异;α表示地球自转一周的时间和24小时的差异,通常取约4分钟。

2.几何平均法:这种方法将地球视为一个球体,将日出日落的计算转化为求解在球体上的两点之间的距离。这种方法的精度比简化公式法高,但是仍然存在一定误差。

cos(ωs) = -tan(φ) * tan(δ) ωs = arccos(cos(ωs)) t = (ωs * 24) / (2π)

其中,ωs表示日出日落时太阳的高度角,φ表示纬度,δ表示太阳的赤纬,t表示日出日落时间。

3.物理光学法:使用光线追踪等方法,考虑大气折射等因素,计算出日出日落时间。这种方法的公式比较复杂,通常需要使用计算机程序进行计算。

在实际应用中,常用的方法是简化公式法和几何平均法,可以通过天文学软件、网站等工具进行计算。例如,可以使用日出日落 API ,输入城市编码参数,就可以得到相应的结果。

日出日落 API 的工作原理

日出日落API的工作原理基于天文学原理和算法。具体来说,日出日落 API 利用太阳、地球和天文时的位置关系,来计算出指定城市或地点的日出和日落时间。以下是该API的具体工作原理:

应用场景

日出日落API可以广泛应用于多个领域,包括天气预报、航海导航、摄影、农业和旅游等。在天气预报方面,日出日落时间是影响天气预报准确性的一个因素。

常用日出日落API 推荐

以下是我推荐的几个日出日落API:

1.APISpace 日出日落 API

简介:APISpace 日出日落 API 支持国内3400+个城市以及国际4万个城市,获取指定城市/地点每日日出时间、日落时间。

接入方式:很简单三个步骤即可完成了,有不明白的小伙伴可以评论区交流~

Java 接入代码:

OkHttpClient client = new OkHttpClient().newBuilder().build();
MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");
Request request = new Request.Builder()
  .url("https://eolink.o.apispace.com/ewre/lives_geo/v001/sun?days=1&areacode=101010100")
  .method("GET",null)
  .addHeader("X-APISpace-Token","")
  .addHeader("Authorization-Type","apikey")
  .build();

Response response = client.newCall(request).execute();
System.out.println(response.body().string());

返回示例:


    “status”: 0,
    “result”: 
        “location”: 
            “areacode”: “101010100”,        //城市ID
            “name”: “北京”,                //城市中文名
            “country”: “中国”,                //所属国家中文名
            “path”: “北京,北京市,北京市,中国”          //行政区划路径
        ,
        “sunrises”: [
            
                “sunrise”: “06:52”,                //日出时间(当地时间)
                “sunset”: “18:03”,                //日落时间(当地时间)
                “data_time”: “2020-02-27”        //预报日期(当地时间)
            ,
                ……                              //其它日期日出日落信息
        ]
    

2.Time and Date Sunrise/Sunset API

提供了详细的日出日落时间数据,包括黄昏、拂晓、日出、日落、黎明等时刻

3.WeatherAPI

提供了日出、日落和日顶的时间数据,以及相关的天文信息和气象数据。

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

以上是关于浅谈日出日落的计算方法以及替代工具的主要内容,如果未能解决你的问题,请参考以下文章

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

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

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

c日出日落时间

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

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