- 新增时标、ΔT 模型、质心时间与 UT1 支持 - 改进日月食、月掩、行星事件及路径边界计算 - 完善恒星三维自行与动态距离传播 - 扩展 SVG、GeoJSON、KML 输出与底层距离换算工具 - 整理中英文手册、示例资源及回归测试
56 KiB
Planets
The seven major planets each have a package of their own: mercury, venus, mars, jupiter, saturn, uranus, and neptune.
They share the same API shape: a civil instant is passed as time.Time, angles and distances come back as float64, and event searches return time.Time or a struct.
The inner planets (Mercury and Venus) add superior/inferior conjunction, greatest elongation, and geocentric transit; the outer planets (Mars through Neptune) add opposition and quadrature; Jupiter alone has the Galilean satellites and Saturn alone has ring parameters. The low-level VSOP87 series and the solar/lunar analytic series live in the planet package, shared by these seven packages and by sun / moon.
-
The function names of the common capabilities are identical across the seven packages (for example all of them provide
ApparentRa,ApparentDec, andApparentRaDec); only the extra families differ.Always qualify a call with its package name instead of mixing packages.
-
Position functions return a geocentric apparent place.
Topocentric quantities and horizontal coordinates are separate:
Altitude/Azimuth/Zenith/HourAngle/ParallacticAngle, with formulas under Coordinate Tools. -
Event-search families come as
Last.../Next...pairs (some alsoClosest...) and always return the nearest event at or before/after the input instant, endpoints included. -
The planets have no dedicated SVG chart entry point; occultation-related charts (including Saturn-ring occultations) are documented in Lunar Occultations.
Contents
- The position and rise time of Mars
- API Reference
- Usage examples
- Basic examples
- Topic examples
- Position and coordinates
- Rise, set and culmination
- Conjunctions, oppositions, stations and quadratures
- Greatest elongation and geocentric transits
- Nodes, phase, magnitude, diameter and parallactic angle
- Division of labour with other manuals
- Physical ephemerides
- Galilean satellites of Jupiter
- Shared types and constants from the
planetpackage
- Parameter and result conventions
The position and rise time of Mars
package main
import (
"fmt"
"log"
"time"
"b612.me/astro/mars"
)
func main() {
cst := time.FixedZone("CST", 8*3600)
date := time.Date(2020, 1, 1, 8, 8, 8, 0, cst)
lon, lat, height := 108.93, 34.27, 0.0
ra, dec := mars.ApparentRaDec(date)
fmt.Printf("RA=%.6f Dec=%.6f deg\n", ra, dec)
rise, err := mars.RiseTime(date, lon, lat, height, true)
if err != nil {
log.Fatal(err)
}
fmt.Println(rise.Format(time.RFC3339))
}
ApparentRaDec returns geocentric apparent right ascension and declination in degrees. Rise/set also needs a site and ellipsoidal height, and returns an error when no rise event exists.
API Reference
Cross-planet comparison
Rows list capabilities and columns list planetary packages. Qualify each function with its package, for example mars.NextOpposition. A slash separates function names; — means the package has no corresponding API.
| Capability | mercury |
venus |
mars |
jupiter |
saturn |
uranus |
neptune |
|---|---|---|---|---|---|---|---|
| Apparent ecliptic longitude / latitude | ApparentLo / ApparentBo |
ApparentLo / ApparentBo |
ApparentLo / ApparentBo |
ApparentLo / ApparentBo |
ApparentLo / ApparentBo |
ApparentLo / ApparentBo |
ApparentLo / ApparentBo |
| Apparent right ascension / declination | ApparentRa / ApparentDec / ApparentRaDec |
ApparentRa / ApparentDec / ApparentRaDec |
ApparentRa / ApparentDec / ApparentRaDec |
ApparentRa / ApparentDec / ApparentRaDec |
ApparentRa / ApparentDec / ApparentRaDec |
ApparentRa / ApparentDec / ApparentRaDec |
ApparentRa / ApparentDec / ApparentRaDec |
| Apparent magnitude | ApparentMagnitude |
ApparentMagnitude |
ApparentMagnitude |
ApparentMagnitude |
ApparentMagnitude |
ApparentMagnitude |
ApparentMagnitude |
| Geocentric / heliocentric distance | EarthDistance / SunDistance |
EarthDistance / SunDistance |
EarthDistance / SunDistance |
EarthDistance / SunDistance |
EarthDistance / SunDistance |
EarthDistance / SunDistance |
EarthDistance / SunDistance |
| Orbital ascending / descending node | AscendingNode / DescendingNode |
AscendingNode / DescendingNode |
AscendingNode / DescendingNode |
AscendingNode / DescendingNode |
AscendingNode / DescendingNode |
AscendingNode / DescendingNode |
AscendingNode / DescendingNode |
| Apparent diameter / semidiameter | Diameter / Semidiameter |
Diameter / Semidiameter |
Diameter / Semidiameter |
Diameter / Semidiameter |
Diameter / Semidiameter |
Diameter / Semidiameter |
Diameter / Semidiameter |
| Phase angle / illuminated fraction / bright-limb position angle | PhaseAngle / Phase / IlluminatedFraction / BrightLimbPositionAngle |
PhaseAngle / Phase / IlluminatedFraction / BrightLimbPositionAngle |
PhaseAngle / Phase / IlluminatedFraction / BrightLimbPositionAngle |
PhaseAngle / Phase / IlluminatedFraction / BrightLimbPositionAngle |
PhaseAngle / Phase / IlluminatedFraction / BrightLimbPositionAngle |
PhaseAngle / Phase / IlluminatedFraction / BrightLimbPositionAngle |
PhaseAngle / Phase / IlluminatedFraction / BrightLimbPositionAngle |
| Topocentric horizontal quantities | Altitude / Azimuth / Zenith / HourAngle / ParallacticAngle |
Altitude / Azimuth / Zenith / HourAngle / ParallacticAngle |
Altitude / Azimuth / Zenith / HourAngle / ParallacticAngle |
Altitude / Azimuth / Zenith / HourAngle / ParallacticAngle |
Altitude / Azimuth / Zenith / HourAngle / ParallacticAngle |
Altitude / Azimuth / Zenith / HourAngle / ParallacticAngle |
Altitude / Azimuth / Zenith / HourAngle / ParallacticAngle |
| Rise / set / culmination | RiseTime / SetTime / DownTime / CulminationTime |
RiseTime / SetTime / DownTime / CulminationTime |
RiseTime / SetTime / DownTime / CulminationTime |
RiseTime / SetTime / DownTime / CulminationTime |
RiseTime / SetTime / DownTime / CulminationTime |
RiseTime / SetTime / DownTime / CulminationTime |
RiseTime / SetTime / DownTime / CulminationTime |
| Physical ephemeris | Physical / PhysicalN |
Physical / PhysicalN |
Physical / PhysicalN |
Physical / PhysicalN / CentralMeridians / CentralMeridiansN |
Physical / PhysicalN / PhysicalSystemIII / Ring |
Physical / PhysicalN / PhysicalSystemIII |
Physical / PhysicalN |
| Conjunction | LastConjunction / NextConjunction |
LastConjunction / NextConjunction |
LastConjunction / NextConjunction |
LastConjunction / NextConjunction |
LastConjunction / NextConjunction |
LastConjunction / NextConjunction |
LastConjunction / NextConjunction |
| Superior / inferior conjunction | LastSuperiorConjunction / NextSuperiorConjunction / LastInferiorConjunction / NextInferiorConjunction |
LastSuperiorConjunction / NextSuperiorConjunction / LastInferiorConjunction / NextInferiorConjunction |
— | — | — | — | — |
| Station | LastProgradeToRetrograde / NextProgradeToRetrograde / LastRetrogradeToPrograde / NextRetrogradeToPrograde, plus LastRetrograde / NextRetrograde |
LastProgradeToRetrograde / NextProgradeToRetrograde / LastRetrogradeToPrograde / NextRetrogradeToPrograde, plus LastRetrograde / NextRetrograde |
LastProgradeToRetrograde / NextProgradeToRetrograde / LastRetrogradeToPrograde / NextRetrogradeToPrograde |
LastProgradeToRetrograde / NextProgradeToRetrograde / LastRetrogradeToPrograde / NextRetrogradeToPrograde |
LastProgradeToRetrograde / NextProgradeToRetrograde / LastRetrogradeToPrograde / NextRetrogradeToPrograde |
LastProgradeToRetrograde / NextProgradeToRetrograde / LastRetrogradeToPrograde / NextRetrogradeToPrograde |
LastProgradeToRetrograde / NextProgradeToRetrograde / LastRetrogradeToPrograde / NextRetrogradeToPrograde |
| Opposition | — | — | LastOpposition / NextOpposition |
LastOpposition / NextOpposition |
LastOpposition / NextOpposition |
LastOpposition / NextOpposition |
LastOpposition / NextOpposition |
| Quadrature | — | — | LastEasternQuadrature / NextEasternQuadrature / LastWesternQuadrature / NextWesternQuadrature |
LastEasternQuadrature / NextEasternQuadrature / LastWesternQuadrature / NextWesternQuadrature |
LastEasternQuadrature / NextEasternQuadrature / LastWesternQuadrature / NextWesternQuadrature |
LastEasternQuadrature / NextEasternQuadrature / LastWesternQuadrature / NextWesternQuadrature |
LastEasternQuadrature / NextEasternQuadrature / LastWesternQuadrature / NextWesternQuadrature |
| Greatest elongation | LastGreatestElongation / NextGreatestElongation / LastGreatestElongationEast / NextGreatestElongationEast / LastGreatestElongationWest / NextGreatestElongationWest |
LastGreatestElongation / NextGreatestElongation / LastGreatestElongationEast / NextGreatestElongationEast / LastGreatestElongationWest / NextGreatestElongationWest |
— | — | — | — | — |
| Geocentric transit | LastTransit / NextTransit / ClosestTransit |
LastTransit / NextTransit / ClosestTransit |
— | — | — | — | — |
| Galilean satellites | — | — | — | Satellites / SatellitePhenomena / LastGalileanPhenomenonEvent / NextGalileanPhenomenonEvent / ClosestGalileanPhenomenonEvent / LastGalileanPhenomenonContactEvent / NextGalileanPhenomenonContactEvent / ClosestGalileanPhenomenonContactEvent |
— | — | — |
| Result types | PhysicalInfo / TransitInfo |
PhysicalInfo / TransitInfo |
PhysicalInfo |
PhysicalInfo / CentralMeridianInfo / GalileanSatellitesInfo / GalileanPhenomenaInfo / GalileanSatellitePosition / GalileanSatellitePhenomenon / GalileanPhenomenonEvent / GalileanPhenomenonContactEvent |
PhysicalInfo / RingInfo |
PhysicalInfo |
PhysicalInfo |
All seven packages spell the truncation family the same way: append N to any instantaneous evaluation function, where n < 0 uses the full built-in series and n >= 0 truncates it.
See the ...N truncation family for details. Event-search families (Last... / Next... / Closest...) have no N variants.
Common capabilities and units
| Capability | Purpose | Unit and convention |
|---|---|---|
ApparentLo / ApparentBo |
Geocentric apparent ecliptic longitude and latitude | degrees; true equinox of date, including light time, aberration, and nutation |
ApparentRa / ApparentDec / ApparentRaDec |
Geocentric apparent right ascension and declination | degrees; true equator of date; ApparentRaDec returns both at once |
ApparentMagnitude |
Apparent visual magnitude | magnitudes (dimensionless) |
Altitude / Azimuth / Zenith / HourAngle |
Topocentric horizontal coordinates | degrees; azimuth runs from north toward east, and Zenith equals 90 - Altitude |
RiseTime / SetTime / DownTime |
Rise and set within the local civil day | time.Time keeping the input time zone; DownTime is a compatibility alias for SetTime |
CulminationTime |
Upper culmination instant | time.Time keeping the input time zone |
ParallacticAngle |
Parallactic angle (zenith direction angle) | degrees |
Diameter / Semidiameter |
Geocentric apparent diameter and semidiameter | arcseconds |
PhaseAngle |
Sun-planet-Earth angle | degrees |
IlluminatedFraction / Phase |
Illuminated fraction | 0-1; Phase is an alias for IlluminatedFraction |
BrightLimbPositionAngle |
Position angle of the bright-limb center | degrees |
EarthDistance / SunDistance |
Earth distance and Sun distance | AU |
AscendingNode / DescendingNode |
Ecliptic longitude of the orbital plane's intersections with the ecliptic | degrees; the two differ by about 180° at the same instant |
Physical |
Disk orientation, sub-Earth/sub-Solar coordinates, north-pole position angle | degrees; the positive longitude direction follows each body's IAU convention |
planet.WherePlanet / planet.WherePlanetN |
VSOP87 longitude, latitude, and heliocentric distance | degrees / AU; out-of-range input returns NaN instead of panicking |
The ...N truncation family
Every instantaneous evaluation function has an ...N variant that trades accuracy for cost: n < 0 uses the full built-in series and is equivalent to the plain function, while n >= 0 keeps roughly n principal terms and scales the higher orders proportionally.
Event-search families (Last... / Next... / Closest...) have no N variant.
Functions with an N variant include ApparentLoN, ApparentBoN, ApparentRaN, ApparentDecN, ApparentRaDecN, ApparentMagnitudeN, EarthDistanceN, SunDistanceN, AltitudeN, AzimuthN, ZenithN, HourAngleN, CulminationTimeN, RiseTimeN, SetTimeN, DownTimeN, ParallacticAngleN, DiameterN, SemidiameterN, PhaseAngleN, PhaseN, IlluminatedFractionN, BrightLimbPositionAngleN, AscendingNodeN, DescendingNodeN, and PhysicalN, plus CentralMeridiansN for Jupiter, RingN and PhysicalSystemIIIN for Saturn, and PhysicalSystemIIIN for Uranus.
fmt.Println(mars.ApparentLo(date), mars.ApparentLoN(date, 8)) // ecliptic longitude: full series / truncated to about 8 terms
fmt.Println(mars.SunDistance(date), mars.SunDistanceN(date, 8)) // heliocentric distance, AU
Usage examples
Which planet can I see tonight?
fmt.Println(venus.RiseTime(date, lon, lat, height, true)) // Venus rises today
fmt.Println(jupiter.CulminationTime(date, lon)) // Jupiter's upper culmination
fmt.Println(mars.Altitude(date, lon, lat), mars.Azimuth(date, lon, lat)) // Mars's altitude and azimuth now
2020-01-01 10:02:34.350145161 +0800 CST <nil>
2020-01-01 12:32:17.585815787 +0800 CST
31.194578177219057 152.07031660415714
Above the horizon means Altitude greater than 0, and azimuth increases from due north towards the east; aero = true lowers the geometric horizon to about -0.5667° for standard refraction.
Per-parameter conventions and the polar sentinel errors are in Rise, set and culmination.
Oppositions, conjunctions, elongations, stations and retrogrades
fmt.Println(mars.NextOpposition(date)) // Mars's next opposition
fmt.Println(jupiter.NextConjunction(date)) // Jupiter's next conjunction
fmt.Println(saturn.NextProgradeToRetrograde(date)) // Saturn's next prograde-to-retrograde station
2020-10-14 07:25:50.441412627 +0800 CST
2021-01-29 09:39:33.697994649 +0800 CST
2020-05-11 17:26:53.961271941 +0800 CST
Event searches return the nearest event at or after the input instant and keep its time zone; the paired Last... functions and the direction-agnostic NextRetrograde are in Conjunctions, oppositions, stations and quadratures;
Mercury's and Venus's NextGreatestElongationEast / ...West are in Greatest elongation and geocentric transits.
Mercury and Venus transits
transit := mercury.NextTransit(date) // next geocentric Mercury transit after 2020
fmt.Println(transit.Valid, transit.Start, transit.Greatest) // whether one was found, first contact, greatest transit
fmt.Println(transit.Duration, transit.MinimumSeparationArcsec) // duration and minimum separation at greatest transit
true 2032-11-13 14:41:13.161198198 +0800 CST 2032-11-13 16:54:12.821315824 +0800 CST
4h26m2.695272267s 572.0643215495325
TransitInfo.Valid false means no transit inside the search window and every other field is the zero value; a transit is a geocentric geometry test and does not check whether the Sun is above the horizon at a given site.
The four contacts, partial transits and the internal-contact fields are in Greatest elongation and geocentric transits.
Phase, diameter, magnitude and nodes
fmt.Println(venus.PhaseAngle(date), venus.Phase(date)) // phase angle (degrees) and illuminated fraction
fmt.Println(venus.Diameter(date), venus.ApparentMagnitude(date)) // apparent diameter (arcseconds) and magnitude
fmt.Println(mars.AscendingNode(date), mars.DescendingNode(date)) // ascending/descending node longitudes (degrees)
49.98145049145023 0.8215177914415865
13.059409604614839 -4
49.71479005849112 229.71479005849113
Phase is an alias of IlluminatedFraction and runs from 0 to 1; the two nodes are about 180° apart at any instant.
Definitions, aliases and the truncated versions are in Nodes, phase, magnitude, diameter and parallactic angle.
Physical ephemerides and the Galilean satellites
j := jupiter.Physical(date) // Jupiter's physical ephemeris
fmt.Println(j.DS, j.DE, j.CentralMeridianSystemIII) // sub-solar/sub-Earth latitude and System III central meridian
sats := jupiter.Satellites(date) // instantaneous positions of the four Galilean satellites
fmt.Println(sats.Io.OffsetXJupiterR, sats.Io.InFrontOfJupiter) // Io's offset and whether it is in front of the disk
-56.55778470155335 -2.039966127259664 311.37430665615585
3.8223302102343975 false
Saturn's rings have their own saturn.Ring (EarthLatitude, MinorAxis, and so on; angles in degrees and axes in arcseconds). Disk orientation and the central meridians are covered in Physical ephemerides; the Galilean-satellite public entry points are in the jupiter package, while JupiterGalilean* in basic is the low-level entry that takes a Julian day, see Galilean satellites of Jupiter.
Comparison conventions
fmt.Println(mars.ApparentLo(date), mars.ApparentLoN(date, 8)) // apparent longitude with every term / truncated to about 8
_, err := mars.RiseTime(date, 0, 89, 0, true) // an observing site in the polar region
fmt.Println(errors.Is(err, mars.ERR_MARS_NEVER_RISE), errors.Is(err, mars.ERR_MARS_NEVER_SET))
238.38840227925655 238.39637464888327
true false
ApparentLo and friends are geocentric apparent places referred to the true equinox of date; bring external J2000 or mean places to the same convention with coord.Precess before comparing.
In the truncation family n < 0 uses every built-in term and n >= 0 truncates.
The convention gap between the Galilean contact events and JPL Horizons / IMCCE tables is documented under External baselines, and the overall boundaries under Parameter and result conventions.
Basic examples
The two examples below are the smallest runnable programs and use date = 2020-01-01 08:08:08 CST with the Xi'an coordinates.
Inner planets
package main
import (
"fmt"
"time"
"b612.me/astro/mercury"
"b612.me/astro/venus"
)
func main() {
// Xi'an, China. Longitude east and latitude north are positive; elevation is 0 m.
var lon, lat, height float64 = 108.93, 34.27, 0
cst := time.FixedZone("CST", 8*3600)
// Instant of observation.
date := time.Date(2020, 1, 1, 8, 8, 8, 8, cst)
// Previous inferior conjunction of Mercury.
fmt.Println(mercury.LastInferiorConjunction(date))
// Next superior conjunction of Venus.
fmt.Println(venus.NextSuperiorConjunction(date))
// Previous Mercury station from prograde to retrograde.
fmt.Println(mercury.LastProgradeToRetrograde(date))
// Next Venus station from retrograde to prograde.
fmt.Println(venus.NextRetrogradeToPrograde(date))
// Previous greatest eastern elongation of Mercury.
fmt.Println(mercury.LastGreatestElongationEast(date))
// Next greatest western elongation of Venus.
fmt.Println(venus.NextGreatestElongationWest(date))
// Venus rise and set times in Xi'an.
fmt.Println(venus.RiseTime(date, lon, lat, height, true))
fmt.Println(venus.SetTime(date, lon, lat, height, true))
// Current apparent magnitude of Venus.
fmt.Println(venus.ApparentMagnitude(date))
// Venus phase angle, illuminated fraction, and bright-limb position angle.
fmt.Println(venus.PhaseAngle(date))
fmt.Println(venus.Phase(date))
fmt.Println(venus.BrightLimbPositionAngle(date))
// Earth-Venus distance.
fmt.Println(venus.EarthDistance(date))
// Sun-Venus distance.
fmt.Println(venus.SunDistance(date))
}
Output:
2019-11-11 23:21:41.971051096 +0800 CST // previous inferior conjunction of Mercury
2021-03-26 14:57:42.052354216 +0800 CST // next superior conjunction of Venus
2019-11-01 04:31:49.749019145 +0800 CST // previous Mercury station from prograde to retrograde
2020-06-25 02:07:41.599749326 +0800 CST // next Venus station from retrograde to prograde
2019-10-20 12:01:37.740152478 +0800 CST // previous greatest eastern elongation of Mercury
2020-08-13 08:14:46.304587125 +0800 CST // next greatest western elongation of Venus
2020-01-01 10:02:34.172435402 +0800 CST <nil> // Venus rise time in Xi'an; no error
2020-01-01 20:25:37.36411482 +0800 CST <nil> // Venus set time in Xi'an; no error
-4 // Venus apparent magnitude
49.98145049145023 // Venus phase angle, degrees
0.8215177914415865 // illuminated fraction of Venus
255.63802053541346 // bright-limb position angle of Venus, degrees
1.2778819631550336 // Earth-Venus distance, AU
0.7262651056423838 // Sun-Venus distance, AU
Inner and outer planets also expose Diameter / Semidiameter and N variants, returning geocentric apparent diameter/semidiameter in arcseconds.
Planet apparent diameter and orbital nodes can be queried directly:
fmt.Println(mars.Diameter(date), mars.Semidiameter(date)) // Martian apparent diameter and semidiameter, arcseconds
fmt.Println(venus.AscendingNode(date), venus.DescendingNode(date)) // Venus ascending-node and descending-node ecliptic longitudes, degrees
Ascending node / descending node here means the two intersections of the body's orbital plane with the ecliptic:
AscendingNode: ecliptic longitude where the body crosses from south of the ecliptic to north of itDescendingNode: ecliptic longitude where the body crosses from north of the ecliptic to south of it- return values are degrees; for the same instant, descending node is usually about
180°from ascending node
For date := 2020-01-01 08:08:08 CST, the output is:
4.287299886569956 2.143649943284978 // Mars apparent diameter and semidiameter, arcseconds
76.86008484515058 256.8600848451506 // Venus ascending-node and descending-node longitudes, degrees
Mercury and Venus also expose NextTransit / LastTransit / ClosestTransit for geocentric planetary transits. "Geocentric" means the planet disk crosses the solar disk as seen from Earth's center; it does not test whether the Sun is above the horizon at a particular observing site. For observing plans, combine this with local solar altitude and weather.
package main
import (
"fmt"
"time"
"b612.me/astro/mercury"
"b612.me/astro/venus"
)
func main() {
// Next geocentric Mercury transit after the beginning of 2019.
mercuryTransit := mercury.NextTransit(time.Date(2019, 1, 1, 0, 0, 0, 0, time.UTC))
fmt.Println(mercuryTransit.Valid)
fmt.Println(mercuryTransit.Start)
fmt.Println(mercuryTransit.InternalStart)
fmt.Println(mercuryTransit.Greatest)
fmt.Println(mercuryTransit.InternalEnd)
fmt.Println(mercuryTransit.End)
fmt.Println(mercuryTransit.Duration)
fmt.Println(mercuryTransit.MinimumSeparationArcsec)
fmt.Println(mercuryTransit.SunSemidiameterArcsec)
fmt.Println(mercuryTransit.PlanetSemidiameterArcsec)
// Next geocentric Venus transit after the beginning of 2012.
venusTransit := venus.NextTransit(time.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC))
fmt.Println(venusTransit.Valid)
fmt.Println(venusTransit.Start)
fmt.Println(venusTransit.InternalStart)
fmt.Println(venusTransit.Greatest)
fmt.Println(venusTransit.InternalEnd)
fmt.Println(venusTransit.End)
fmt.Println(venusTransit.Duration)
}
Output:
true // a valid geocentric Mercury transit was found
2019-11-11 12:35:31.567597389 +0000 UTC // first contact: Mercury externally enters the solar disk
2019-11-11 12:37:12.817581295 +0000 UTC // second contact: Mercury is fully inside the solar disk
2019-11-11 15:19:48.36056292 +0000 UTC // greatest transit: Mercury center is closest to the Sun center
2019-11-11 18:02:29.176982045 +0000 UTC // third contact: Mercury starts leaving the solar disk
2019-11-11 18:04:10.637948513 +0000 UTC // fourth contact: Mercury externally leaves the solar disk
5h28m39.070351124s // geocentric transit duration from first to fourth contact
75.92400059923187 // minimum Mercury-Sun center separation at greatest transit, arcseconds
968.8881519533047 // solar semidiameter at greatest transit, arcseconds
4.978442871670873 // Mercury semidiameter at greatest transit, arcseconds
true // a valid geocentric Venus transit was found
2012-06-05 22:09:47.466886639 +0000 UTC // first contact: Venus externally enters the solar disk
2012-06-05 22:27:35.865356326 +0000 UTC // second contact: Venus is fully inside the solar disk
2012-06-06 01:29:35.572371482 +0000 UTC // greatest transit: Venus center is closest to the Sun center
2012-06-06 04:31:35.068444311 +0000 UTC // third contact: Venus starts leaving the solar disk
2012-06-06 04:49:23.25597167 +0000 UTC // fourth contact: Venus externally leaves the solar disk
6h39m35.789085031s // geocentric transit duration from first to fourth contact
Outer planets
package main
import (
"fmt"
"time"
"b612.me/astro/jupiter"
"b612.me/astro/mars"
"b612.me/astro/neptune"
"b612.me/astro/saturn"
"b612.me/astro/uranus"
)
func main() {
// Xi'an, China. Longitude east and latitude north are positive; elevation is 0 m.
var lon, lat, height float64 = 108.93, 34.27, 0
cst := time.FixedZone("CST", 8*3600)
// Instant of observation.
date := time.Date(2020, 1, 1, 8, 8, 8, 8, cst)
// Next opposition of Mars.
fmt.Println(mars.NextOpposition(date))
// Next conjunction of Jupiter.
fmt.Println(jupiter.NextConjunction(date))
// Previous Saturn station from prograde to retrograde.
fmt.Println(saturn.LastProgradeToRetrograde(date))
// Saturn ring observing parameters.
ring := saturn.Ring(date)
fmt.Printf("saturn B=%.6f Bp=%.6f P=%.6f dU=%.6f major=%.6f minor=%.6f\n",
ring.EarthLatitude,
ring.SunLatitude,
ring.PositionAngle,
ring.DeltaU,
ring.MajorAxis,
ring.MinorAxis,
)
// Next Uranus station from retrograde to prograde.
fmt.Println(uranus.NextRetrogradeToPrograde(date))
// Previous eastern quadrature of Neptune.
fmt.Println(neptune.LastEasternQuadrature(date))
// Next western quadrature of Mars.
fmt.Println(mars.NextWesternQuadrature(date))
// Mars rise and set times in Xi'an.
fmt.Println(mars.RiseTime(date, lon, lat, height, true))
fmt.Println(mars.SetTime(date, lon, lat, height, true))
// Current apparent magnitude of Mars.
fmt.Println(mars.ApparentMagnitude(date))
// Earth-Mars distance.
fmt.Println(mars.EarthDistance(date))
// Sun-Mars distance.
fmt.Println(mars.SunDistance(date))
}
Output:
2020-10-14 07:25:50.441412627 +0800 CST // next opposition of Mars
2021-01-29 09:39:33.697994649 +0800 CST // next conjunction of Jupiter
2019-04-30 10:28:00.187439918 +0800 CST // previous Saturn station from prograde to retrograde
saturn B=23.577025 Bp=23.266930 P=6.629811 dU=1.171016 major=34.133852 minor=13.652911 // Saturn ring B, B', P, dU, major axis, minor axis
2020-01-11 15:23:23.360308706 +0800 CST // next Uranus station from retrograde to prograde
2019-12-08 17:00:15.517960488 +0800 CST // previous eastern quadrature of Neptune
2020-06-07 03:11:00.026179254 +0800 CST // next western quadrature of Mars
2020-01-01 04:41:29.621566236 +0800 CST <nil> // Mars rise time in Xi'an; no error
2020-01-01 14:55:32.963508367 +0800 CST <nil> // Mars set time in Xi'an; no error
1.57 // Mars apparent magnitude
2.1844284956325937 // Earth-Mars distance, AU
1.5897860004265403 // Sun-Mars distance, AU
saturn.Ring returns RingInfo: EarthLatitude is ring opening angle B, SunLatitude is B', PositionAngle is the position angle of the northern semiminor axis, DeltaU is the Saturnicentric longitude difference between the Sun and Earth in the ring plane, and MajorAxis / MinorAxis are the apparent outer major/minor axes in arcseconds.
Topic examples
The snippets below are grouped by topic and all build on the shared variables date, lon, lat, and height; complete runnable versions are in the basic examples above.
Position and coordinates
ApparentLo / ApparentBo / ApparentRa / ApparentDec / ApparentRaDec return a geocentric apparent place: the geometric geocentric position corrected for light time, aberration, and nutation, then converted to the true equator and equinox of date.
These packages do not provide J2000 or mean-place output; for a J2000 frame, use coord.Precess for precession and coord.Nutation2000B for nutation, and use coord.TopocentricEquatorial and coord.EquatorialToHorizontal for topocentric quantities. See Coordinate Tools.
// Apparent place of date: ecliptic and equatorial coordinates, degrees.
lo, bo := venus.ApparentLo(date), venus.ApparentBo(date)
ra, dec := venus.ApparentRaDec(date)
fmt.Println(lo, bo, venus.ApparentRa(date), venus.ApparentDec(date), ra, dec)
// Earth distance and Sun distance, AU.
fmt.Println(venus.EarthDistance(date), venus.SunDistance(date))
Rise, set and culmination
RiseTime / SetTime / DownTime work on the local civil day only: date selects the local date and the output time zone (when the local hour is greater than 12 it is first shifted back by 12 hours), height is the ellipsoidal height in meters, and aero == true adds standard atmospheric refraction (lowering the geometric horizon to about -0.5667°).
Polar day, polar night, or a day with no crossing returns a sentinel error instead of an instant. CulminationTime gives upper culmination; Altitude / Azimuth / Zenith / HourAngle / ParallacticAngle form the topocentric family, with geometry under Coordinate Tools.
// Rise, set, and culmination on the local civil day in Xi'an; aero=true adds refraction.
rise, err := mars.RiseTime(date, lon, lat, height, true)
set, err := mars.SetTime(date, lon, lat, height, true)
fmt.Println(rise, set, err)
fmt.Println(mars.CulminationTime(date, lon))
// Topocentric horizontal quantities: east-positive longitude, north-positive latitude, degrees.
fmt.Println(mars.Altitude(date, lon, lat), mars.Azimuth(date, lon, lat))
fmt.Println(mars.Zenith(date, lon, lat), mars.HourAngle(date, lon))
fmt.Println(mars.ParallacticAngle(date, lon, lat))
// DownTime is a compatibility alias for SetTime; the N variant evaluates a truncated series.
set, err := mars.DownTime(date, lon, lat, height, true)
fmt.Println(set, err)
fmt.Println(mars.CulminationTimeN(date, lon, 12))
Conjunctions, oppositions, stations and quadratures
Event searches always return the nearest event at or before/after the input instant (endpoints included), in the input time zone. The inner planets use LastConjunction / NextConjunction plus the superior/inferior conjunction family; the outer planets use LastConjunction / NextConjunction, LastOpposition / NextOpposition, and the eastern/western quadrature family.
Stations come in two directions: LastProgradeToRetrograde / NextProgradeToRetrograde (prograde to retrograde) and LastRetrogradeToPrograde / NextRetrogradeToPrograde (retrograde to prograde); Mercury and Venus additionally have LastRetrograde / NextRetrograde, which ignore the direction, and the outer planets do not have those two names.
For the inner planets a conjunction is simply "on the same side as the Sun"; the outer planets additionally split opposition and quadrature: only the five planets outside Earth's orbit can reach opposition (Sun-Earth-planet in a line) or eastern/western quadrature (about 90° of ecliptic longitude from the Sun).
Mercury and Venus stay inside Earth's orbit, so those two families exist only in the outer-planet packages.
// Inner planets: superior/inferior conjunction, and direction-agnostic stations.
fmt.Println(mercury.LastSuperiorConjunction(date), mercury.NextInferiorConjunction(date))
fmt.Println(mercury.LastRetrograde(date), mercury.NextRetrograde(date))
// Outer planets: conjunction, opposition, and eastern/western quadrature.
fmt.Println(jupiter.NextConjunction(date), mars.NextOpposition(date))
fmt.Println(mars.NextEasternQuadrature(date), neptune.LastWesternQuadrature(date))
// Both station directions have Last/Next forms.
fmt.Println(saturn.LastProgradeToRetrograde(date), saturn.NextProgradeToRetrograde(date))
fmt.Println(saturn.LastRetrogradeToPrograde(date), saturn.NextRetrogradeToPrograde(date))
Greatest elongation and geocentric transits
Greatest elongation only makes sense for Mercury and Venus: LastGreatestElongation / NextGreatestElongation ignore the side, while LastGreatestElongationEast / NextGreatestElongationEast and the ...West forms distinguish it.
The public entry points for geocentric transits are likewise only in mercury / venus: LastTransit / NextTransit / ClosestTransit return a TransitInfo.
Valid == false means no transit inside the search window and every other field is a zero value; a partial transit has no internal contacts, so HasInternal is false and InternalStart / InternalEnd are zero.
A transit is a purely geocentric geometry test and does not check whether the Sun is above the horizon at a given site.
// Greatest elongation: use ...East / ...West to pick a side, or the plain form for either.
fmt.Println(mercury.NextGreatestElongationEast(date), venus.LastGreatestElongationWest(date))
fmt.Println(venus.NextGreatestElongation(date))
// Geocentric transit: when Valid is false every other field is a zero value.
transit := mercury.NextTransit(date)
if transit.Valid {
fmt.Println(transit.Start, transit.InternalStart, transit.Greatest, transit.InternalEnd, transit.End)
fmt.Println(transit.Duration, transit.MinimumSeparationArcsec, transit.SunSemidiameterArcsec)
}
// Remaining transit fields; InternalDuration is 0 when there are no internal contacts.
transit := venus.ClosestTransit(date)
fmt.Println(transit.HasInternal, transit.InternalDuration, transit.MinimumSeparationArcsec)
fmt.Println(transit.SunSemidiameterArcsec, transit.PlanetSemidiameterArcsec)
Nodes, phase, magnitude, diameter and parallactic angle
AscendingNode / DescendingNode are the ecliptic longitudes of the two intersections of the planet's orbital plane with the ecliptic, in degrees, about 180° apart at the same instant.
PhaseAngle is the Sun-planet-Earth angle in degrees; IlluminatedFraction (alias Phase) is the illuminated fraction from 0 to 1; BrightLimbPositionAngle is the position angle of the bright-limb center in degrees.
Diameter / Semidiameter return the geocentric apparent diameter and semidiameter in arcseconds. ParallacticAngle returns the topocentric parallactic angle (zenith direction angle) in degrees; topocentric coordinates are under Coordinate Tools.
fmt.Println(mars.AscendingNode(date), mars.DescendingNode(date)) // node longitudes, degrees
fmt.Println(mars.PhaseAngle(date), mars.IlluminatedFraction(date), mars.Phase(date)) // phase angle in degrees; illuminated fraction
fmt.Println(mars.ApparentMagnitude(date), mars.BrightLimbPositionAngle(date)) // apparent magnitude; bright-limb position angle
fmt.Println(mars.Diameter(date), mars.Semidiameter(date)) // apparent diameter and semidiameter, arcseconds
fmt.Println(mars.ParallacticAngle(date, lon, lat)) // parallactic angle, degrees
// Nodes and apparent diameter also have truncated variants.
fmt.Println(mars.AscendingNodeN(date, 12), mars.DescendingNodeN(date, 12))
fmt.Println(mars.DiameterN(date, 12), mars.SemidiameterN(date, 12))
Division of labour with other manuals
- Sidereal time, precession and nutation, and topocentric/horizontal conversion are in Coordinate Tools.
- Sun and Moon positions, phases, rise/set, and syzygies are in the Sun and Moon manual.
- Planetary occultations, occultation bands, and lunar-disk charts are in Lunar Occultations.
- Asteroids, comets, and other bodies computed from orbital elements are in Small-body orbits.
- Time-scale declarations, UT1 conventions, and GeoJSON output are in Event Maps and GeoJSON; the scale convention itself is in Time Scale Declaration.
- The authoritative capability list, dependency matrix, and accuracy summary are in the root README.
Physical ephemerides
All seven major planets provide Physical / PhysicalN for disk orientation, sub-Earth/sub-Sun coordinates, and north-pole position angle. Jupiter additionally exposes System I/II/III central meridians, and Saturn exposes ring parameters.
package main
import (
"fmt"
"time"
"b612.me/astro/jupiter"
"b612.me/astro/saturn"
)
func main() {
date := time.Date(2025, 11, 1, 0, 0, 0, 0, time.UTC)
// Jupiter: DS and DE are planetocentric declinations of the Sun and Earth relative to Jupiter's equator.
// CMI/CMII/CMIII are Jupiter System I/II/III central meridians, degrees.
j := jupiter.Physical(date)
fmt.Printf("jupiter DS=%.6f DE=%.6f CMI=%.6f CMII=%.6f CMIII=%.6f\n",
j.DS,
j.DE,
j.CentralMeridianSystemI,
j.CentralMeridianSystemII,
j.CentralMeridianSystemIII,
)
// Saturn ring: B/B' are ring-plane latitudes seen from Earth and Sun; P is the position angle of the ring minor axis.
ring := saturn.Ring(date)
fmt.Printf("saturn B=%.6f Bp=%.6f P=%.6f major=%.6f minor=%.6f\n",
ring.EarthLatitude,
ring.SunLatitude,
ring.PositionAngle,
ring.MajorAxis,
ring.MinorAxis,
)
}
Output:
jupiter DS=54.342153 DE=1.436485 CMI=292.712909 CMII=276.309048 CMIII=147.241811 // Jupiter DS/DE and System I/II/III central meridians, degrees
saturn B=-0.608048 Bp=-2.675677 P=4.480276 major=42.709920 minor=0.453248 // Saturn ring B, B', minor-axis position angle, outer major/minor axes
If only Jupiter central meridians are needed:
cm := jupiter.CentralMeridians(date)
fmt.Printf("CMI=%.6f CMII=%.6f CMIII=%.6f\n", cm.SystemI, cm.SystemII, cm.SystemIII) // Jupiter System I/II/III central meridians
Saturn and Uranus also retain explicit System III semantic aliases:
sat3 := saturn.PhysicalSystemIII(date)
ura3 := uranus.PhysicalSystemIII(date)
fmt.Printf("saturn systemIII lon=%.6f lat=%.6f P=%.6f\n", sat3.SubEarthLongitude, sat3.SubEarthLatitude, sat3.NorthPolePositionAngle) // Saturn sub-Earth longitude/latitude and north-pole position angle
fmt.Printf("uranus systemIII lon=%.6f lat=%.6f P=%.6f\n", ura3.SubEarthLongitude, ura3.SubEarthLatitude, ura3.NorthPolePositionAngle) // Uranus sub-Earth longitude/latitude and north-pole position angle
All seven packages return their own PhysicalInfo, whose fields mirror basic.PlanetPhysicalInfo one for one.
The positive direction of SubEarthLongitude / SubSolarLongitude follows each body's current IAU/Horizons cartographic convention: Mercury, Mars, Jupiter, Saturn, and Neptune use west-positive longitudes, while Venus and Uranus use east-positive longitudes.
Saturn-ring parameters describe only the disk and band; they take no part in occultation contact geometry, and charts are in Lunar Occultations.
p := uranus.Physical(date) // Uranus sub-Earth/sub-Solar coordinates and north-pole position angle, degrees
fmt.Println(p.SubEarthLongitude, p.SubEarthLatitude, p.SubSolarLongitude, p.SubSolarLatitude, p.NorthPolePositionAngle)
// Truncated variants of the Saturn ring and the Jupiter central meridians.
fmt.Println(saturn.RingN(date, 12).MinorAxis, jupiter.CentralMeridiansN(date, 12).SystemIII)
Galilean satellites of Jupiter
The public entry points are in the jupiter package (jupiter.Satellites, jupiter.SatellitePhenomena, jupiter.NextGalileanPhenomenonEvent, and so on); they take a time.Time and return Jupiter's own types.
The JupiterGalilean* functions in basic (such as basic.JupiterGalileanSatelliteObservations and basic.NextJupiterGalileanPhenomenonEvent) are the low-level entries of the same implementation: they take a Julian day and return basic types.
Applications should use the jupiter layer.
// Entry point is in the jupiter package; satellite numbers use jupiter.GalileanSatelliteIo and friends.
sats := jupiter.Satellites(date)
fmt.Println(sats.Io.OffsetXJupiterR, sats.Io.OffsetYJupiterR, sats.Io.InFrontOfJupiter)
Satellite numbers and phenomenon types have named constants, so there is no need to write raw numbers or strings:
- Satellite numbers:
GalileanSatelliteIo,GalileanSatelliteEuropa,GalileanSatelliteGanymede,GalileanSatelliteCallisto - Phenomenon types (
GalileanPhenomenonType):GalileanPhenomenonTransit,GalileanPhenomenonOccultation,GalileanPhenomenonEclipse,GalileanPhenomenonShadowTransit - Contact phases (
GalileanPhenomenonContactPhase):GalileanPhenomenonContactDisappearance,GalileanPhenomenonContactReappearance
// Satellite numbers and phenomenon types are constants, so no raw numbers or strings are needed.
event := jupiter.NextGalileanPhenomenonEvent(date, jupiter.GalileanSatelliteCallisto, jupiter.GalileanPhenomenonShadowTransit)
fmt.Println(event.Type == jupiter.GalileanPhenomenonShadowTransit)
The jupiter package provides apparent positions, instantaneous phenomena, and event searches for the four Galilean satellites.
Common entry points:
Satellites: instantaneous apparent positions relative to Jupiter's diskSatellitePhenomena: instantaneous transit, occultation, eclipse, and shadow-transit flagsLastGalileanPhenomenonEvent/NextGalileanPhenomenonEvent/ClosestGalileanPhenomenonEvent: search whole phenomenon intervalsLastGalileanPhenomenonContactEvent/NextGalileanPhenomenonContactEvent/ClosestGalileanPhenomenonContactEvent: search IMCCE-style D/F contact events
Two conventions matter:
GalileanPhenomenonEventtreats the satellite as a point and checks when its center enters or leaves Jupiter's disk. It is suitable for fast phenomenon search and internal state checks.GalileanPhenomenonContactEventincludes the finite disk of the satellite and splits disappearance and reappearance contact windows. It is the better match for IMCCE tables such asTR.D/TR.F/OC.D/OC.F/EC.D/EC.F/SH.D/SH.F.
The two conventions may differ by up to about 7 minutes in duration. This is a definition difference, not a timing-accuracy failure. Use GalileanPhenomenonContactEvent for observing predictions and direct comparison with public almanacs.
Code example
package main
import (
"fmt"
"time"
"b612.me/astro/jupiter"
)
func main() {
date := time.Date(2026, 1, 15, 0, 0, 0, 0, time.UTC)
// Instantaneous positions of the four satellites relative to Jupiter's center.
sats := jupiter.Satellites(date)
fmt.Printf("io x=%.6f y=%.6f front=%v\n", sats.Io.OffsetXJupiterR, sats.Io.OffsetYJupiterR, sats.Io.InFrontOfJupiter)
fmt.Printf("europa ra=%.6f dec=%.6f\n", sats.Europa.ApparentRA, sats.Europa.ApparentDec)
// Instantaneous phenomenon flags.
ph := jupiter.SatellitePhenomena(date)
fmt.Printf("io transit=%v occultation=%v eclipse=%v shadow=%v\n", ph.Io.Transit, ph.Io.Occultation, ph.Io.Eclipse, ph.Io.ShadowTransit)
fmt.Printf("europa transit=%v occultation=%v eclipse=%v shadow=%v\n", ph.Europa.Transit, ph.Europa.Occultation, ph.Europa.Eclipse, ph.Europa.ShadowTransit)
// Next full Io transit event.
event := jupiter.NextGalileanPhenomenonEvent(date, jupiter.GalileanSatelliteIo, jupiter.GalileanPhenomenonTransit)
fmt.Printf("event valid=%v sat=%d type=%s\n", event.Valid, event.Satellite, event.Type)
fmt.Println(event.Start)
fmt.Println(event.Greatest)
fmt.Println(event.End)
fmt.Println(event.Duration)
// Next IMCCE-style contact window for a Europa occultation.
contact := jupiter.NextGalileanPhenomenonContactEvent(date, jupiter.GalileanSatelliteEuropa, jupiter.GalileanPhenomenonOccultation)
fmt.Printf("contact valid=%v sat=%d type=%s\n", contact.Valid, contact.Satellite, contact.Type)
fmt.Println(contact.Disappearance.Start)
fmt.Println(contact.Disappearance.ModelCrossing)
fmt.Println(contact.Disappearance.End)
fmt.Println(contact.Greatest)
fmt.Println(contact.Reappearance.Start)
fmt.Println(contact.Reappearance.ModelCrossing)
fmt.Println(contact.Reappearance.End)
}
Output:
io x=-0.675026 y=-0.032798 front=true // Io X/Y offset from Jupiter center, in Jupiter radii; in front of Jupiter
europa ra=110.769133 dec=22.335828 // Europa apparent RA and Dec, degrees
io transit=true occultation=false eclipse=false shadow=true // Io is transiting, and its shadow is also transiting
europa transit=false occultation=false eclipse=false shadow=false // Europa has no transit, occultation, eclipse, or shadow transit at this instant
event valid=true sat=1 type=transit // next valid event is an Io transit
2026-01-16 16:32:47.552742362 +0000 UTC // Io transit begins
2026-01-16 17:40:44.189371168 +0000 UTC // midpoint of the Io transit
2026-01-16 18:48:40.287077128 +0000 UTC // Io transit ends
2h15m52.734334766s // Io transit duration
contact valid=true sat=2 type=occultation // next valid contact event is a Europa occultation
2026-01-17 01:00:34.99533087 +0000 UTC // Europa occultation disappearance starts
2026-01-17 01:02:31.714070141 +0000 UTC // model center crossing during disappearance
2026-01-17 01:04:28.432809412 +0000 UTC // disappearance ends
2026-01-17 02:27:37.807798683 +0000 UTC // deepest occultation
2026-01-17 03:50:48.120300471 +0000 UTC // reappearance starts
2026-01-17 03:52:43.901527225 +0000 UTC // model center crossing during reappearance
2026-01-17 03:54:39.68275398 +0000 UTC // reappearance ends
External baselines
The Galilean-satellite implementation was checked against two external baselines:
- JPL Horizons: apparent positions of the four satellites relative to Jupiter's center, and shadow-center offsets from Jupiter's disk during shadow transits.
- IMCCE 2026 tables: transits, occultations, Jupiter eclipses, shadow transits, and D/F contact windows.
Comparison results:
Satellitespositions relative to Jupiter center: maximum sample difference against JPL Horizons aboutX=0.054",Y=0.048".SatellitePhenomenashadow-transit shadow-center offsets: maximum sample difference against JPL Horizons aboutX=0.051",Y=0.016"; boolean phenomenon flags match in the samples.GalileanPhenomenonContactEventdiffers from IMCCE 2026 D/F contact times by at most about79 s, and contact durations by about17 sin the compared cases.GalileanPhenomenonEventuses a different definition from IMCCE D/F contacts, so start and end times can differ by about7 min.
Shared types and constants from the planet package
The planet package is the low-level analytic-series entry point, shared by the seven planet packages and by sun / moon.
It exports functions only and no types, so what the planet packages really share is one set of numerical conventions and truncation semantics rather than shared types: each package's PhysicalInfo mirrors basic.PlanetPhysicalInfo and TransitInfo mirrors basic.PlanetTransitResult, field for field, while the types themselves still belong to their own packages.
| Entry point | Purpose | Unit |
|---|---|---|
planet.WherePlanet / planet.WherePlanetN |
VSOP87 result: xt is 1..7 for Mercury through Neptune and -1 or 0 for Earth, zn is 0 longitude, 1 latitude, 2 heliocentric distance; an out-of-range xt / zn returns NaN instead of panicking |
degrees / AU |
planet.Distance |
Sun-Earth distance | AU |
planet.SunLo / planet.SunM / planet.SunMidFun / planet.SunTrueLo / planet.SunApparentLo |
Solar geometric longitude, mean anomaly, equation of center, true longitude, apparent longitude | degrees |
planet.Earthe / planet.EarthPI |
Earth's orbital eccentricity and longitude of perihelion | dimensionless / degrees |
planet.MoonLo / planet.MoonM / planet.MoonLonX / planet.SunMoonAngle |
Lunar mean longitude, mean anomaly, mean argument of latitude, and mean elongation | degrees |
planet.MoonI / planet.MoonB / planet.MoonR |
Periodic longitude, latitude, and distance terms (truncated ELP2000/82-style series) | 10⁻⁶ degrees / 10⁻⁶ degrees / 10⁻³ km |
planet.MoonTrueLo / planet.MoonTrueBo / planet.MoonAway |
Lunar true longitude, true latitude, and Earth distance | degrees / degrees / km |
// xt=1..7 is Mercury..Neptune; zn=0 longitude, 1 latitude, 2 heliocentric distance (AU).
fmt.Println(planet.WherePlanet(4, 2, 2460000.5)) // Jupiter heliocentric distance, AU
fmt.Println(planet.WherePlanetN(4, 2, 2460000.5, 12)) // truncated form, about 12 principal terms
fmt.Println(planet.WherePlanet(8, 0, 2460000.5)) // xt out of range: NaN
// Earth's heliocentric longitude (xt=-1) and a planet's can be compared on the same convention.
fmt.Println(planet.WherePlanet(-1, 0, 2460000.5), planet.WherePlanet(4, 0, 2460000.5))
Parameter and result conventions
The conventions below are shared by all seven packages; per-capability return units are summarised under Common capabilities and units.
Time scale and civil time
Every public API treats its time.Time argument as a civil instant (a UTC label): position and physical functions take date.UTC() and convert to TT internally before evaluating the ephemeris, while rise/set, culmination, and the topocentric horizontal family additionally read date.Zone() for local-time computation.
UTC had no leap seconds before 1972-01-01; the library treats that span as UT1, so a civil-time label there is equal to UT1.
From 1972 on the built-in leap-second table is used, and beyond the exact window the active UTC tracking policy applies. For explicit conversion use astro.UT1FromUTC, astro.TTFromUTC, and astro.DUT1 from the root package; time-scale declarations inside figures and captions and the UT1 convention are in Time Scale Declaration.
Units and conventions
Angles are always in degrees; apparent diameter and semidiameter are in arcseconds; distances follow the function name -- EarthDistance / SunDistance and planet.WherePlanet with zn=2 are in AU, while planet.MoonAway is in km.
PhaseAngle is in degrees, IlluminatedFraction and its alias Phase are 0-1, and ApparentMagnitude is a magnitude (dimensionless); rise/set, culmination, and every event search return time.Time in the input time zone.
Duration fields inside event structs (TransitInfo.Duration, TransitInfo.InternalDuration, GalileanPhenomenonEvent.Duration, GalileanPhenomenonContact.Duration) are Go time.Duration values, not Julian days or day counts; the Start / Greatest / End / InternalStart / InternalEnd fields of TransitInfo keep the caller's time zone.
Geocentric, topocentric, and distance are three different conventions: ApparentLo / ApparentBo / ApparentRa / ApparentDec / ApparentRaDec are geocentric apparent places, Altitude / Azimuth / Zenith / HourAngle / ParallacticAngle are topocentric quantities, and EarthDistance / SunDistance are geometric geocentric distances.
Zero values, out-of-range input and sentinel errors
When an event search finds nothing inside its window it returns zero values or a struct with Valid == false (TransitInfo.Valid, GalileanPhenomenonEvent.Valid, GalileanPhenomenonContactEvent.Valid) instead of an error; when TransitInfo.HasInternal is false, InternalStart / InternalEnd are zero values because a partial transit has no internal contacts.
planet.WherePlanet / planet.WherePlanetN return NaN instead of panicking when xt / zn is out of range; in the ...N truncation family, n < 0 uses the full built-in series and n >= 0 truncates it.
RiseTime / SetTime / DownTime (including their N forms) are the only family that returns an error: when the body has no geometric rise or set on that day they return the sentinel error below with a zero instant.
Each planet package has its own polar-day/polar-night errors.
NEVER_RISE in the name means "never rises that day" (polar night), NEVER_SET means "never sets that day" (polar day), and NEVER_DOWN is a compatibility alias for NEVER_SET.
| Package | Never rises | Never sets | Set alias |
|---|---|---|---|
mercury |
ERR_MERCURY_NEVER_RISE |
ERR_MERCURY_NEVER_SET |
ERR_MERCURY_NEVER_DOWN |
venus |
ERR_VENUS_NEVER_RISE |
ERR_VENUS_NEVER_SET |
ERR_VENUS_NEVER_DOWN |
mars |
ERR_MARS_NEVER_RISE |
ERR_MARS_NEVER_SET |
ERR_MARS_NEVER_DOWN |
jupiter |
ERR_JUPITER_NEVER_RISE |
ERR_JUPITER_NEVER_SET |
ERR_JUPITER_NEVER_DOWN |
saturn |
ERR_SATURN_NEVER_RISE |
ERR_SATURN_NEVER_SET |
ERR_SATURN_NEVER_DOWN |
uranus |
ERR_URANUS_NEVER_RISE |
ERR_URANUS_NEVER_SET |
ERR_URANUS_NEVER_DOWN |
neptune |
ERR_NEPTUNE_NEVER_RISE |
ERR_NEPTUNE_NEVER_SET |
ERR_NEPTUNE_NEVER_DOWN |
// Polar day/night: the rise/set functions return a sentinel error and a zero time.Time.
rise, err := mercury.RiseTime(date, lon, lat, height, true)
switch {
case errors.Is(err, mercury.ERR_MERCURY_NEVER_RISE):
fmt.Println("polar night: never rises that day", rise.IsZero())
case errors.Is(err, mercury.ERR_MERCURY_NEVER_SET):
fmt.Println("polar day: never sets that day", rise.IsZero())
}
Topocentric versus geocentric
Altitude / Azimuth / Zenith / HourAngle / ParallacticAngle use date's time zone for local-time computation, with east-positive longitude, north-positive latitude, and height as the ellipsoidal height in meters (not orthometric elevation).
They are a different convention from the geocentric apparent place of ApparentRa / ApparentDec; convert through Coordinate Tools before mixing them.
Accuracy and scope
The planet packages use the built-in truncated VSOP87 series, covering about 4000 years around J2000; the truncation magnitudes relative to full VSOP87 are in Sun and planets and the overall scope is in Scope And Accuracy.
The ...N forms relax that baseline further and suit batch scans or live front-end refreshes.
saturn.Ring and the physical ephemerides affect only the disk and band rendering: the Saturn ring takes no part in occultation contact geometry and is not drawn as a disk boundary. The planets have no dedicated chart entry point; occultation and Saturn-ring charts are in Lunar Occultations.