Skip to main content

Moon Module

The Moon module provides calculations for lunar position, phases, rise/set times, and related phenomena. Essential for planning observations and understanding our celestial companion.

Overview​

The Moon's motion is complex—more so than any other celestial body we observe regularly. This module implements algorithms suitable for:

  • Lunar position (RA/Dec, ecliptic coordinates)
  • Moon phase (illumination, age, phase name)
  • Moonrise and moonset times
  • Next occurrence of major phases
  • Angular diameter and parallax

Accuracy: Position ~0.5° (sufficient for rise/set and phase calculations).

Quick Start​

CLI Usage​

# Current lunar position
starward moon position

# Current phase information
starward moon phase

# Moonrise and moonset
starward moon rise --lat 51.5 --lon -0.1
starward moon set --lat 51.5 --lon -0.1

# Next full moon
starward moon next full

# Next new moon
starward moon next new

Python API​

from starward.core.moon import (
moon_position, moon_phase, moon_altitude,
moonrise, moonset, next_phase, MoonPhase
)
from starward.core.observer import Observer
from starward.core.time import jd_now

# Create an observer
greenwich = Observer.from_degrees("Greenwich", 51.4772, -0.0005)

# Get current lunar position
jd = jd_now()
pos = moon_position(jd)
print(f"Moon RA: {pos.ra.hours:.2f}h, Dec: {pos.dec.degrees:.1f}°")
print(f"Distance: {pos.distance_km:.0f} km")

# Current phase
phase = moon_phase(jd)
print(f"Phase: {phase.name}")
print(f"Illumination: {phase.percent_illuminated:.0f}%")
print(f"Age: {phase.age_days:.1f} days")

# Moonrise and moonset
rise = moonrise(greenwich, jd)
if rise:
print(f"Moonrise: {rise.to_datetime()}")

# Next full moon
next_full = next_phase(jd, MoonPhase.FULL_MOON)
print(f"Next full moon: {next_full.to_datetime()}")

Lunar Position​

The moon_position() function returns a MoonPosition object containing:

FieldDescription
longitudeEcliptic longitude (Angle)
latitudeEcliptic latitude (Angle, ±5.3°)
raRight Ascension (Angle)
decDeclination (Angle)
distance_kmDistance in kilometers
angular_diameterApparent size (Angle)
parallaxHorizontal parallax (Angle)

Distance and Size​

The Moon's distance varies from ~356,500 km (perigee) to ~406,700 km (apogee), causing its apparent size to vary:

pos = moon_position(jd)
print(f"Distance: {pos.distance_km:.0f} km")
print(f"Angular diameter: {pos.angular_diameter.arcminutes:.1f} arcmin")
print(f"Parallax: {pos.parallax.degrees:.2f}°")

When the Moon is closer, it appears larger—a "supermoon" occurs when a full moon coincides with perigee.

Moon Phase​

The moon_phase() function returns a MoonPhaseInfo object:

FieldDescription
phase_anglePhase angle (0° = new, 180° = full)
illuminationIlluminated fraction (0-1)
percent_illuminatedPercentage (0-100)
age_daysDays since new moon (0-29.5)
namePhase name (string)

Phase Names​

The lunar cycle is divided into eight phases:

PhaseAge (days)Illumination
New Moon00%
Waxing Crescent1-70-50%
First Quarter~7.450%
Waxing Gibbous7-1550-100%
Full Moon~14.8100%
Waning Gibbous15-22100-50%
Last Quarter~22.150%
Waning Crescent22-29.550-0%
phase = moon_phase(jd)
print(f"Phase: {phase.name}")
print(f"Age: {phase.age_days:.1f} days")
print(f"Illumination: {phase.percent_illuminated:.0f}%")

Finding Next Phases​

Find the next occurrence of a major phase:

from starward.core.moon import next_phase, MoonPhase

jd = jd_now()

# Major phases
next_new = next_phase(jd, MoonPhase.NEW_MOON)
next_first = next_phase(jd, MoonPhase.FIRST_QUARTER)
next_full = next_phase(jd, MoonPhase.FULL_MOON)
next_last = next_phase(jd, MoonPhase.LAST_QUARTER)

print(f"Next new moon: {next_new.to_datetime()}")
print(f"Next full moon: {next_full.to_datetime()}")

Moonrise and Moonset​

Unlike the Sun, the Moon rises and sets at very different times each day (about 50 minutes later each day on average):

rise = moonrise(observer, jd)
set_t = moonset(observer, jd)

if rise and set_t:
print(f"Moonrise: {rise.to_datetime()}")
print(f"Moonset: {set_t.to_datetime()}")

Edge Cases​

  • The Moon may not rise or set on a given day
  • Near full moon, moonrise occurs around sunset
  • Near new moon, moonrise occurs around sunrise

Moon Altitude​

Calculate the Moon's altitude at any time:

alt = moon_altitude(observer, jd)
print(f"Moon altitude: {alt.degrees:.1f}°")

if alt.degrees > 0:
print("Moon is up")

The Synodic Month​

The synodic month (new moon to new moon) averages 29.53 days but varies due to the elliptical orbit:

# Find two consecutive new moons
new1 = next_phase(jd, MoonPhase.NEW_MOON)
new2 = next_phase(JulianDate(new1.jd + 1), MoonPhase.NEW_MOON)

synodic_month = new2.jd - new1.jd
print(f"This synodic month: {synodic_month:.2f} days")

Observation Planning​

Moon-Target Separation​

For deep-sky observations, moonlight can be problematic. Use the visibility module:

from starward.core.visibility import moon_target_separation
from starward.core.coords import ICRSCoord

target = ICRSCoord.from_degrees(83.63, 22.01) # M1 Crab Nebula
sep = moon_target_separation(target, jd)
print(f"Moon separation: {sep.degrees:.1f}°")

if sep.degrees < 30:
print("Moon may affect observations")

Best Observation Windows​

For faint objects, plan observations when:

  1. Moon is below the horizon
  2. Moon is far from target (>60°)
  3. Moon is near new phase

Lunar Libration​

Although not directly computed by this module, the Moon's apparent "wobble" (libration) means we can see about 59% of its surface over time, not just 50%.

Algorithm Details​

This module uses the simplified lunar theory from Jean Meeus' Astronomical Algorithms, incorporating:

  • Mean orbital elements
  • Major perturbations from the Sun
  • Variation in orbital speed
  • Parallax correction

For higher precision (sub-arcminute), consider ELP/MPP02 (not yet implemented).

CLI Reference​

# Position
starward moon position [--jd JD] [--json] [--verbose]

# Phase
starward moon phase [--jd JD] [--json]

# Rise/Set
starward moon rise --lat LAT --lon LON [--jd JD]
starward moon set --lat LAT --lon LON [--jd JD]

# Altitude
starward moon altitude --lat LAT --lon LON [--jd JD]

# Next phase (full|new|first|last)
starward moon next PHASE [--jd JD]

See Also​