suncalc

package module
v0.0.0-...-291b193 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 14, 2025 License: BSD-2-Clause Imports: 2 Imported by: 10

README

= SunCalc
:source-highlighter: highlight.js

SunCalc is a tiny BSD-licensed Golang library for calculating sun position,
sunlight phases (times for sunrise, sunset, dusk, etc.),
moon position and lunar phase for the given location and time,
created originally in Javascript by [Vladimir Agafonkin](http://agafonkin.com/en) ([@mourner](https://github.com/mourner))
as a part of the [SunCalc.net project](http://suncalc.net).

Translated in GOLANG by Douglas Six

Most calculations are based on the formulas given in the excellent Astronomy Answers articles
about [position of the sun](http://aa.quae.nl/en/reken/zonpositie.html)
and [the planets](http://aa.quae.nl/en/reken/hemelpositie.html).
You can read about different twilight phases calculated by SunCalc
in the [Twilight article on Wikipedia](http://en.wikipedia.org/wiki/Twilight).


== Usage example

[source, go]
----
package main

import (
	"fmt"
	"github.com/pschou/go-suncalc"
	"math"
	"time"
)

func main() {
	var now = time.Now()

	// get today's sunlight times for London
	lat, long := 51.5, -0.1

	// get the times for today, latitude, longitude, height below or above the
	// horizon, and in timezone
	var times = suncalc.GetTimes(now, lat, long, 0, time.UTC)

	for _, oneTime := range times {
		fmt.Printf("%-13s %d-%02d-%02d %02d:%02d:%02d\n", string(oneTime.Name),
			oneTime.Value.Time.Year(), oneTime.Value.Time.Month(), oneTime.Value.Time.Day(),
			oneTime.Value.Time.Hour(), oneTime.Value.Time.Minute(), oneTime.Value.Time.Second())
	}

	// format sunrise time from the Date object
	fmt.Printf("Sunrise / Sunset time: %d:%02d / %d:%02d\n",
		times[suncalc.Sunrise].Value.Time.Hour(), times[suncalc.Sunrise].Value.Time.Minute(),
		times[suncalc.Sunset].Value.Time.Hour(), times[suncalc.Sunset].Value.Time.Minute(),
	)

	// get position of the sun (azimuth and altitude) at today's sunrise
	var sunrisePos = suncalc.GetPosition(times[suncalc.Sunrise].Value.Time, lat, long)

	// get sunrise azimuth in degrees
	var sunriseAzimuth = sunrisePos.Azimuth * 180 / math.Pi
	fmt.Printf("Sunrise Azimuth: %f deg\n", sunriseAzimuth)

	// get position of the sun (azimuth and altitude) at today's sunset
	var sunsetPos = suncalc.GetPosition(times[suncalc.Sunset].Value.Time, lat, long)

	// get the sunset azimuth in degrees
	var sunsetAzimuth = sunsetPos.Azimuth * 180 / math.Pi
	fmt.Printf("Sunset Azimuth: %f deg\n", sunsetAzimuth)

	// get current position of the sun (azimuth and altitude) at today's sunrise
	var sunPos = suncalc.GetPosition(now, lat, long)
	fmt.Printf("Sun Azimuth: %f deg\n", sunPos.Azimuth*180/math.Pi)
	fmt.Printf("Sun Altitude: %f deg\n", sunPos.Altitude*180/math.Pi)
}
----

== Reference

=== Sunlight times

[source, go]
----
suncalc.GetTimes(date time.Time, latitude float64, longitude float64, height float64, location *time.Location)
----

Returns an object with the following properties (each is a `Date` object):

[cols="30h,70d"]
|===
| Property
| Description


| `sunrise`
| sunrise (top edge of the sun appears on the horizon)

| `sunriseEnd`
| sunrise ends (bottom edge of the sun touches the horizon)

| `goldenHourEnd`
| morning golden hour (soft light, best time for photography) ends

| `solarNoon`
| solar noon (sun is in the highest position)

| `goldenHour`
| evening golden hour starts

| `sunsetStart`
| sunset starts (bottom edge of the sun touches the horizon)

| `sunset`
| sunset (sun disappears below the horizon, evening civil twilight starts)

| `dusk`
| dusk (evening nautical twilight starts)

| `nauticalDusk`
| nautical dusk (evening astronomical twilight starts)

| `night`
| night starts (dark enough for astronomical observations)

| `nadir`
| nadir (darkest moment of the night, sun is in the lowest position)

| `nightEnd`
| night ends (morning astronomical twilight starts)

| `nauticalDawn`
| nautical dawn (morning nautical twilight starts)

| `dawn`
| dawn (morning nautical twilight ends, morning civil twilight starts)
|===

=== Sun position

[source, go]
----
suncalc.GetPosition(timeAndDate time.Time, latitude float64, longitude float64)
----

Returns an object with the following properties:

 * `Altitude`: sun altitude above the horizon in radians,
 e.g. `0` at the horizon and `PI/2` at the zenith (straight over your head)
 * `Azimuth`: sun azimuth in radians (direction along the horizon, measured from south to west),
 e.g. `0` is south and `Math.PI * 3/4` is northwest


=== Moon position

[source, go]
----
suncalc.GetMoonPosition(date time.Time, latitude float64, longitude float64)
----

Returns an object with the following properties:

 * `Altitude`: moon altitude above the horizon in radians
 * `Azimuth`: moon azimuth in radians
 * `Distance`: distance to moon in kilometers
 * `ParallacticAngle`: parallactic angle of the moon in radians


=== Moon illumination

[source, go]
----
suncalc.GetMoonIllumination(timeAndDate time.Time)
----

Returns an object with the following properties:

 * `Fraction`: illuminated fraction of the moon; varies from `0.0` (new moon) to `1.0` (full moon)
 * `Phase`: moon phase; varies from `0.0` to `1.0`, described below
 * `Angle`: midpoint angle in radians of the illuminated limb of the moon reckoned eastward from the north point of the disk;
 the moon is waxing if the angle is negative, and waning if positive

Moon phase value should be interpreted like this:

[cols="20h,80d"]
|===
| Phase
| Name

| 0
| New Moon

|
| Waxing Crescent

| 0.25
| First Quarter

|
| Waxing Gibbous

| 0.5
| Full Moon

|
| Waning Gibbous

| 0.75
| Last Quarter

|
| Waning Crescent
|===


By subtracting the `parallacticAngle` from the `angle` one can get the zenith angle of the moons bright limb (anticlockwise).
The zenith angle can be used do draw the moon shape from the observers perspective (e.g. moon lying on its back).

=== Moon rise and set times

[source, go]
----
suncalc.GetMoonTimes(date time.Time, latitude float64, longitude float64[, inUTC bool])
----

Returns an object with the following properties:

 * `Rise`: moonrise time as `Date`
 * `Set`: moonset time as `Date`
 * `AlwaysUp`: `true` if the moon never rises/sets and is always _above_ the horizon during the day
 * `AlwaysDown`: `true` if the moon is always _below_ the horizon

By default, it will search for moon rise and set during local user's day (from 0 to 24 hours).
If `inUTC` is set to true, it will instead search the specified date from 0 to 24 UTC hours.

== Changelog

=== 1.1.0 - Mai 23, 2020
* `suncalc.GetTimes()` now takes two additional parameters:
** `height`: positive elevation position. Can be set to 0, if not known.
** `location`: time.Location for the result Time. It can be `nil`
* `DayTime` structure members changed. `MorningName` becomes `Name` and `Time` becomes `Value` of type `sql.NullTime`
to have the valuable information about the validity of the date. In fact, in some places and time some values are
not possible: close to the polars the sun does not set in summer and does not rise in winter.
* Add some unit tests
* Update Documentation

=== 1.0.2 - Mai 21, 2019
* Finish documentation.
* Make sure all struct fields are visible from outside.

=== 1.0.1 - Mai 18, 2019
* Place SunCalc in his own package.
* Make some struct variables visible from outside.

=== 1.0.0 - Mai 18, 2019
* First commit.

Documentation

Index

Examples

Constants

View Source
const J0 = 0.0009

calculations for sun times

View Source
const J1970 = 2440588
View Source
const J2000 = 2451545

Variables

Functions

func GetTimes

func GetTimes(date time.Time, lat float64, lng float64) map[DayTimeName]DayTime

calculates sun times for a given date and latitude/longitude

Example
package main

import (
	"fmt"
	"math"
	"time"

	"github.com/sixdouglas/suncalc"
)

func main() {
	var now = time.Date(2005, 6, 1, 12, 0, 0, 0, time.UTC)

	// Location to query for
	lat, long := 51.5, -0.1

	// get the times for today, latitude, longitude, height below or above the
	// horizon, and in timezone
	var times = suncalc.GetTimes(now, lat, long)

	for _, timeOfDay := range suncalc.DayTimeNames {
		oneTime := times[timeOfDay]
		if !oneTime.Value.IsZero() {
			fmt.Printf("%-13s %s\n", string(oneTime.Name),
				oneTime.Value.Format("2006-01-02 15:04:05"))
		}
	}

	// format sunrise time from the Date object
	fmt.Printf("Sunrise / Sunset time: %s / %s\n",
		times[suncalc.Sunrise].Value.Format("15:04:05"),
		times[suncalc.Sunset].Value.Format("15:04:05"),
	)

	// get position of the sun (azimuth and altitude) at today's sunrise
	var sunrisePos = suncalc.GetPosition(times[suncalc.Sunrise].Value, lat, long)

	// get sunrise azimuth in degrees
	var sunriseAzimuth = sunrisePos.Azimuth * 180 / math.Pi
	fmt.Printf("Sunrise Azimuth: %f deg\n", sunriseAzimuth)

	// get position of the sun (azimuth and altitude) at today's sunset
	var sunsetPos = suncalc.GetPosition(times[suncalc.Sunset].Value, lat, long)

	// get the sunset azimuth in degrees
	var sunsetAzimuth = sunsetPos.Azimuth * 180 / math.Pi
	fmt.Printf("Sunset Azimuth: %f deg\n", sunsetAzimuth)

	// get current position of the sun (azimuth and altitude) at today's sunrise
	var sunPos = suncalc.GetPosition(now, lat, long)
	fmt.Printf("Sun Azimuth: %f deg\n", sunPos.Azimuth*180/math.Pi)
	fmt.Printf("Sun Altitude: %f deg\n", sunPos.Altitude*180/math.Pi)
}
Output:
nauticalDawn  2005-06-01 01:57:31
dawn          2005-06-01 03:04:43
sunrise       2005-06-01 03:50:12
sunriseEnd    2005-06-01 03:54:33
goldenHourEnd 2005-06-01 04:42:52
goldenHour    2005-06-01 19:16:35
sunsetStart   2005-06-01 20:04:54
sunset        2005-06-01 20:09:15
dusk          2005-06-01 20:54:44
nauticalDusk  2005-06-01 22:01:56
Sunrise / Sunset time: 03:50:12 / 20:09:15
Sunrise Azimuth: -128.374196 deg
Sunset Azimuth: 128.610491 deg
Sun Azimuth: 0.351955 deg
Sun Altitude: 60.593709 deg

func GetTimesWithObserver

func GetTimesWithObserver(date time.Time, obs Observer) map[DayTimeName]DayTime

calculates sun times for a given date and latitude/longitude, and, the observer height (in meters) relative to the horizon, you can set it to 0 if unknown

Example
package main

import (
	"fmt"
	"math"
	"time"

	"github.com/sixdouglas/suncalc"
)

func main() {
	var now = time.Date(2012, 12, 12, 12, 0, 0, 0, time.UTC)
	// Use time.Now() for today

	// Location to query for
	lat, long := 51.5, -0.1

	// get the times for today, latitude, longitude, height below or above the
	// horizon, and in timezone
	var observer = suncalc.Observer{
		Latitude:  lat,
		Longitude: long,
		Height:    0,
		Location:  time.UTC,
	}

	var times = suncalc.GetTimesWithObserver(now, observer)

	for _, timeOfDay := range suncalc.DayTimeNames {
		oneTime := times[timeOfDay]
		if !oneTime.Value.IsZero() {
			fmt.Printf("%-13s %s\n", string(oneTime.Name),
				oneTime.Value.Format("2006-01-02 15:04:05"))
		}
	}

	// format sunrise time from the Date object
	fmt.Printf("Sunrise / Sunset time: %s / %s\n",
		times[suncalc.Sunrise].Value.Format("15:04:05"),
		times[suncalc.Sunset].Value.Format("15:04:05"),
	)

	// get position of the sun (azimuth and altitude) at today's sunrise
	var sunrisePos = suncalc.GetPosition(times[suncalc.Sunrise].Value, lat, long)

	// get sunrise azimuth in degrees
	var sunriseAzimuth = sunrisePos.Azimuth * 180 / math.Pi
	fmt.Printf("Sunrise Azimuth: %f deg\n", sunriseAzimuth)

	// get position of the sun (azimuth and altitude) at today's sunset
	var sunsetPos = suncalc.GetPosition(times[suncalc.Sunset].Value, lat, long)

	// get the sunset azimuth in degrees
	var sunsetAzimuth = sunsetPos.Azimuth * 180 / math.Pi
	fmt.Printf("Sunset Azimuth: %f deg\n", sunsetAzimuth)

	// get current position of the sun (azimuth and altitude) at today's sunrise
	var sunPos = suncalc.GetPosition(now, lat, long)
	fmt.Printf("Sun Azimuth: %f deg\n", sunPos.Azimuth*180/math.Pi)
	fmt.Printf("Sun Altitude: %f deg\n", sunPos.Altitude*180/math.Pi)
}
Output:
nightEnd      2012-12-12 05:54:58
nauticalDawn  2012-12-12 06:35:38
dawn          2012-12-12 07:18:37
sunrise       2012-12-12 07:58:39
sunriseEnd    2012-12-12 08:03:00
goldenHourEnd 2012-12-12 08:59:36
goldenHour    2012-12-12 14:51:47
sunsetStart   2012-12-12 15:48:23
sunset        2012-12-12 15:52:45
dusk          2012-12-12 16:32:47
nauticalDusk  2012-12-12 17:15:46
night         2012-12-12 17:56:26
Sunrise / Sunset time: 07:58:39 / 15:52:45
Sunrise Azimuth: -52.101764 deg
Sunset Azimuth: 52.356679 deg
Sun Azimuth: 1.187845 deg
Sun Altitude: 15.381733 deg

Types

type DayTime

type DayTime struct {
	Name  DayTimeName
	Value time.Time
}

type DayTimeName

type DayTimeName string
const (
	Sunrise DayTimeName = "sunrise" // sunrise (top edge of the sun appears on the horizon)
	Sunset  DayTimeName = "sunset"  // sunset (sun disappears below the horizon, evening civil twilight starts)

	SunriseEnd  DayTimeName = "sunriseEnd"  // sunrise ends (bottom edge of the sun touches the horizon)
	SunsetStart DayTimeName = "sunsetStart" // sunset starts (bottom edge of the sun touches the horizon)

	Dawn DayTimeName = "dawn" // dawn (morning nautical twilight ends, morning civil twilight starts)
	Dusk DayTimeName = "dusk" // dusk (evening nautical twilight starts)

	NauticalDawn DayTimeName = "nauticalDawn" // nautical dawn (morning nautical twilight starts)
	NauticalDusk DayTimeName = "nauticalDusk" // nautical dusk (evening astronomical twilight starts)

	NightEnd DayTimeName = "nightEnd" // night ends (morning astronomical twilight starts)
	Night    DayTimeName = "night"    // night starts (dark enough for astronomical observations)

	GoldenHourEnd DayTimeName = "goldenHourEnd" // morning golden hour (soft light, best DayTime for photography) ends
	GoldenHour    DayTimeName = "goldenHour"    // evening golden hour starts

	SolarNoon DayTimeName = "solarNoon" // solar noon (sun is in the highest position)
	Nadir     DayTimeName = "nadir"     // nadir (darkest moment of the night, sun is in the lowest position)
)

type MoonIllumination

type MoonIllumination struct {
	Fraction float64
	Phase    float64
	Angle    float64
}

func GetMoonIllumination

func GetMoonIllumination(date time.Time) MoonIllumination

calculations for illumination parameters of the moon, based on http://idlastro.gsfc.nasa.gov/ftp/pro/astro/mphase.pro formulas and Chapter 48 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998.

type MoonPosition

type MoonPosition struct {
	Azimuth          float64
	Altitude         float64
	Distance         float64
	ParallacticAngle float64
}

func GetMoonPosition

func GetMoonPosition(date time.Time, lat float64, lng float64) MoonPosition

type MoonTimes

type MoonTimes struct {
	Rise       time.Time
	Set        time.Time
	AlwaysUp   bool
	AlwaysDown bool
}

func GetMoonTimes

func GetMoonTimes(date time.Time, lat float64, lng float64, inUTC bool) MoonTimes

calculations for moon rise/set times are based on http://www.stargazing.net/kepler/moonrise.html article

func GetMoonTimesWithObserver

func GetMoonTimesWithObserver(date time.Time, obs Observer) MoonTimes

calculations for moon rise/set times are based on http://www.stargazing.net/kepler/moonrise.html article

type Observer

type Observer struct {
	// Location of the observer
	Latitude, Longitude,

	Height float64

	Location *time.Location
}

type SunPosition

type SunPosition struct {
	Azimuth  float64
	Altitude float64
}

func GetPosition

func GetPosition(date time.Time, lat float64, lng float64) SunPosition

calculates sun position for a given date and latitude/longitude

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL