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:
| Field | Description |
|---|---|
longitude | Ecliptic longitude (Angle) |
latitude | Ecliptic latitude (Angle, ±5.3°) |
ra | Right Ascension (Angle) |
dec | Declination (Angle) |
distance_km | Distance in kilometers |
angular_diameter | Apparent size (Angle) |
parallax | Horizontal 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:
| Field | Description |
|---|---|
phase_angle | Phase angle (0° = new, 180° = full) |
illumination | Illuminated fraction (0-1) |
percent_illuminated | Percentage (0-100) |
age_days | Days since new moon (0-29.5) |
name | Phase name (string) |
Phase Names
The lunar cycle is divided into eight phases:
| Phase | Age (days) | Illumination |
|---|---|---|
| New Moon | 0 | 0% |
| Waxing Crescent | 1-7 | 0-50% |
| First Quarter | ~7.4 | 50% |
| Waxing Gibbous | 7-15 | 50-100% |
| Full Moon | ~14.8 | 100% |
| Waning Gibbous | 15-22 | 100-50% |
| Last Quarter | ~22.1 | 50% |
| Waning Crescent | 22-29.5 | 50-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:
- Moon is below the horizon
- Moon is far from target (>60°)
- 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
- Sun Module - Solar calculations
- Visibility Module - Observation planning
- Observer Module - Location management