Calculating moon phase for a date

How to know the current moon phase without walking outside at night and hoping that there are no clouds? You can of course look it up on the Internet.

However, I decided to design my own PHP script to calculate the moon phase. Here below I will explain how the script works, and I include the PHP source code of a small demo script.

How to calculate moon phases?

How to do it? If you want to be very accurate, it is also very complicated, because the duration of a lunar cycle fluctuates. However, the fluctuations are small, so I decided to work with a formula that is based on a repeating fixed lunar cycle duration.

For this fixed lunar cycle I have used: 29.53058770576 days. If you want to know why I picked this number, see: .

I am happy with a script that works for the period between years 1900 and 2100 (just 200 years), so as a starting point for the calculation I used the first new moon of the year 2000.

The first new moon of 2000 was on January 6 at 18:14 UTC. (see: )

The script will start with a certain date and time. It then calculates the moment in the corresponding lunar cycle as a fraction, where 0 and 1 are ‘new moon’, .25 is ‘first quarter moon’, 0.5 is ‘full moon’ and 0.75 is ‘last quarter moon’.

These 4 names for moon phases correspond to the following ‘age’ of the moon:

  • 0 days = new
  • 7.38264692644 days = first quarter
  • 14.76529385288 days = full
  • 22.14794077932 days = last quarter (or third quarter)
  • 29.53058770576 days = 0 days = new again

These moon phases are moments in time. The periods in between are called ‘waxing crescent’, ‘waxing gibous’, ‘waning gibous’, and ‘waning crescent’.

Of course when we want to calculate the moon phase for a certain day, we need to use a certain period (instead of a moment) to be called ‘new’, ‘first quarter’, etc. Otherwise the formula would only find waxing or waning moons.

In formulas on the Internet I have seen that the moon cycle is often divided in 8 equal part. That gives 8 moon phases (new, waxing crescent, first quarter, waxing gibous, full, waning gibous, etc.), which each have the same length of about 3.69 days.

I don’t find that very realistic, because it means that 3 or 4 consecutive days will be called ‘full moon’, or ‘new moon’. So I want to reduce the length of the periods which I will call ‘new’, ‘first quarter’, ‘full’ and ‘last quarter’, and increase the length of the ‘waxing’ and ‘waning’ periods.

I decided that I will call the moon ‘full’ when it is within 1 day before and 1 day after the full moon age. So the ‘full moon’ is from age 13.76529385288 to age 15.76529385288 and has a duration of 2 days. In the same way ‘first quarter’, ‘last quarter’ and ‘new moon’ will be periods of 2 days duration. The 2 waxing and the 2 waning periods now each have a duration of 5.38264692644 days.

So I prepared the following tables. When calculating the moon phase, the script can then use either of these tables to look up the name of the lunar phase.

Age of moon in days

from age to age
New 0 1
Waxing Crescent 1 6.38264692644001
First Quarter 6.38264692644001 8.38264692644
Waxing Gibbous 8.38264692644 13.76529385288
Full 13.76529385288 15.76529385288
Waning Gibbous 15.76529385288 21.14794077932
Last Quarter 21.14794077932 23.14794077932
Waning Crescent 23.14794077932 28.53058770576
New 28.53058770576 29.53058770576

Fraction of the moon cycle

from to
New 0 0.033863193308711
Waxing Crescent 0.033863193308711 0.216136806691289
First Quarter 0.216136806691289 0.283863193308711
Waxing Gibbous 0.283863193308711 0.466136806691289
Full 0.466136806691289 0.533863193308711
Waning Gibbous 0.533863193308711 0.716136806691289
Last Quarter 0.716136806691289 0.783863193308711
Waning Crescent 0.783863193308711 0.966136806691289
New 0.966136806691289 1

How does the moon phaser formula work?

The script needs just a few steps to calculate the moon phase for a date and time.

  1. Use the lunar cycle constant (29.53058770576 ) and calculate its duration in seconds (lunarsecs).
  2. Let user enter a date and convert to unix timestamp (unixdate)’
  3. Convert date of first full moon in 2000 (January 6 at 18:14 UTC) to unix timestamp (new2000)
  4. Calculate ‘totalsecs’ which is the time (in seconds) between the user date and the moment of the first new moon in 2000 (totalsecs = unixdate – new2000)
  5. Calculate the modulus , to know the amount of seconds that have passed in the current cycle (currentsecs).
  6. If this is negative number (in case a date was selected before 2000) we add 1 cycle (add ‘lunarsecs’ to ‘currentsecs’).
  7. Now divide ‘currentsecs’ by ‘lunarsecs’ to know the fraction which tells us where we are in the cycle (currentfrac).
  8. Look up in a table what the corresponding moon phase is (currentphase)

Below is the source code (PHP) of a short demo script.

Source code of demo moon phaser script

PHP to JavaScript

After getting this PHP script working I rewrote the script in JavaScript. You can see it at work on the Moon Phaser page, where you can pick your own date and time and the script returns the corresponding moon phase.

Scroll to Top