首先感谢帮我算题的小玉玉~
算了一周的日出日落,倍觉痛苦,写下来防止下次再算。
根据经纬度和UTC计算日出日落的思路、算法及scala代码如下~
日出和日落的计算思路:
- 一天的日出和日落可以根据正午时刻平分昼长得到。
- 正午时刻可以根据所在时区和经度得到。
- 根据经度可以知道所在时区。
- 昼长可以根据太阳赤角和所在纬度计算得到。
符号说明:
rc:日出
rl:日落
zw:正午
day:昼长
zone:时区
δ:太阳赤纬
lon:经度
lat:纬度
N:每年一月一日到当前的天数
b:弧度制
计算公式:
当lon大于7.5时加一,小于7.5时减一
δ=0.006918-0.399912*cos(b)+0.070257*sin(b)-0.006758*cos(2*b)+0.000907*sin(2*b)-0.002697*cos(3*b)+0.00148*sin(3*b)
例子:
2018年3月1日上海(121.07,31.03)的日出日落。
所在时区 = (121.07 - 7.5)/15 +1 = 8
正午时刻 = 12 +(8*15 - 121.07)/15 = 11.93
距离年初的天数为59天
弧度b:1.0156381729413577
太阳赤纬delta:-0.13752063172367998昼长:11.706427291331444
日出:1551391471
日落:1551433614
代码:
object TimeUtil {
def main(args: Array[String]): Unit = {
println(getDay(121.07,31.03,1551424419))
}
/**
* 计算当地日出日落UTC
*/
def getDay(lon: Double, lat: Double, utc: Int): (Int, Int) = {
var day = 0;
var rc = 0;
var rl = 0;
val lon_pai = Math.PI * (lon / 360)
val lat_pai = Math.PI * (lat / 360)
val time_zone = getTimeZone(lon) //时区
val time_real = utc + time_zone * 3600 // 真实时间,计算出所在时区的本地时间
println(time_real)
val yearTimeStamp = getUtcYearStart(time_zone, time_real.toString) // 获取所在时区年份的UTC
val N = (utc - yearTimeStamp) / 86400 // 一年中的第几天
val b = (2 * Math.PI * N) / 365
val delta = 0.006918 - 0.399912 * math.cos(b) + 0.070257 * math.sin(b) - 0.006758 * math.cos(2 * b) + 0.000907 * math.sin(2 * b) - 0.002697 * math.cos(3 * b) + 0.00148 * math.sin(3 * b)
val gama = Math.PI / 2 - math.abs(delta)
// 判断极昼、极夜
if (delta >= 0) {
if (lat_pai > gama) {
rc = 1
} else if (lat_pai < -gama) {
rl = 1
}
} else if (delta < 0) {
if (lat_pai > gama) {
rl = 1
} else if (lat_pai < -gama) {
rc = 1
}
}
if (lat_pai >= -gama && lat_pai <= gama) {
var time_day = 24 - 24 * Math.acos(Math.tan(delta) * Math.tan(lat_pai)) / Math.PI //昼长
var time_z = 12 + (time_zone * 15 - lon) / 15 //太阳正午时间
var time_days = time_real / 86400 // 计算当地天数
var time_rc = ((time_z - time_day / 2) * 3600 + time_days * 86400).toInt - time_zone * 3600
var time_rl = ((time_z + time_day / 2) * 3600 + time_days * 86400).toInt - time_zone * 3600
rc = time_rc
rl = time_rl
}
(rc, rl)
}
/**
* 计算时区
*/
def getTimeZone(lon: Double): Int = {
var time_zone = 0
if (lon > 0) {
if (lon > 7.5) {
time_zone = ((lon - 7.5) / 15 + 1).toInt
}
} else if (lon < 0) {
if (lon < -7.5) {
time_zone = ((lon + 7.5) / 15 - 1).toInt
}
}
(time_zone)
}
/**
* 获取所在时区当天开始时间的UTC
* (获取所在时区的当天日期,补全开始时间,并转化为UTC)
*/
def getUtcNightStart(lon: Double, rc: String): Long = {
val time_zone = getTimeZone(lon)
val fm = new SimpleDateFormat("yyyy-MM-dd")
val timeDay = fm.format(new Date((rc.toLong - 8 * 3600 + time_zone * 3600) * 1000)) // 所在时区的当天日期
val date = fm.parse(timeDay)
val timeHour = date.getTime / 1000 // 所在时区的当天日期在东八区的当天日期的时间戳
val nightStart = timeHour + 8 * 3600 - time_zone * 3600 // 所在时区的当天日期开始时间所对应的UTC
nightStart
}
/**
* 计算所在时区当年的开始UTC
*/
def getUtcYearStart(time_zone: Int, tm: String): Long = {
val fm = new SimpleDateFormat("yyyy")
val timeYear = fm.format(new Date((tm.toLong - 8 * 3600 + time_zone * 3600) * 1000)) // 所在时区的年份
val dt = fm.parse(timeYear)
val timeHour = dt.getTime() / 1000
val yearStart = timeHour + 8 * 3600 - time_zone * 3600
yearStart
}
}
转载自原文链接, 如需删除请联系管理员。
原文链接:计算日出日落算法实现,转载请注明来源!