Vendor dependencies
This commit is contained in:
+10
@@ -0,0 +1,10 @@
|
||||
language: go
|
||||
|
||||
go:
|
||||
- stable
|
||||
|
||||
before_install:
|
||||
- go install github.com/mattn/goveralls@latest
|
||||
|
||||
script:
|
||||
- $GOPATH/bin/goveralls -service=travis-ci
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017 Nathan Osman
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
## go-sunrise
|
||||
|
||||
[](https://app.travis-ci.com/nathan-osman/go-sunrise)
|
||||
[](https://coveralls.io/github/nathan-osman/go-sunrise?branch=master)
|
||||
[](https://goreportcard.com/report/github.com/nathan-osman/go-sunrise)
|
||||
[](https://godoc.org/github.com/nathan-osman/go-sunrise)
|
||||
[](http://opensource.org/licenses/MIT)
|
||||
|
||||
Go package for calculating the sunrise and sunset times for a given location based on [this method](https://en.wikipedia.org/wiki/Sunrise_equation#Complete_calculation_on_Earth).
|
||||
|
||||
### Usage
|
||||
|
||||
To calculate sunrise and sunset times, you will need the following information:
|
||||
|
||||
- the date for which you wish to calculate the times
|
||||
- the latitude and longitudinal coordinates of the location
|
||||
|
||||
Begin by importing the package:
|
||||
|
||||
import "github.com/nathan-osman/go-sunrise"
|
||||
|
||||
Next, feed the information into the SunriseSunset() method:
|
||||
|
||||
rise, set := sunrise.SunriseSunset(
|
||||
43.65, -79.38, // Toronto, CA
|
||||
2000, time.January, 1, // 2000-01-01
|
||||
)
|
||||
|
||||
The two return values will be the sunrise and sunset times for the location on the given day as time.Time values. If sun does not rise or set, both return values will be time.Time{}.
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
package sunrise
|
||||
|
||||
import (
|
||||
"math"
|
||||
)
|
||||
|
||||
// SolarMeanAnomaly calculates the angle of the sun relative to the earth for
|
||||
// the specified Julian day.
|
||||
func SolarMeanAnomaly(d float64) float64 {
|
||||
v := math.Remainder(357.5291+0.98560028*(d-J2000), 360)
|
||||
if v < 0 {
|
||||
v += 360
|
||||
}
|
||||
return v
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
package sunrise
|
||||
|
||||
import (
|
||||
"math"
|
||||
)
|
||||
|
||||
// EquationOfCenter calculates the angular difference between the position of
|
||||
// the earth in its elliptical orbit and the position it would occupy in a
|
||||
// circular orbit for the given mean anomaly.
|
||||
func EquationOfCenter(solarAnomaly float64) float64 {
|
||||
var (
|
||||
anomalyInRad = solarAnomaly * (math.Pi / 180)
|
||||
anomalySin = math.Sin(anomalyInRad)
|
||||
anomaly2Sin = math.Sin(2 * anomalyInRad)
|
||||
anomaly3Sin = math.Sin(3 * anomalyInRad)
|
||||
)
|
||||
return 1.9148*anomalySin + 0.0200*anomaly2Sin + 0.0003*anomaly3Sin
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package sunrise
|
||||
|
||||
import (
|
||||
"math"
|
||||
)
|
||||
|
||||
const (
|
||||
// Degree provides a precise fraction for converting between degrees and
|
||||
// radians.
|
||||
Degree = math.Pi / 180
|
||||
|
||||
// J2000 is the Julian date for January 1, 2000, 12:00:00 TT.
|
||||
J2000 = 2451545
|
||||
)
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package sunrise
|
||||
|
||||
import (
|
||||
"math"
|
||||
)
|
||||
|
||||
// Declination calculates one of the two angles required to locate a point on
|
||||
// the celestial sphere in the equatorial coordinate system. The ecliptic
|
||||
// longitude parameter must be in degrees.
|
||||
func Declination(eclipticLongitude float64) float64 {
|
||||
return math.Asin(math.Sin(eclipticLongitude*Degree)*0.39779) / Degree
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
package sunrise
|
||||
|
||||
import (
|
||||
"math"
|
||||
"time"
|
||||
)
|
||||
|
||||
// TimeOfElevation calculates the times of day when the sun is at a given elevation
|
||||
// above the horizon on a given day at the specified location.
|
||||
// Returns time.Time{} if there sun does not reach the elevation
|
||||
func TimeOfElevation(latitude, longitude, elevation float64, year int, month time.Month, day int) (time.Time, time.Time) {
|
||||
var (
|
||||
d = MeanSolarNoon(longitude, year, month, day)
|
||||
solarAnomaly = SolarMeanAnomaly(d)
|
||||
equationOfCenter = EquationOfCenter(solarAnomaly)
|
||||
eclipticLongitude = EclipticLongitude(solarAnomaly, equationOfCenter, d)
|
||||
solarTransit = SolarTransit(d, solarAnomaly, eclipticLongitude)
|
||||
declination = Declination(eclipticLongitude)
|
||||
// https://solarsena.com/solar-elevation-angle-altitude/
|
||||
numerator = math.Sin(elevation*Degree) - (math.Sin(latitude*Degree) * math.Sin(declination*Degree))
|
||||
denominator = math.Cos(latitude*Degree) * math.Cos(declination*Degree)
|
||||
hourAngle = math.Acos(numerator / denominator)
|
||||
frac = hourAngle / (2 * math.Pi)
|
||||
morning = solarTransit - frac
|
||||
evening = solarTransit + frac
|
||||
)
|
||||
|
||||
// Check for cases where the sun never reaches the given elevation.
|
||||
if math.IsNaN(hourAngle) {
|
||||
return time.Time{}, time.Time{}
|
||||
}
|
||||
|
||||
return JulianDayToTime(morning), JulianDayToTime(evening)
|
||||
}
|
||||
|
||||
// Elevation calculates the angle of the sun above the horizon at a given moment
|
||||
// at the specified location.
|
||||
func Elevation(latitude, longitude float64, when time.Time) float64 {
|
||||
var (
|
||||
d = MeanSolarNoon(longitude, when.Year(), when.Month(), when.Day())
|
||||
solarAnomaly = SolarMeanAnomaly(d)
|
||||
equationOfCenter = EquationOfCenter(solarAnomaly)
|
||||
eclipticLongitude = EclipticLongitude(solarAnomaly, equationOfCenter, d)
|
||||
solarTransit = SolarTransit(d, solarAnomaly, eclipticLongitude)
|
||||
declination = Declination(eclipticLongitude)
|
||||
frac = solarTransit - TimeToJulianDay(when)
|
||||
hourAngle = 2 * math.Pi * frac
|
||||
// https://solarsena.com/solar-elevation-angle-altitude/
|
||||
firstPart = math.Sin(latitude*Degree) * math.Sin(declination*Degree)
|
||||
secondPart = math.Cos(latitude*Degree) * math.Cos(declination*Degree) * math.Cos(hourAngle)
|
||||
)
|
||||
|
||||
return math.Asin(firstPart+secondPart) / Degree
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
package sunrise
|
||||
|
||||
import (
|
||||
"math"
|
||||
)
|
||||
|
||||
// HourAngle calculates the second of the two angles required to locate a point
|
||||
// on the celestial sphere in the equatorial coordinate system.
|
||||
func HourAngle(latitude, declination float64) float64 {
|
||||
var (
|
||||
latitudeRad = latitude * Degree
|
||||
declinationRad = declination * Degree
|
||||
numerator = -0.01449 - math.Sin(latitudeRad)*math.Sin(declinationRad)
|
||||
denominator = math.Cos(latitudeRad) * math.Cos(declinationRad)
|
||||
)
|
||||
|
||||
// Check for no sunrise/sunset
|
||||
if numerator/denominator > 1 {
|
||||
// Sun never rises
|
||||
return math.MaxFloat64
|
||||
}
|
||||
|
||||
if numerator/denominator < -1 {
|
||||
// Sun never sets
|
||||
return -1 * math.MaxFloat64
|
||||
}
|
||||
|
||||
return math.Acos(numerator/denominator) / Degree
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package sunrise
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
secondsInADay = 86400
|
||||
unixEpochJulianDay = 2440587.5
|
||||
)
|
||||
|
||||
// TimeToJulianDay converts a time.Time into a Julian day.
|
||||
func TimeToJulianDay(t time.Time) float64 {
|
||||
return float64(t.Unix())/secondsInADay + unixEpochJulianDay
|
||||
}
|
||||
|
||||
// JulianDayToTime converts a Julian day into a time.Time.
|
||||
func JulianDayToTime(d float64) time.Time {
|
||||
return time.Unix(int64((d-unixEpochJulianDay)*secondsInADay), 0).UTC()
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
package sunrise
|
||||
|
||||
import (
|
||||
"math"
|
||||
)
|
||||
|
||||
// EclipticLongitude calculates the angular distance of the earth along the
|
||||
// ecliptic.
|
||||
func EclipticLongitude(solarAnomaly, equationOfCenter, d float64) float64 {
|
||||
return math.Mod(solarAnomaly+equationOfCenter+180+ArgumentOfPerihelion(d), 360)
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package sunrise
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// MeanSolarNoon calculates the time at which the sun is at its highest
|
||||
// altitude. The returned time is in Julian days.
|
||||
func MeanSolarNoon(longitude float64, year int, month time.Month, day int) float64 {
|
||||
t := time.Date(year, month, day, 12, 0, 0, 0, time.UTC)
|
||||
return TimeToJulianDay(t) - longitude/360
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package sunrise
|
||||
|
||||
// ArgumentOfPerihelion calculates the argument of periapsis for the earth on
|
||||
// the given Julian day.
|
||||
func ArgumentOfPerihelion(d float64) float64 {
|
||||
return 102.93005 + 0.3179526*(d-2451545)/36525
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package sunrise
|
||||
|
||||
import "math"
|
||||
|
||||
// DefaultPlaces specifies the default precision for rounding.
|
||||
const DefaultPlaces = 5
|
||||
|
||||
// Round takes the provided float and rounds it to the specified number of
|
||||
// decimal places. This function is adapted from user korya on GitHub
|
||||
// (https://gist.github.com/DavidVaini/10308388#gistcomment-1391788).
|
||||
func Round(f float64, places int) float64 {
|
||||
shift := math.Pow(10, float64(places))
|
||||
return math.Floor(f*shift+.5) / shift
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
package sunrise
|
||||
|
||||
import (
|
||||
"math"
|
||||
"time"
|
||||
)
|
||||
|
||||
// SunriseSunset calculates when the sun will rise and when it will set on the
|
||||
// given day at the specified location.
|
||||
// Returns time.Time{} if there sun does not rise or set
|
||||
func SunriseSunset(latitude, longitude float64, year int, month time.Month, day int) (time.Time, time.Time) {
|
||||
var (
|
||||
d = MeanSolarNoon(longitude, year, month, day)
|
||||
solarAnomaly = SolarMeanAnomaly(d)
|
||||
equationOfCenter = EquationOfCenter(solarAnomaly)
|
||||
eclipticLongitude = EclipticLongitude(solarAnomaly, equationOfCenter, d)
|
||||
solarTransit = SolarTransit(d, solarAnomaly, eclipticLongitude)
|
||||
declination = Declination(eclipticLongitude)
|
||||
hourAngle = HourAngle(latitude, declination)
|
||||
frac = hourAngle / 360
|
||||
sunrise = solarTransit - frac
|
||||
sunset = solarTransit + frac
|
||||
)
|
||||
|
||||
// Check for no sunrise, no sunset
|
||||
if hourAngle == math.MaxFloat64 || hourAngle == -1*math.MaxFloat64 {
|
||||
return time.Time{}, time.Time{}
|
||||
}
|
||||
|
||||
return JulianDayToTime(sunrise), JulianDayToTime(sunset)
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package sunrise
|
||||
|
||||
import (
|
||||
"math"
|
||||
)
|
||||
|
||||
// SolarTransit calculates the Julian data for the local true solar transit.
|
||||
func SolarTransit(d, solarAnomaly, eclipticLongitude float64) float64 {
|
||||
equationOfTime := 0.0053*math.Sin(solarAnomaly*Degree) -
|
||||
0.0069*math.Sin(2*eclipticLongitude*Degree)
|
||||
return d + equationOfTime
|
||||
}
|
||||
Reference in New Issue
Block a user