Skip to content

Instantly share code, notes, and snippets.

@miklb
Created July 1, 2015 07:12
Show Gist options
  • Star 32 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save miklb/ed145757971096565723 to your computer and use it in GitHub Desktop.
Save miklb/ed145757971096565723 to your computer and use it in GitHub Desktop.
Calculate Lunar Phase
#!/usr/bin/env python
"""
moonphase.py - Calculate Lunar Phase
Author: Sean B. Palmer, inamidst.com
Cf. http://en.wikipedia.org/wiki/Lunar_phase#Lunar_phase_calculation
"""
import math, decimal, datetime
dec = decimal.Decimal
def position(now=None):
if now is None:
now = datetime.datetime.now()
diff = now - datetime.datetime(2001, 1, 1)
days = dec(diff.days) + (dec(diff.seconds) / dec(86400))
lunations = dec("0.20439731") + (days * dec("0.03386319269"))
return lunations % dec(1)
def phase(pos):
index = (pos * dec(8)) + dec("0.5")
index = math.floor(index)
return {
0: "New Moon",
1: "Waxing Crescent",
2: "First Quarter",
3: "Waxing Gibbous",
4: "Full Moon",
5: "Waning Gibbous",
6: "Last Quarter",
7: "Waning Crescent"
}[int(index) & 7]
def main():
pos = position()
phasename = phase(pos)
roundedpos = round(float(pos), 3)
print "%s (%s)" % (phasename, roundedpos)
if __name__=="__main__":
main()
@clintmjohnson
Copy link

Great Script! Thanks

@aceisace
Copy link

aceisace commented Nov 5, 2019

Simple, yet awesome piece of code! 👍 Thanks for sharing :)
If you don't mind, may I use this snippet in one of my repos?

@miklb
Copy link
Author

miklb commented Nov 12, 2019

Not my code, so I’m assuming as long as leave credit in the script, you would be Ok.

@aceisace
Copy link

@miklb
Thanks for getting back. OK, I'll do that then.

@DamienAllonsius
Copy link

Hey! Thanks for the script 👍
I understood that 0.20439731 = 1 / synodic lunar month.
But could you explain what 0.20439731 represents ? Is it the lunation at 00:00 on the 1st of January 2001 ? If yes, where did you get this figure ?
Thanks a lot

@cbronner35
Copy link

Amazing script! Would it be possible to the show percentage of the moon instead of what phase its in?

@miklb
Copy link
Author

miklb commented Sep 8, 2021

Swap out the percentages for the names in the return starting on line 24. You could add them instead of swapping for that matter.

@cbronner35
Copy link

I actually did that at first until I realized that some phases of the moon are between 0% to 50%. I need a more exact percentage. We use night vision googles that amplify light by 6000 times. The moon is the primary source of light for amplification. So when were flying the percent tells how well we are going to see. Hope that makes sense lol

@miklb
Copy link
Author

miklb commented Sep 9, 2021

It does and while this wasn’t my script it’s a challenge worthy figuring out. My 1st instinct is the print lunations and see what that value is.

@miklb
Copy link
Author

miklb commented Sep 9, 2021

Actually I believe roundedpos is your lunation %. I get .09 for today which seems ~.01 accurate

I added print(f"{pos: .2%}" + " illuminated") after the current print

6F986A32-0066-467E-967E-616821A24B22

@cbronner35
Copy link

Perfect!!! Thanks so much that's exactly what I needed! Your amazing! I appreciate it :)

@cbronner35
Copy link

You know actually I'm not super sure its very accurate. I just printed around 12.4 % but according to this site https://www.timeanddate.com/astronomy/@4313572 for our area its 16.1 percent. Any idea why I have such a disconnect between these two?

@miklb
Copy link
Author

miklb commented Sep 10, 2021

My tide app tells me it’s 28% waxing. I believe there are a few different formulas for calculating lunation. All use some fixed time from the past to calculate from. I suppose if you need accuracy to the 1°, a different formula may be required. If you find one I’d be happy to help implement in this script.

@miklb
Copy link
Author

miklb commented Sep 11, 2021

You could always go a different route & make an api call to get the reported lunation. That could also get you visibility for closest weather station and any other details you might need. If worried about connectivity, store it in LocalStorage in the browser. I’m not sure how you are using the script though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment