Forum Moderators: open

Message Too Old, No Replies

Lunar Phase Formula

Does anyone know it?

         

neophyte

11:08 am on Oct 2, 2009 (gmt 0)

10+ Year Member



No idea where else I could post this question so here it is: Have a project spec that includes building a Lunar Phase calculator in php from scratch.

I've been searching and searching (moon phase formula, lunar phase equation, etc., etc.) and while there's TONS of moon phase calculators out there, not one that I found offers the secret to how it's done - e.g. what the formula is to make such a calculation for varying days, months, years.

Thought I'd just scrape some site that already has the data but was then told that I've gotta create a function that will display ALL phases - not just the primary ones: New moon, first-quarter, full moon, last-quarter.

Now I just stumbled onto a site that indicates that moon phases are slightly different depending on location on earth... say what?

Anyway, there's my dilemma. Anybody got any idea where I could find such a formula?

Great appreciation for all responses!

Neophyte

jdMorgan

12:02 pm on Oct 2, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Establish a fixed date in the past where the exact phase is known for a known location -- I would suggest the Greenwich Observatory meridian, so that you start with GMT/UTC=0. Then calculate the number of full lunar cycles since then, and throw away all but the remainder. Then calculate the user's offset from GMT/UTC to obtain the correction for his "local time." The moon phase will vary slightly due to this offset -- visualize that a user in California is one-quarter of a day 'behind' Greenwich, England.

By using this method, you deal only in 'seconds since the originally-established phase' and can do all the time/date conversions last.

Jim

swa66

6:55 pm on Oct 2, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Not the formulas, but the orbital data is e.g. here:
[nssdc.gsfc.nasa.gov...]
Considering these folks went there ...

kaled

8:43 pm on Oct 3, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I believe the Synodic value (29.53 days) is the key. If you have an initial value, you can calculate the phase from that.

I'm not sure how geolocation (longitude and latitude) affects the calculation, but if you test other calculators (that agree with one another) then you should be able to figure it out. HOWEVER, be certain that you are using the correct time, i.e. local or GMT/UTC (or possibly solar time).

Kaled.

swa66

9:45 pm on Oct 3, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Timezone, even longitude and latitude are important:

Consider somebody in London and Sydney: they are half a day apart ... if you seek high accuracy that's going to be important to know if the moon is fully with it's shadow side to the earth or if there is that thinest of a line of sunlit moon showing through.

Consider moonrise and moonset times: it's going to be depended on where you are on the globe, just as it is with the sun.

When calculating moon or sun eclipses, the location of the observer is even more important (the are where the eclipse is visible is small and moves quite rapidly over the surface of the earth).

neophyte

2:21 am on Oct 5, 2009 (gmt 0)

10+ Year Member



JdMorgan, swa66 and kaled -

Thank you all so much for your insight and input. I've managed to build a preliminary function that spits out the the Moon Age based on Julian Days which sort of works - atleast I guess it does. I'm comparing my output to the output of some moon phase calculators on the net and most of the moon ages I'm getting are correct except one nagging Zero Moon Age output. Some calculators indicate that there is indeed a Zero Moon Age, others do not - hummm.

Anyway... the process continues.

Neophyte.

httpwebwitch

3:11 pm on Oct 5, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Hey! another astronomical computation enthusiast!

There's a book by Meeus called Astronomical Algorithms. You must get it. Not easy to find, but you can order it direct from the publisher.

In it, you'll find accurate methods for calculating all kinds of plantary, lunar and orbital events. Plus, you'll learn a lot about not-so-obvious challenges in astronomical computation from a pro.

As a beginning programmer back in the 90's, I used that book to build a virtual orrery & astro visualizer for my own amusement. Comparing my data with almanacs from the US Navy, they were all spot on to within fractions of seconds.

g1smd

9:56 pm on Oct 5, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Do be aware that the exact moment of New or Full Moon - or of any phase for that matter - might occur when the Moon is below your horizon.

httpwebwitch

12:57 am on Oct 6, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



oh, by the way the synodic month mentioned by kaled (29.53 days) is an average. Some lunar months are longer than others, because the earth does not travel at a fixed speed around its orbit. So, some months are slightly longer than others, as the moon needs more time to "catch up" with the faster-travelling earth.

So, if you want accuracy, none of the formulas mentioned so far will cut it.

httpwebwitch

4:48 am on Oct 6, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I dug this up from the vaults... it's in VBscript. I started porting these to PHP, but then I gave up on the project before I got to lunar events. please excuse the code dump


function moonphase(inyear,phase)
' input: approximate time and phase
' output: nearest requested phase moment in JD

' inyear is the year (yyyy) plus decimal fraction for parts of the year.

' phase=0 - new
' phase=1 - first quarter
' phase=2 - full
' phase=3 - last quarter

realphase=phase * 0.25

' k is the lunation number. partial lunations correspond to partial phases. Algorithm is valid only for 1/4 parts of a lunation
' approximate value for k is (year - 2000) * 12.3685
' find the lunation (new moon) closest to date X
' this is often not accurate enough!

k = INT((inyear - 2000) * 12.3685)

k = k + realphase

' where k = lunation integer,
' k+0 - new moon
' k+0.25 - first quarter
' k+0.5 - full moon
' k+0.75 - last quarter
' any other value for k will give meaningless results.

T = k / 1236.85 ' time in Julian centuries since the epoch 2000
JDE = 2451550.09766 + (29.530588861 * k) + (0.00015437 * T*T) - (0.000000150 * T*T*T) + (0.00000000073 * T*T*T*T)

M = 2.5534 + (29.10535670 * k) - (0.0000014 * T*T) - (0.00000011 * T*T*T) ' Suns mean anomaly
M_prime = 201.5643 + (385.81693528 * k) + (0.0107582 * T*T) + (0.00001238 * T*T*T) - (0.000000058 * T*T*T*T) ' Moons mean anomaly
F = 160.7108 + (390.67050284 * k) - (0.0016118 * T*T) - (0.00000227 * T*T*T) + (0.000000011 *T*T*T*T) ' moons argument of latitude
omega = 124.7746 - (1.56375588 * k) + (0.0020672 * T*T) + (0.00000215 * T*T*T)

' planetary arguments
a_1 = 299.77 + (0.107408 * k) - (0.009173 * T*T*T)
a_2 = 251.88 + (0.016321 * k)
a_3 = 251.83 + (26.651886 * k)
a_4 = 349.42 + (36.412478 * k)
a_5 = 84.66 + (18.206239 * k)
a_6 = 141.74 + (53.303771 * k)
a_7 = 207.14 + (2.453732 * k)
a_8 = 154.84 + (7.306860 * k)
a_9 = 34.52 + (27.261239 * k)
a_10 = 207.19 + (0.121824 * k)
a_11 = 291.34 + (1.844379 * k)
a_12 = 161.72 + (24.198154 * k)
a_13 = 239.56 + (25.513099 * k)
a_14 = 331.55 + (3.592518 * k)

E = 1 - (0.002516*T) - (0.0000074 * T*T)

if realphase = 0 then
' corrections for new moon
' these first 7 are a little different
corr = -0.40720 * dsin(M_prime)
corr = corr + 0.17241 * E * dsin(M)
corr = corr + 0.01608 * dsin(2*M_prime)
corr = corr + 0.01039 * dsin(2*F)
corr = corr + 0.00739 * E * dsin(M_prime - M)
corr = corr - 0.00514 * E * dsin(M_prime + M)
corr = corr + 0.00208 * E*E* dsin(2*M)
' the rest are the same for new and full
corr = corr - 0.00111 * dsin(M_prime - (2*F))
corr = corr - 0.00057 * dsin(M_prime + (2*F))
corr = corr + 0.00056 * E * dsin((2*M_prime) + M)
corr = corr - 0.00042 * dsin(3*M_prime)
corr = corr + 0.00042 * E * dsin(M + (2*F))
corr = corr + 0.00038 * E * dsin(M - (2*F))
corr = corr - 0.00024 * E * dsin((2*M_prime) - M)
corr = corr - 0.00017 * dsin(omega)
corr = corr - 0.00007 * dsin(M_prime + (2*M))
corr = corr + 0.00004 * dsin((2*M_prime)-(2*F))
corr = corr + 0.00004 * dsin(3*M)
corr = corr + 0.00003 * dsin(M_prime + M - (2*F))
corr = corr + 0.00003 * dsin((2*M_prime) + (2*F))
corr = corr - 0.00003 * dsin(M_prime + M + (2*F))
corr = corr + 0.00003 * dsin(M_prime - M + (2*F))
corr = corr - 0.00002 * dsin(M_prime - M - (2*F))
corr = corr - 0.00002 * dsin((3*M_prime) + M)
corr = corr + 0.00002 * dsin(4*M_prime)

JDE = JDE + corr

elseif realphase = 0.5 then
' full moon
' these first 7 are a little different
corr = -0.40614 * dsin(M_prime)
corr = corr + 0.17302 * E * dsin(M)
corr = corr + 0.01614 * dsin(2*M_prime)
corr = corr + 0.01043 * dsin(2*F)
corr = corr + 0.00734 * E * dsin(M_prime - M)
corr = corr - 0.00515 * E * dsin(M_prime + M)
corr = corr + 0.00209 * E*E* dsin(2*M)
' the rest are the same for new and full
corr = corr - 0.00111 * dsin(M_prime - (2*F))
corr = corr - 0.00057 * dsin(M_prime + (2*F))
corr = corr + 0.00056 * E * dsin((2*M_prime) + M)
corr = corr - 0.00042 * dsin(3*M_prime)
corr = corr + 0.00042 * E * dsin(M + (2*F))
corr = corr + 0.00038 * E * dsin(M - (2*F))
corr = corr - 0.00024 * E * dsin((2*M_prime) - M)
corr = corr - 0.00017 * dsin(omega)
corr = corr - 0.00007 * dsin(M_prime + (2*M))
corr = corr + 0.00004 * dsin((2*M_prime)-(2*F))
corr = corr + 0.00004 * dsin(3*M)
corr = corr + 0.00003 * dsin(M_prime + M - (2*F))
corr = corr + 0.00003 * dsin((2*M_prime) + (2*F))
corr = corr - 0.00003 * dsin(M_prime + M + (2*F))
corr = corr + 0.00003 * dsin(M_prime - M + (2*F))
corr = corr - 0.00002 * dsin(M_prime - M - (2*F))
corr = corr - 0.00002 * dsin((3*M_prime) + M)
corr = corr + 0.00002 * dsin(4*M_prime)

JDE = JDE + corr

elseif realphase=0.25 OR realphase=0.75 then
' first and last quarters
corr = -0.62801 * dsin(M_prime)
corr = corr + 0.17172 * E* dsin(M)
corr = corr - 0.01183 * E * dsin(M_prime + M)
corr = corr + 0.00862 * dsin(2*M_prime)
corr = corr + 0.00804 * dsin(2*F)
corr = corr + 0.00454 * E * dsin(M_prime - M)
corr = corr + 0.00204 * E*E* dsin(2*M)
corr = corr - 0.00108 * dsin(M_prime - (2*F))
corr = corr - 0.00070 * dsin(M_prime + (2*F))
corr = corr - 0.00040 * dsin(3*M_prime)
corr = corr - 0.00034 * E * dsin((2*M_prime) - M)
corr = corr + 0.00032 * E * dsin(M + (2*F))
corr = corr + 0.00032 * E * dsin(M - (2*F))
corr = corr + 0.00028 * E*E* dsin(M_prime + (2*M))
corr = corr + 0.00027 * E * dsin((2*M_prime) + M)
corr = corr - 0.00017 * dsin(omega)
corr = corr - 0.00005 * dsin(M_prime - M - (2*F))
corr = corr + 0.00004 * dsin((2*M_prime) + (2*F))
corr = corr - 0.00004 * dsin(M_prime + M + (2*F))
corr = corr + 0.00004 * dsin(M_prime - (2*M))
corr = corr + 0.00003 * dsin(M_prime + M - (2*F))
corr = corr + 0.00003 * dsin(3*M)
corr = corr + 0.00002 * dsin((2*M_prime) - (2*F))
corr = corr + 0.00002 * dsin(M_prime - M + (2*F))
corr = corr - 0.00002 * dsin((3*M_prime) + M)

' calculate for quarter phases only
W = 0.00306 - (0.00038 * E * dcos(M)) + (0.00026 * dcos(M_prime)) - (0.00002 * dcos(M_prime - M)) + (0.00002 * dcos(M_prime + M)) + (0.00002 * dcos(2*F))

if realphase = 0.25 then
corr = corr + W
elseif realphase = 0.75 then
corr = corr - W
end if

JDE = JDE + corr

end if

' additional corrections for all phases:

corr = 0.000325 * dsin(a_1)
corr = corr + 0.000165 * dsin (a_2)
corr = corr + 0.000164 * dsin (a_3)
corr = corr + 0.000126 * dsin (a_4)
corr = corr + 0.000110 * dsin (a_5)
corr = corr + 0.000062 * dsin (a_6)
corr = corr + 0.000060 * dsin (a_7)
corr = corr + 0.000056 * dsin (a_8)
corr = corr + 0.000047 * dsin (a_9)
corr = corr + 0.000042 * dsin (a_10)
corr = corr + 0.000040 * dsin (a_11)
corr = corr + 0.000037 * dsin (a_12)
corr = corr + 0.000035 * dsin (a_13)
corr = corr + 0.0000325 * dsin (a_14)

JDE = JDE + corr

moonphase = JDE

end function

httpwebwitch

4:57 am on Oct 6, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



you'll need this

function dsin(x)
dsin = sin(radians(x))
end function

neophyte

5:46 am on Oct 6, 2009 (gmt 0)

10+ Year Member



httpwebwitch -

Wow, I'm speechless. Thanks so much. I've been scanning the VB Code and can pretty much understand most of what's going on. I'll give it a go in PHP and let you know the outcome.

I'm quite interested in the book you were mentioning as well - unfortunately I'm in the Philippines and I'm sure that a book like Astronomical Algorithms will be very difficult to find. I'll look it up on the I-Net and see if I can find the publisher and see if they'll send it overseas.

I would like to get my function to be as accurate as possible for various places on earth and I keep coming up with indications that I would need to somehow input lon/lat values as well.

Anyway, one step at a time. Thanks so very much for your informative posts.

Neophyte

httpwebwitch

12:55 pm on Oct 7, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Lunar phase doesn't depend on your lat/long. In astro terms, a full moon is when the moon is in opposition to the sun, a new moon is when the moon is in conjunction. The vertices are measured from the center point of the spheres (moon and earth). I suppose if you want to get really technical there is a slight difference in how much of the illuminated surface you can see from one side of the earth or another, but this difference is really really really small.

mattglet

5:49 pm on Oct 8, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Great stuff.

kaled

7:26 pm on Oct 8, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I suppose if you want to get really technical there is a slight difference in how much of the illuminated surface you can see from one side of the earth or another, but this difference is really really really small.

The Earth has a diameter of 12,756 km and the moon has a mean orbital radius of 378,000 km this represents an arc of about 1.9 degrees - it's small but not really really really small.

Kaled.

httpwebwitch

4:56 am on Oct 9, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



point taken kaled, and I think your math is right... So in calculations you could choose if you're merely getting the current phase (ie opposition, conjunction, "square", etc), or the current visible illuminated surface from where you're standing. if you're viewing the moon from the left or right "side" of the earth, there's a 1 degree margin of indiscretion either way (approx), and your math just got much more complicated.

Oh, another tip. be careful... The built-in PHP functions for converting Julian to Gregorian dates are not built right, and AFAIK they haven't been fixed. Julian dates begin at noon, and Gregorian Dates begin at midnight. you need to account for that when converting one to the other.

see my comment here from 2004
[php.net...]