浅谈日出日落的计算方法以及替代工具
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到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]<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的十个简单步骤
- 首先计算一年中的哪一天 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调整到[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
- 计算太阳的赤纬 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
- 计算当地平均上升/设定时间 T = H + RA - (0.06571 * t) - 6.622
- 调整回UTC UT = T - lngHour注意:UT可能需要通过添加/减去24来调整到[0,24]范围内
- 将UT值转换为纬度/经度的本地时区 localT = UT + localOffset
这似乎很容易实现: http://edwilliams.org/sunrise_sunset_algorithm.htm
有一个c解决方案,其中包含日出/设置的目标c包装:https://gith 以上是关于浅谈日出日落的计算方法以及替代工具的主要内容,如果未能解决你的问题,请参考以下文章