/go-sampa

Package for calculating Sun and Moon position

Primary LanguageGoMIT LicenseMIT

Go SAMPA Go Reference Classic Go Reference

Go SAMPA is a package for calculating Sun and Moon position. SAMPA itself is acronym of Sun and Moon Position Algorithm. It uses algorithms from several sources:

  • Algorithm for calculating Sun position is taken from SPA paper by Ibrahim Reda and Afshin Andreas from NREL.
  • Algorithm for calculating Moon position is taken from SAMPA paper which also created by Ibrahim Reda and Afshin Andreas.
  • Algorithm for rise, set, transit time and phases of moon are taken from Astronomical Algorithms by Jean Meeus.

Table of Contents

Installation

To use this package, make sure your project use Go 1.20 or above, then run the following command via terminal:

go get -u -v github.com/hablullah/go-sampa

Features

  • Calculate Sun and Moon position for a given time and position.
  • Calculate rise, set and transit for Sun and Moon.
  • Calculate time when Sun or Moon reach a certain elevation.
  • Calculate moon phases around a specified date.
  • Thanks to Go, it will seamlessly handle DST times.
  • Fast and accurate enough for amateur use.

API

You can check the Go documentations to see the available APIs. However, the main interests in this package are:

  • Function GetSunPosition to calculate Sun location for the given time and location.
  • Function GetSunEvents to calculate Sunrise, Sunset, transit and any other additional events for the given time and location.
  • Function GetMoonPosition to calculate Moon location for the given time and location.
  • Function GetMoonEvents to calculate Moonrise, Moonset, transit and any other additional events for the given time and location.
  • Function GetMoonPhases to calculate the time for Moon phases around the specified date time.

Here is the example for all of those functions:

func main() {
	// Prepare location
	tz, _ := time.LoadLocation("Asia/Jakarta")
	jakarta := sampa.Location{Latitude: -6.14, Longitude: 106.81}

	// Fetch Sun position in Jakarta at 2023-05-20 18:15:00
	dt := time.Date(2023, 5, 20, 18, 15, 0, 0, tz)
	sunPosition, _ := sampa.GetSunPosition(dt, jakarta, nil)

	// Fetch Moon position in Jakarta at 2023-05-20 20:15:00
	dt = time.Date(2023, 5, 20, 20, 15, 0, 0, tz)
	moonPosition, _ := sampa.GetMoonPosition(dt, jakarta, nil)

	// Fetch Sun and Moon events in Jakarta at 2023-11-20
	dt = time.Date(2023, 11, 20, 0, 0, 0, 0, tz)
	sunEvents, _ := sampa.GetSunEvents(dt, jakarta, nil)
	moonEvents, _ := sampa.GetMoonEvents(dt, jakarta, nil)

	// Fetch Moon phases in Jakarta around 2023-03-05
	dt = time.Date(2023, 3, 5, 0, 0, 0, 0, tz)
	moonPhases := sampa.GetMoonPhases(dt, nil)

	// To handle DST, just load the timezone properly.
	// For example, here we calculate Sun in Oslo that use DST.
	cet, _ := time.LoadLocation("CET")
	oslo := sampa.Location{Latitude: 59.91, Longitude: 10.74}
	dt = time.Date(2023, 5, 20, 18, 15, 0, 0, cet)
	sunPositionInOslo, _ := sampa.GetSunPosition(dt, oslo, nil)
}

Accuracy

Disclaimer: I'm not an astronomer or physicist. I'm just an amateur with some interests toward celestial bodies.

This package has been extensively compared to Time and Date, which uses algorithm based on work by the U.S. Naval Observatory and NASA's Jet Propulsion Laboratory. I've compared the calculations for following locations:

Name Country Latitude Longitude Timezone Offset DST Offset
Lord Howe Island Australia 31°33'S 159°05'E Australia/Lord_Howe UTC+10:30 UTC+11:00
Maputo Mozambique 25°58'S 32°34'E Africa/Maputo UTC+02:00
Amsterdam Netherlands 52°22'N 4°54'E CET UTC+01:00 UTC+02:00
Oslo Norway 59°55'N 10°44'E CET UTC+01:00 UTC+02:00
Philipsburg Sint Maarten 18°02'N 63°03'W UTC-4 UTC-04:00
New York USA 40°43'N 74°01'W America/New_York UTC-05:00 UTC-04:00

The calculations can be seen in comparison directory.

From the comparison, I've found that by average the results are accurate to within a minute for both Sun and Moon events. The difference are pretty small for area around equators, and become quite large for area with higher latitude (>45°) where the Sun might not rise or set for the entire day. However, I argue this package is still correct and accurate enough to use.

For example, the largest time difference for Sun event in our comparison data is for astronomical dusk in Oslo at 22 April 2023:

  • TimeAndDate said the astronomical dusk will occur at "2023-04-22 01:00:16"
  • Go SAMPA calculation result is "2023-04-22 01:01:04" (48 seconds difference)

However, if we compare the Sun elevation angle for both times using the official SPA calculator, we'll get the following result:

  • At "2023-04-22 01:00:16" (TimeAndDate result) the Sun elevation is -17.995° (calc).
  • At "2023-04-22 01:01:04" (Go SAMPA result) the Sun elevation is -18.002° (calc).

Since astronomical dusk occured when Sun is 18° below horizons, both calculations are correct despite the huge time difference between them.

FAQ

  1. Does the elevation affects calculation result?

    Yes, it will affect the result for rise and set time. If the elevation is very high, it can affect the times by a couple of minutes thanks to atmospheric refraction. However, most apps that I know prefer to set elevation to zero, which means every locations will be treated as located in sea level.

  2. The rise and set times are different compared to reality!

    Apparently there are no algorithms that could exactly calculate when the Sun will rise and set, and I assume it's the same for the Moon.

  3. Are the calculation results are accurate up to seconds?

    While the results of this package are in seconds, as mentioned above there are several seconds different between this package and other famous calculators like TimeAndDate. So, it's better to not expect it to be exactly accurate to seconds, and instead treat it as minute rounding suggestions.

  4. Why are the sunrise and sunset times occured in different day?

    In this package, the sunrise and sunset are connected to transit time (the time when Sun reach meridian). However, in area with higher latitude sometime the Sun will never rise nor set for the entire day. In this case, sunrise might occur yesterday and the sunset might occur tomorrow.

  5. Why are the moonrise and moonset times not calculated?

    There are some days where Moon never reach the meridian. In those case the moonrise and moonset will not be calculated since in this package rise and set are chained to transit time.

Resources

  1. Reda, I.; Andreas, A. (2003). Solar Position Algorithm for Solar Radiation Applications. 55 pp.; NREL Report No. TP-560-34302, Revised January 2008. (web)
  2. Reda, I. (2010). Solar Eclipse Monitoring for Solar Energy Applications Using the Solar and Moon Position Algorithms. 35 pp.; NREL Report No. TP-3B0-47681. (web)
  3. Meeus, J. (1998). Astronomical Algorithms, Second Edition.

License

Go-Sampa is distributed using MIT license.