Calculating the Moon Phase Part 2

In an older post about Calculating the Moon Phase, I converted the some code I found to PHP. However the Lunar Phase Calculator has some more information (ecliptic latitude and longitude in degrees, the moon’s distance in Earth radii, etc.), the other one doesn’t, so I went ahead and converted it from JavaScript to PHP.


<?php
/*
Based on the JavaScript
Lunar Phase Calculator
by Stephen R. Schmitt

http://home.att.net/~srschmitt/script_moon_phase.html

which was adapted from a BASIC program from the Astronomical Computing column of Sky & Telescope, April 1994
*/
function isdayofmonth($month, $day, $year)
{
$dim = array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
if ($month != 2)
{
if (1 <= $day && $day <= $dim[$month - 1])
return true;
else
return false;
}
$feb = $dim[1];
if (isleapyear($year))
{
$feb++;// is leap year
}
if (1 <= $day && $day <= $feb)
{
return true;
}
return false;
}
function isleapyear($year)
{
$a = floor($year - 4 * floor($year / 4));
$b = floor($year - 100 * floor($year / 100));
$c = floor($year - 400 * floor($year / 400));
// possible leap year
if ($a == 0)
{
if ($b == 0 && $c != 0)
return false;// not leap year
else
return true;// is leap year
}
return false;
}
// compute moon position and phase
function moon_posit($month = null, $day = null, $year = null)
{
$moon = array();
if(!isdayofmonth($month, $day, $year))
{
$moon['errors'] = 'Invalid date';
}
else
{
$moon['errors'] = null;
$age = 0.0;// Moon's age in days from New Moon
$distance = 0.0;// Moon's distance in Earth radii
$latitude = 0.0;// Moon's ecliptic latitude in degrees
$longitude = 0.0;// Moon's ecliptic longitude in degrees
$phase = '';
$zodiac = '';
$YY = 0;
$MM = 0;
$K1 = 0;
$K2 = 0;
$K3 = 0;
$JD = 0;
$IP = 0.0;
$DP = 0.0;
$NP = 0.0;
$RP = 0.0;
// calculate the Julian date at 12h UT
$YY = $year - floor((12 - $month) / 10);
$MM = $month + 9;
if ($MM >= 12)
{
$MM = $MM - 12;
}
$K1 = floor(365.25 * ($YY + 4712));
$K2 = floor(30.6 * $MM + 0.5);
$K3 = floor(floor(($YY / 100) + 49) * 0.75) - 38;
$JD = $K1 + $K2 + $day + 59;// for dates in Julian calendar
if ($JD > 2299160)
{
$JD = $JD - $K3;// for Gregorian calendar
}
// calculate moon's age in days
$IP = normalize(($JD - 2451550.1) / 29.530588853);
$age = $IP * 29.53;
if ($age < 1.84566)
$phase = 'NEW';
else if ($age < 5.53699)
$phase = 'Evening crescent';
else if ($age < 9.22831)
$phase = 'First quarter';
else if ($age < 12.91963)
$phase = 'Waxing gibbous';
else if ($age < 16.61096)
$phase = 'FULL';
else if ($age < 20.30228)
$phase = 'Waning gibbous';
else if ($age < 23.99361)
$phase = 'Last quarter';
else if ($age < 27.68493)
$phase = 'Morning crescent';
else
$phase = 'NEW';
$IP = $IP * 2 * pi();// Convert phase to radians
// calculate moon's distance
$DP = 2 * pi() * normalize(($JD - 2451562.2) / 27.55454988);
$distance = 60.4 - 3.3 * cos($DP) - 0.6 * cos(2 * $IP - $DP) - 0.5 * cos(2 * $IP);
// calculate moon's ecliptic latitude
$NP = 2 * pi() * normalize(($JD - 2451565.2) / 27.212220817);
$latitude = 5.1 * sin($NP);
// calculate moon's ecliptic longitude
$RP = normalize(($JD - 2451555.8) / 27.321582241);
$longitude = 360 * $RP + 6.3 * sin($DP) + 1.3 * sin(2 * $IP - $DP) + 0.7 * sin(2 * $IP);
if ($longitude < 33.18)
$zodiac = 'Pisces';
else if ($longitude < 51.16)
$zodiac = 'Aries';
else if ($longitude < 93.44)
$zodiac = 'Taurus';
else if ($longitude < 119.48)
$zodiac = 'Gemini';
else if ($longitude < 135.30)
$zodiac = 'Cancer';
else if ($longitude < 173.34)
$zodiac = 'Leo';
else if ($longitude < 224.17)
$zodiac = 'Virgo';
else if ($longitude < 242.57)
$zodiac = 'Libra';
else if ($longitude < 271.26)
$zodiac = 'Scorpio';
else if ($longitude < 302.49)
$zodiac = 'Sagittarius';
else if ($longitude < 311.72)
$zodiac = 'Capricorn';
else if ($longitude < 348.58)
$zodiac = 'Aquarius';
else
$zodiac = 'Pisces';
// so longitude is not greater than 360!
if ($longitude > 360)
$longitude = $longitude - 360;
$moon['age'] = round($age, 2);
$moon['distance'] = round($distance, 2);
$moon['latitude'] = round($latitude, 2);
$moon['longitude'] = round($longitude, 2);
$moon['phase'] = $phase;
$moon['zodiac'] = $zodiac;
}
return $moon;
}
// normalize values to range 0...1
function normalize($v)
{
$v = $v - floor($v);
if ($v < 0)
{
$v++;
}
return $v;
}
?>

And to use it, you can do something like this

<?php
include('moon2.php');
$date = time();
$year = date('Y', $date);
$month = date('n', $date);
$day = date('j', $date);
$moon = moon_posit($month, $day, $year);
//debug results
echo '<pre>';
print_r($moon);
echo '</pre>';
if ($moon['errors'] === null)
{
//output and format what you want
}
else
{
//handle error how you want, perhaps give error message and then show today''s moon info
}
?>

I haven’t figured out how to get the percentage of illumination of the moon though.

Found two WordPress plugins that have some code you might look at for moon phase calculation: ephemeris and moon phases

Tags: ,

Comments 1-4 of 4 to “Calculating the Moon Phase Part 2”

  1. 1 · guest says:

    the script work fine but we are now in 2010 are you sure of the moons position (longitude on ecliptique) ? The 09 january 2010 the moon are in Libra not in Virgo …
    It is possible to modify the script for a best moon course ?
    thank for the work !

  2. 2 · blogger says:

    All I did was convert the code. I’m not sure about the math behind it all, but this code and the other one were the only two I could find online. Feel free to edit it how you like.

  3. 3 · Great work well done says:

    I have converted it to VB and so far wors well. just the rest of my life to see how it goes. :). thanks for your work.

  4. 4 · mrugesh shah says:

    your is a great code. just one question.

    can you explain me how to change the timezone in the above code ?

    I want +5:30 INDIAN (IST) timezone.

    please help.

Leave a Comment

Comments are reviewed before publishing to prevent spam.