2

It seems like pyephem should be able to give me your standard human-type names for where we are in a moon cycle, given a date -- "first quarter," "full," "waxing crescent," "waning gibbous," etc.

Am I right that it does not?

Does anyone know of a standard solution for that?

hanksims
  • 1,479
  • 2
  • 12
  • 22
  • You may try [this](https://stackoverflow.com/a/2526835/2629998) piece of code. –  Nov 02 '14 at 17:29

2 Answers2

6

There is not, alas, any standard definition of a term like “Full Moon” beyond its being the moment when the Moon is completely full. This means that, technically, there is only one exact infinitely small moment when the Moon is completely full, and therefore that any real moment about which you could ask PyEphem will be either before or after that perfect moment of fullness.

So unless you can find a standard definition for how “wide” in seconds the moment of Full Moon is, the actual phase at any given second that you ask about will be either waxing or waning. You can consult the USNO definitions for all the details:

http://aa.usno.navy.mil/faq/docs/moon_phases.php

Since the standards there say that the difference in ecliptic longitude is how you determine the phase, you might try something like this:

import ephem
tau = 2.0 * ephem.pi

sun = ephem.Sun()
moon = ephem.Moon()
names = ['Waxing Crescent', 'Waxing Gibbous',
         'Waning Gibbous', 'Waning Crescent']

for n in range(1, 31):
    s = '2014/%d/11' % n
    sun.compute(s)
    moon.compute(s)

    sunlon = ephem.Ecliptic(sun).lon
    moonlon = ephem.Ecliptic(moon).lon

    angle = (moonlon - sunlon) % tau
    quarter = int(angle * 4.0 // tau)
    print n, names[quarter]
Brandon Rhodes
  • 83,755
  • 16
  • 106
  • 147
  • 1
    Aha, well! Still, that "exact infinitely small moment" -- either for full, new, or quarter moons -- is all I really need, and pyephem does give it to me. The date that the infinitely small moment of fullness occurs is, for my purposes, the date of the full moon. – hanksims Nov 04 '14 at 20:40
5

Here's my quick and dirty solution to my own problem. It assumes observer is in the same timezone as the system timezone, but that's good enough for my purposes.

Still surprised pyephem doesn't have something like/more refined than this, but maybe there's an astronomical reason that I'm not smart enough to understand.

import ephem

def human_moon(observer):
    target_date_utc = observer.date
    target_date_local = ephem.localtime( target_date_utc ).date()
    next_full = ephem.localtime( ephem.next_full_moon(target_date_utc) ).date()
    next_new = ephem.localtime( ephem.next_new_moon(target_date_utc) ).date()
    next_last_quarter = ephem.localtime( ephem.next_last_quarter_moon(target_date_utc) ).date()
    next_first_quarter = ephem.localtime( ephem.next_first_quarter_moon(target_date_utc) ).date()
    previous_full = ephem.localtime( ephem.previous_full_moon(target_date_utc) ).date()
    previous_new = ephem.localtime( ephem.previous_new_moon(target_date_utc) ).date()
    previous_last_quarter = ephem.localtime( ephem.previous_last_quarter_moon(target_date_utc) ).date()
    previous_first_quarter = ephem.localtime( ephem.previous_first_quarter_moon(target_date_utc) ).date()
    if target_date_local in (next_full, previous_full):
        return 'Full'
    elif target_date_local in (next_new, previous_new):
        return 'New'
    elif target_date_local in (next_first_quarter, previous_first_quarter):
        return 'First Quarter'
    elif target_date_local in (next_last_quarter, previous_last_quarter):
        return 'Last Full Quarter'
    elif previous_new < next_first_quarter < next_full < next_last_quarter < next_new:
        return 'Waxing Crescent'
    elif previous_first_quarter < next_full < next_last_quarter < next_new < next_first_quarter:
        return 'Waxing Gibbous'
    elif previous_full < next_last_quarter < next_new < next_first_quarter < next_full:
        return 'Waning Gibbous'
    elif previous_last_quarter < next_new < next_first_quarter < next_full < next_last_quarter:
        return 'Waning Crescent'
hanksims
  • 1,479
  • 2
  • 12
  • 22