Astro::Coord::ECI::Moon - Compute the position of the Moon.


 my $moon = Astro::Coord::ECI::Moon->new ();
 my $sta = Astro::Coord::ECI->
     universal (time ())->
     geodetic ($lat, $long, $alt);
 my ($time, $rise) = $sta->next_elevation ($moon);
 print "Moon @{[$rise ? 'rise' : 'set']} is ",
     scalar localtime $time;


This module implements the position of the Moon as a function of time, as described in Jean Meeus' "Astronomical Algorithms," second edition. It is a subclass of Astro::Coord::ECI, with the id, name, and diameter attributes initialized appropriately, and the time_set() method overridden to compute the position of the Moon at the given time.


The following methods should be considered public:

$moon = Astro::Coord::ECI::Moon->new ();

This method instantiates an object to represent the coordinates of the Moon. This is a subclass of Astro::Coord::ECI, with the id and name attributes set to 'Moon', and the diameter attribute set to 3476 km per Jean Meeus' "Astronomical Algorithms", 2nd Edition, Appendix I, page 407.

Any arguments are passed to the set() method once the object has been instantiated. Yes, you can override the "hard-wired" id and name in this way.

@almanac = $moon->almanac ($location, $start, $end);

This method produces almanac data for the Moon for the given location, between the given start and end times. The location is assumed to be Earth-Fixed - that is, you can't do this for something in orbit.

The start time defaults to the current time setting of the $moon object, and the end time defaults to a day after the start time.

The almanac data consists of a list of list references. Each list reference points to a list containing the following elements:

 [0] => time
 [1] => event (string)
 [2] => detail (integer)
 [3] => description (string)

The @almanac list is returned sorted by time.

The following events, details, and descriptions are at least potentially returned:

 horizon: 0 = Moon set, 1 = Moon rise;
 transit: 1 = Moon transits meridian;
 quarter: 0 = new moon, 1 = first quarter,
          2 = full moon, 3 = last quarter.
($time, $quarter, $desc) = $moon->next_quarter ($want);

This method calculates the time of the next quarter-phase of the Moon after the current time setting of the $moon object. The returns are the time, which quarter-phase it is as a number from 0 (new moon) to 3 (last quarter), and a string describing the phase. If called in scalar context, you just get the time.

The optional $want argument says which phase you want.

As a side effect, the time of the $moon object ends up set to the returned time.

The method of calculation is successive approximation, and actually returns the second after the quarter.

$period = $moon->period ()

This method returns the siderial period of the Moon, per Appendix I (pg 408) of Jean Meeus' "Astronomical Algorithms," 2nd edition.

($phase, $illum) = $moon->phase ($time);

This method calculates the current phase of the moon in radians, and its illuminated fraction as a number from 0 to 1. If the time is omitted, the current time of the $moon object is used.

If called in scalar context, you get the phase.

This can be called as a class method, but if you do this the time must be specified.

Jean Meeus' "Astronomical Algorithms", 2nd Edition, Chapter 49 page 349, defines the phases of the moon in terms of the difference between the geocentric longitudes of the moon and sun - specifically, that new, first quarter, full, and last quarter are the moments when this difference is 0, 90, 180, and 270 degrees respectively.

Not quite above reproach, this module simply defines the phase of the Moon as the difference between these two quantities, even if it is not a multiple of 90 degrees. This is different than the "phase angle" of the Moon, which Meeus defines as the elongation of the Earth from the Sun, as seen from the Moon. Because we take the "phase angle" as just pi - the phase (in radians), we introduce an error of about 0.3% in the illumination calculation.

$moon->time_set ()

This method sets coordinates of the object to the coordinates of the Moon at the object's currently-set universal time. The velocity components are arbitrarily set to 0, since Meeus' algorithm does not provide this information.

Although there's no reason this method can't be called directly, it exists to take advantage of the hook in the Astro::Coord::ECI object, to allow the position of the Moon to be computed when the object's time is set.

The computation comes from Jean Meeus' "Astronomical Algorithms", 2nd Edition, Chapter 47, pages 337ff. Meeus gives the accuracy as 10 seconds of arc in latitude, and 4 seconds of arc in longitude. He credits the algorithm to M. Chalpront-Touze and J. Chalpront, "The Lunar Ephemeris ELP 2000" from Astronomy and Astrophysics volume 124, pp 50-62 (1983), but the formulae for the mean arguments to J. Chalpront, M. Chalpront-Touze, and G. Francou, Introduction dans ELP 2000-82B de nouvelles valeurs des parametres orbitaux de la Lune et du barycentre Terre-Lune, Paris, January 1998.


The author wishes to acknowledge Jean Meeus, whose book "Astronomical Algorithms" (second edition) formed the basis for this module.


The Astro-MoonPhase package by Brett Hamilton, which contains a function-based module to compute the current phase, distance and angular diameter of the Moon, as well as the angular diameter and distance of the Sun.


Thomas R. Wyant, III (wyant at cpan dot org)


Copyright 2005, 2006 by Thomas R. Wyant, III (wyant at cpan dot org). All rights reserved.

This module is free software; you can use it, redistribute it and/or modify it under the same terms as Perl itself. Please see for the current licenses.

This software is provided without any warranty of any kind, express or implied. The author will not be liable for any damages of any sort relating in any way to this software.