|
|
@@ -0,0 +1,447 @@
|
|
|
+// Package sunrisesunset should be used to calculate the apparent sunrise and sunset based on the latitude, longitude, UTC offset and date.
|
|
|
+// All calculations (formulas) were extracted from the Solar Calculation Details of the Earth System Research Laboratory:
|
|
|
+// https://www.esrl.noaa.gov/gmd/grad/solcalc/calcdetails.html
|
|
|
+package utils
|
|
|
+
|
|
|
+import (
|
|
|
+ "errors"
|
|
|
+ "math"
|
|
|
+ "time"
|
|
|
+)
|
|
|
+
|
|
|
+// The Parameters struct can also be used to manipulate
|
|
|
+// the data and get the sunrise and sunset
|
|
|
+type Parameters struct {
|
|
|
+ Latitude float64
|
|
|
+ Longitude float64
|
|
|
+ UtcOffset float64
|
|
|
+ Date time.Time
|
|
|
+}
|
|
|
+
|
|
|
+// Just call the 'general' GetSunriseSunset function and return the results
|
|
|
+func (p *Parameters) GetSunriseSunset() (time.Time, time.Time, error) {
|
|
|
+ return GetSunriseSunset(p.Latitude, p.Longitude, p.UtcOffset, p.Date)
|
|
|
+}
|
|
|
+
|
|
|
+// Convert radians to degrees
|
|
|
+func rad2deg(radians float64) float64 {
|
|
|
+ return radians * (180.0 / math.Pi)
|
|
|
+}
|
|
|
+
|
|
|
+// Convert degrees to radians
|
|
|
+func deg2rad(degrees float64) float64 {
|
|
|
+ return degrees * (math.Pi / 180.0)
|
|
|
+}
|
|
|
+
|
|
|
+// Creates a vector with the seconds normalized to the range 0~1.
|
|
|
+// seconds - The number of seconds will be normalized to 1
|
|
|
+// Return A vector with the seconds normalized to 0~1
|
|
|
+func createSecondsNormalized(seconds int) (vector []float64) {
|
|
|
+ for index := 0; index < seconds; index++ {
|
|
|
+ temp := float64(index) / float64(seconds-1)
|
|
|
+ vector = append(vector, temp)
|
|
|
+ }
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+// Calculate Julian Day based on the formula: nDays+2415018.5+secondsNorm-UTCoff/24
|
|
|
+// numDays - The number of days calculated in the calculate function
|
|
|
+// secondsNorm - Seconds normalized calculated by the createSecondsNormalized function
|
|
|
+// utcOffset - UTC offset defined by the user
|
|
|
+// Return Julian day slice
|
|
|
+func calcJulianDay(numDays int64, secondsNorm []float64, utcOffset float64) (julianDay []float64) {
|
|
|
+ for index := 0; index < len(secondsNorm); index++ {
|
|
|
+ temp := float64(numDays) + 2415018.5 + secondsNorm[index] - utcOffset/24.0
|
|
|
+ julianDay = append(julianDay, temp)
|
|
|
+ }
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+// Calculate the Julian Century based on the formula: (julianDay - 2451545.0) / 36525.0
|
|
|
+// julianDay - Julian day vector calculated by the calcJulianDay function
|
|
|
+// Return Julian century slice
|
|
|
+func calcJulianCentury(julianDay []float64) (julianCentury []float64) {
|
|
|
+ for index := 0; index < len(julianDay); index++ {
|
|
|
+ temp := (julianDay[index] - 2451545.0) / 36525.0
|
|
|
+ julianCentury = append(julianCentury, temp)
|
|
|
+ }
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+// Calculate the Geom Mean Long Sun in degrees based on the formula: 280.46646 + julianCentury * (36000.76983 + julianCentury * 0.0003032)
|
|
|
+// julianCentury - Julian century calculated by the calcJulianCentury function
|
|
|
+// Return The Geom Mean Long Sun slice
|
|
|
+func calcGeomMeanLongSun(julianCentury []float64) (geomMeanLongSun []float64) {
|
|
|
+ for index := 0; index < len(julianCentury); index++ {
|
|
|
+ a := 280.46646 + julianCentury[index]*(36000.76983+julianCentury[index]*0.0003032)
|
|
|
+ temp := math.Mod(a, 360.0)
|
|
|
+ geomMeanLongSun = append(geomMeanLongSun, temp)
|
|
|
+ }
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+// Calculate the Geom Mean Anom Sun in degrees based on the formula: 357.52911 + julianCentury * (35999.05029 - 0.0001537 * julianCentury)
|
|
|
+// julianCentury - Julian century calculated by the calcJulianCentury function
|
|
|
+// Return The Geom Mean Anom Sun slice
|
|
|
+func calcGeomMeanAnomSun(julianCentury []float64) (geomMeanAnomSun []float64) {
|
|
|
+ for index := 0; index < len(julianCentury); index++ {
|
|
|
+ temp := 357.52911 + julianCentury[index]*(35999.05029-0.0001537*julianCentury[index])
|
|
|
+ geomMeanAnomSun = append(geomMeanAnomSun, temp)
|
|
|
+ }
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+// Calculate the Eccent Earth Orbit based on the formula: 0.016708634 - julianCentury * (0.000042037 + 0.0000001267 * julianCentury)
|
|
|
+// julianCentury - Julian century calculated by the calcJulianCentury function
|
|
|
+// Return The Eccent Earth Orbit slice
|
|
|
+func calcEccentEarthOrbit(julianCentury []float64) (eccentEarthOrbit []float64) {
|
|
|
+ for index := 0; index < len(julianCentury); index++ {
|
|
|
+ temp := 0.016708634 - julianCentury[index]*(0.000042037+0.0000001267*julianCentury[index])
|
|
|
+ eccentEarthOrbit = append(eccentEarthOrbit, temp)
|
|
|
+ }
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+// Calculate the Sun Eq Ctr based on the formula: sin(deg2rad(geomMeanAnomSun))*(1.914602-julianCentury*(0.004817+0.000014*julianCentury))+sin(deg2rad(2*geomMeanAnomSun))*(0.019993-0.000101*julianCentury)+sin(deg2rad(3*geomMeanAnomSun))*0.000289;
|
|
|
+// julianCentury - Julian century calculated by the calcJulianCentury function
|
|
|
+// geomMeanAnomSun - Geom Mean Anom Sun calculated by the calcGeomMeanAnomSun function
|
|
|
+// Return The Sun Eq Ctr slice
|
|
|
+func calcSunEqCtr(julianCentury []float64, geomMeanAnomSun []float64) (sunEqCtr []float64) {
|
|
|
+ if len(julianCentury) != len(geomMeanAnomSun) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ for index := 0; index < len(julianCentury); index++ {
|
|
|
+ temp := math.Sin(deg2rad(geomMeanAnomSun[index]))*(1.914602-julianCentury[index]*(0.004817+0.000014*julianCentury[index])) + math.Sin(deg2rad(2*geomMeanAnomSun[index]))*(0.019993-0.000101*julianCentury[index]) + math.Sin(deg2rad(3*geomMeanAnomSun[index]))*0.000289
|
|
|
+ sunEqCtr = append(sunEqCtr, temp)
|
|
|
+ }
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+// Calculate the Sun True Long in degrees based on the formula: sunEqCtr + geomMeanLongSun
|
|
|
+// sunEqCtr - Sun Eq Ctr calculated by the calcSunEqCtr function
|
|
|
+// geomMeanLongSun - Geom Mean Long Sun calculated by the calcGeomMeanLongSun function
|
|
|
+// Return The Sun True Long slice
|
|
|
+func calcSunTrueLong(sunEqCtr []float64, geomMeanLongSun []float64) (sunTrueLong []float64) {
|
|
|
+ if len(sunEqCtr) != len(geomMeanLongSun) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ for index := 0; index < len(sunEqCtr); index++ {
|
|
|
+ temp := sunEqCtr[index] + geomMeanLongSun[index]
|
|
|
+ sunTrueLong = append(sunTrueLong, temp)
|
|
|
+ }
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+// Calculate the Sun App Long in degrees based on the formula: sunTrueLong-0.00569-0.00478*sin(deg2rad(125.04-1934.136*julianCentury))
|
|
|
+// sunTrueLong - Sun True Long calculated by the calcSunTrueLong function
|
|
|
+// julianCentury - Julian century calculated by the calcJulianCentury function
|
|
|
+// Return The Sun App Long slice
|
|
|
+func calcSunAppLong(sunTrueLong []float64, julianCentury []float64) (sunAppLong []float64) {
|
|
|
+ if len(sunTrueLong) != len(julianCentury) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ for index := 0; index < len(sunTrueLong); index++ {
|
|
|
+ temp := sunTrueLong[index] - 0.00569 - 0.00478*math.Sin(deg2rad(125.04-1934.136*julianCentury[index]))
|
|
|
+ sunAppLong = append(sunAppLong, temp)
|
|
|
+ }
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+// Calculate the Mean Obliq Ecliptic in degrees based on the formula: 23+(26+((21.448-julianCentury*(46.815+julianCentury*(0.00059-julianCentury*0.001813))))/60)/60
|
|
|
+// julianCentury - Julian century calculated by the calcJulianCentury function
|
|
|
+// Return the Mean Obliq Ecliptic slice
|
|
|
+func calcMeanObliqEcliptic(julianCentury []float64) (meanObliqEcliptic []float64) {
|
|
|
+ for index := 0; index < len(julianCentury); index++ {
|
|
|
+ temp := 23.0 + (26.0+(21.448-julianCentury[index]*(46.815+julianCentury[index]*(0.00059-julianCentury[index]*0.001813)))/60.0)/60.0
|
|
|
+ meanObliqEcliptic = append(meanObliqEcliptic, temp)
|
|
|
+ }
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+// Calculate the Obliq Corr in degrees based on the formula: meanObliqEcliptic+0.00256*cos(deg2rad(125.04-1934.136*julianCentury))
|
|
|
+// meanObliqEcliptic - Mean Obliq Ecliptic calculated by the calcMeanObliqEcliptic function
|
|
|
+// julianCentury - Julian century calculated by the calcJulianCentury function
|
|
|
+// Return the Obliq Corr slice
|
|
|
+func calcObliqCorr(meanObliqEcliptic []float64, julianCentury []float64) (obliqCorr []float64) {
|
|
|
+ if len(meanObliqEcliptic) != len(julianCentury) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ for index := 0; index < len(julianCentury); index++ {
|
|
|
+ temp := meanObliqEcliptic[index] + 0.00256*math.Cos(deg2rad(125.04-1934.136*julianCentury[index]))
|
|
|
+ obliqCorr = append(obliqCorr, temp)
|
|
|
+ }
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+// Calculate the Sun Declination in degrees based on the formula: rad2deg(asin(sin(deg2rad(obliqCorr))*sin(deg2rad(sunAppLong))))
|
|
|
+// obliqCorr - Obliq Corr calculated by the calcObliqCorr function
|
|
|
+// sunAppLong - Sun App Long calculated by the calcSunAppLong function
|
|
|
+// Return the sun declination slice
|
|
|
+func calcSunDeclination(obliqCorr []float64, sunAppLong []float64) (sunDeclination []float64) {
|
|
|
+ if len(obliqCorr) != len(sunAppLong) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ for index := 0; index < len(obliqCorr); index++ {
|
|
|
+ temp := rad2deg(math.Asin(math.Sin(deg2rad(obliqCorr[index])) * math.Sin(deg2rad(sunAppLong[index]))))
|
|
|
+ sunDeclination = append(sunDeclination, temp)
|
|
|
+ }
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+// Calculate the equation of time (minutes) based on the formula:
|
|
|
+// 4*rad2deg(multiFactor*sin(2*deg2rad(geomMeanLongSun))-2*eccentEarthOrbit*sin(deg2rad(geomMeanAnomSun))+4*eccentEarthOrbit*multiFactor*sin(deg2rad(geomMeanAnomSun))*cos(2*deg2rad(geomMeanLongSun))-0.5*multiFactor*multiFactor*sin(4*deg2rad(geomMeanLongSun))-1.25*eccentEarthOrbit*eccentEarthOrbit*sin(2*deg2rad(geomMeanAnomSun)))
|
|
|
+// multiFactor - The Multi Factor vector calculated in the calculate function
|
|
|
+// geomMeanLongSun - The Geom Mean Long Sun vector calculated by the calcGeomMeanLongSun function
|
|
|
+// eccentEarthOrbit - The Eccent Earth vector calculated by the calcEccentEarthOrbit function
|
|
|
+// geomMeanAnomSun - The Geom Mean Anom Sun vector calculated by the calcGeomMeanAnomSun function
|
|
|
+// Return the equation of time slice
|
|
|
+func calcEquationOfTime(multiFactor []float64, geomMeanLongSun []float64, eccentEarthOrbit []float64, geomMeanAnomSun []float64) (equationOfTime []float64) {
|
|
|
+
|
|
|
+ if len(multiFactor) != len(geomMeanLongSun) ||
|
|
|
+ len(multiFactor) != len(eccentEarthOrbit) ||
|
|
|
+ len(multiFactor) != len(geomMeanAnomSun) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ for index := 0; index < len(multiFactor); index++ {
|
|
|
+ a := multiFactor[index] * math.Sin(2.0*deg2rad(geomMeanLongSun[index]))
|
|
|
+ b := 2.0 * eccentEarthOrbit[index] * math.Sin(deg2rad(geomMeanAnomSun[index]))
|
|
|
+ c := 4.0 * eccentEarthOrbit[index] * multiFactor[index] * math.Sin(deg2rad(geomMeanAnomSun[index]))
|
|
|
+ d := math.Cos(2.0 * deg2rad(geomMeanLongSun[index]))
|
|
|
+ e := 0.5 * multiFactor[index] * multiFactor[index] * math.Sin(4.0*deg2rad(geomMeanLongSun[index]))
|
|
|
+ f := 1.25 * eccentEarthOrbit[index] * eccentEarthOrbit[index] * math.Sin(2.0*deg2rad(geomMeanAnomSun[index]))
|
|
|
+ temp := 4.0 * rad2deg(a-b+c*d-e-f)
|
|
|
+ equationOfTime = append(equationOfTime, temp)
|
|
|
+ }
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+// Calculate the HaSunrise in degrees based on the formula: rad2deg(acos(cos(deg2rad(90.833))/(cos(deg2rad(latitude))*cos(deg2rad(sunDeclination)))-tan(deg2rad(latitude))*tan(deg2rad(sunDeclination))))
|
|
|
+// latitude - The latitude defined by the user
|
|
|
+// sunDeclination - The Sun Declination calculated by the calcSunDeclination function
|
|
|
+// Return the HaSunrise slice
|
|
|
+func calcHaSunrise(latitude float64, sunDeclination []float64) (haSunrise []float64) {
|
|
|
+ for index := 0; index < len(sunDeclination); index++ {
|
|
|
+ temp := rad2deg(math.Acos(math.Cos(deg2rad(90.833))/(math.Cos(deg2rad(latitude))*math.Cos(deg2rad(sunDeclination[index]))) - math.Tan(deg2rad(latitude))*math.Tan(deg2rad(sunDeclination[index]))))
|
|
|
+ haSunrise = append(haSunrise, temp)
|
|
|
+ }
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+// Calculate the Solar Noon based on the formula: (720 - 4 * longitude - equationOfTime + utcOffset * 60) * 60
|
|
|
+// longitude - The longitude is defined by the user
|
|
|
+// equationOfTime - The Equation of Time slice is calculated by the calcEquationOfTime function
|
|
|
+// utcOffset - The UTC offset is defined by the user
|
|
|
+// Return the Solar Noon slice
|
|
|
+func calcSolarNoon(longitude float64, equationOfTime []float64, utcOffset float64) (solarNoon []float64) {
|
|
|
+ for index := 0; index < len(equationOfTime); index++ {
|
|
|
+ temp := (720.0 - 4.0*longitude - equationOfTime[index] + utcOffset*60.0) * 60.0
|
|
|
+ solarNoon = append(solarNoon, temp)
|
|
|
+ }
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+// Check if the latitude is valid. Range: -90 - 90
|
|
|
+func checkLatitude(latitude float64) bool {
|
|
|
+ if latitude < -90.0 || latitude > 90.0 {
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ return true
|
|
|
+}
|
|
|
+
|
|
|
+// Check if the longitude is valid. Range: -180 - 180
|
|
|
+func checkLongitude(longitude float64) bool {
|
|
|
+ if longitude < -180.0 || longitude > 180.0 {
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ return true
|
|
|
+}
|
|
|
+
|
|
|
+// Check if the UTC offset is valid. Range: -12 - 14
|
|
|
+func checkUtcOffset(utcOffset float64) bool {
|
|
|
+ if utcOffset < -12.0 || utcOffset > 14.0 {
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ return true
|
|
|
+}
|
|
|
+
|
|
|
+// Check if the date is valid.
|
|
|
+func checkDate(date time.Time) bool {
|
|
|
+ minDate := time.Date(1900, 1, 1, 0, 0, 0, 0, time.UTC)
|
|
|
+ maxDate := time.Date(2200, 1, 1, 0, 0, 0, 0, time.UTC)
|
|
|
+ if date.Before(minDate) || date.After(maxDate) {
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ return true
|
|
|
+}
|
|
|
+
|
|
|
+// Compute the number of days between two dates
|
|
|
+func diffDays(date1, date2 time.Time) int64 {
|
|
|
+ return int64(date2.Sub(date1) / (24 * time.Hour))
|
|
|
+}
|
|
|
+
|
|
|
+// Find the index of the minimum value
|
|
|
+func minIndex(slice []float64) int {
|
|
|
+ if len(slice) == 0 {
|
|
|
+ return -1
|
|
|
+ }
|
|
|
+ min := slice[0]
|
|
|
+ minIndex := 0
|
|
|
+ for index := 0; index < len(slice); index++ {
|
|
|
+ if slice[index] < min {
|
|
|
+ min = slice[index]
|
|
|
+ minIndex = index
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return minIndex
|
|
|
+}
|
|
|
+
|
|
|
+// Convert each value to the absolute value
|
|
|
+func abs(slice []float64) []float64 {
|
|
|
+ var newSlice []float64
|
|
|
+ for _, value := range slice {
|
|
|
+ if value < 0.0 {
|
|
|
+ value = math.Abs(value)
|
|
|
+ }
|
|
|
+ newSlice = append(newSlice, value)
|
|
|
+ }
|
|
|
+ return newSlice
|
|
|
+}
|
|
|
+
|
|
|
+func round(value float64) int {
|
|
|
+ if value < 0 {
|
|
|
+ return int(value - 0.5)
|
|
|
+ }
|
|
|
+ return int(value + 0.5)
|
|
|
+}
|
|
|
+
|
|
|
+// GetSunriseSunset function is responsible for calculate the apparent Sunrise and Sunset times.
|
|
|
+// If some parameter is wrong it will return an error.
|
|
|
+func GetSunriseSunset(latitude float64, longitude float64, utcOffset float64, date time.Time) (sunrise time.Time, sunset time.Time, err error) {
|
|
|
+ // Check latitude
|
|
|
+ if !checkLatitude(latitude) {
|
|
|
+ err = errors.New("Invalid latitude")
|
|
|
+ return
|
|
|
+ }
|
|
|
+ // Check longitude
|
|
|
+ if !checkLongitude(longitude) {
|
|
|
+ err = errors.New("Invalid longitude")
|
|
|
+ return
|
|
|
+ }
|
|
|
+ // Check UTC offset
|
|
|
+ if !checkUtcOffset(utcOffset) {
|
|
|
+ err = errors.New("Invalid UTC offset")
|
|
|
+ return
|
|
|
+ }
|
|
|
+ // Check date
|
|
|
+ if !checkDate(date) {
|
|
|
+ err = errors.New("Invalid date")
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // The number of days since 30/12/1899
|
|
|
+ since := time.Date(1899, 12, 30, 0, 0, 0, 0, time.UTC)
|
|
|
+ numDays := diffDays(since, date)
|
|
|
+
|
|
|
+ // Seconds of a full day 86400
|
|
|
+ seconds := 24 * 60 * 60
|
|
|
+
|
|
|
+ // Creates a vector that represents each second in the range 0~1
|
|
|
+ secondsNorm := createSecondsNormalized(seconds)
|
|
|
+
|
|
|
+ // Calculate Julian Day
|
|
|
+ julianDay := calcJulianDay(numDays, secondsNorm, utcOffset)
|
|
|
+
|
|
|
+ // Calculate Julian Century
|
|
|
+ julianCentury := calcJulianCentury(julianDay)
|
|
|
+
|
|
|
+ // Geom Mean Long Sun (deg)
|
|
|
+ geomMeanLongSun := calcGeomMeanLongSun(julianCentury)
|
|
|
+
|
|
|
+ // Geom Mean Anom Sun (deg)
|
|
|
+ geomMeanAnomSun := calcGeomMeanAnomSun(julianCentury)
|
|
|
+
|
|
|
+ // Eccent Earth Orbit
|
|
|
+ eccentEarthOrbit := calcEccentEarthOrbit(julianCentury)
|
|
|
+
|
|
|
+ // Sun Eq of Ctr
|
|
|
+ sunEqCtr := calcSunEqCtr(julianCentury, geomMeanAnomSun)
|
|
|
+
|
|
|
+ // Sun True Long (deg)
|
|
|
+ sunTrueLong := calcSunTrueLong(sunEqCtr, geomMeanLongSun)
|
|
|
+
|
|
|
+ // Sun App Long (deg)
|
|
|
+ sunAppLong := calcSunAppLong(sunTrueLong, julianCentury)
|
|
|
+
|
|
|
+ // Mean Obliq Ecliptic (deg)
|
|
|
+ meanObliqEcliptic := calcMeanObliqEcliptic(julianCentury)
|
|
|
+
|
|
|
+ // Obliq Corr (deg)
|
|
|
+ obliqCorr := calcObliqCorr(meanObliqEcliptic, julianCentury)
|
|
|
+
|
|
|
+ // Sun Declin (deg)
|
|
|
+ sunDeclination := calcSunDeclination(obliqCorr, sunAppLong)
|
|
|
+
|
|
|
+ // var y
|
|
|
+ var multiFactor []float64
|
|
|
+ for index := 0; index < len(obliqCorr); index++ {
|
|
|
+ temp := math.Tan(deg2rad(obliqCorr[index]/2.0)) * math.Tan(deg2rad(obliqCorr[index]/2.0))
|
|
|
+ multiFactor = append(multiFactor, temp)
|
|
|
+ }
|
|
|
+
|
|
|
+ // Eq of Time (minutes)
|
|
|
+ equationOfTime := calcEquationOfTime(multiFactor, geomMeanLongSun, eccentEarthOrbit, geomMeanAnomSun)
|
|
|
+
|
|
|
+ // HA Sunrise (deg)
|
|
|
+ haSunrise := calcHaSunrise(latitude, sunDeclination)
|
|
|
+
|
|
|
+ // Solar Noon (LST)
|
|
|
+ solarNoon := calcSolarNoon(longitude, equationOfTime, utcOffset)
|
|
|
+
|
|
|
+ // Sunrise and Sunset Times (LST)
|
|
|
+ var tempSunrise []float64
|
|
|
+ var tempSunset []float64
|
|
|
+
|
|
|
+ for index := 0; index < len(solarNoon); index++ {
|
|
|
+ tempSunrise = append(tempSunrise, (solarNoon[index] - float64(round(haSunrise[index]*4.0*60.0)) - float64(seconds)*secondsNorm[index]))
|
|
|
+ tempSunset = append(tempSunset, (solarNoon[index] + float64(round(haSunrise[index]*4.0*60.0)) - float64(seconds)*secondsNorm[index]))
|
|
|
+ }
|
|
|
+
|
|
|
+ // Get the sunrise and sunset in seconds
|
|
|
+ sunriseSeconds := minIndex(abs(tempSunrise))
|
|
|
+ sunsetSeconds := minIndex(abs(tempSunset))
|
|
|
+
|
|
|
+ // Convert the seconds to time
|
|
|
+ defaultTime := new(time.Time)
|
|
|
+ sunrise = defaultTime.Add(time.Duration(sunriseSeconds) * time.Second)
|
|
|
+ sunset = defaultTime.Add(time.Duration(sunsetSeconds) * time.Second)
|
|
|
+
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+func SunriseSunsetForChina(latitude, longitude float64) (string, string, error) {
|
|
|
+ p := Parameters{
|
|
|
+ Latitude: latitude,
|
|
|
+ Longitude: longitude,
|
|
|
+ UtcOffset: 8.0,
|
|
|
+ Date: New(MlNow()).BeginningOfDay(),
|
|
|
+ }
|
|
|
+ // Get sunrise and sunset in seconds
|
|
|
+ sunrise, sunset, err := p.GetSunriseSunset()
|
|
|
+ if err != nil {
|
|
|
+ return "", "", err
|
|
|
+ }
|
|
|
+ if sunrise.Second() >= 30 {
|
|
|
+ sunrise = sunrise.Add(time.Minute)
|
|
|
+ }
|
|
|
+ if sunset.Second() >= 30 {
|
|
|
+ sunset = sunset.Add(time.Minute)
|
|
|
+ }
|
|
|
+ //return "16:17", "16:16", nil
|
|
|
+ return sunrise.Format("15:04"), sunset.Format("15:04"), nil
|
|
|
+}
|