Simple script for lunar/moon phases.
It’s not exact but pretty close for what I need.
--Classification of Lunar Phases
set {year:y, month:m, weekday:w, day:d, hours:h} to (current date)
if (m = 1) then
set d to d - 1
else if (m = 2) then
set d to d + 30
else
set d to d + 28 + (m - 2) * 3059 / 100
end if
set g to (y - 1900) mod 19 + 1
set e to (11 * g + 18) mod 30
if (((e = 25) and (g > 11)) or (e = 24)) then
set e to e + 1
end if
set fullness to ((((e + d) * 6 + 11) mod 177) / 22) as integer
if (fullness = 8) then set fullness to 0
set moonPhase to fullness
if moonPhase = 0 then
set lunarCalendar to "New "
else if moonPhase = 1 then
set lunarCalendar to "Waxing cresent "
else if moonPhase = 2 then
set lunarCalendar to "First quarter "
else if moonPhase = 3 then
set lunarCalendar to "Waxing gibbous "
else if moonPhase = 4 then
set lunarCalendar to "Full "
else if moonPhase = 5 then
set lunarCalendar to "Waning gibbous "
else if moonPhase = 6 then
set lunarCalendar to "Third quarter "
else
set lunarCalendar to "Waning cresent"
end if
return lunarCalendar & "moon"
Looks good. But you need to test for m being either ‘January’ or ‘February’ in the first ‘if’ statement, because months aren’t automatically coerced to integer in equality tests. The '(m - 2) is OK though, because coercion is automatic in math operations.
set {year:y, month:m, weekday:w, day:d, hours:h} to (current date)
if (m = January) then
set d to d - 1
else if (m = February) then
set d to d + 30
else
set d to d + 28 + (m - 2) * 3059 / 100
end if
. and getting rid of the if - else chain, weekday and hours parameters are not needed
set {year:y, month:m, day:d} to (current date)
if (m = January) then
set d to d - 1
else if (m = February) then
set d to d + 30
else
set d to d + 28 + (m - 2) * 3059 / 100
end if
set g to (y - 1900) mod 19 + 1
set e to (11 * g + 18) mod 30
if (((e = 25) and (g > 11)) or (e = 24)) then
set e to e + 1
end if
set moonPhase to (((((e + d) * 6 + 11) mod 177) / 22) as integer) mod 8
set descriptions to {"New", "Waxing cresent", "First quarter", "Waxing gibbous", "Full", "Waning gibbous", "Third quarter", "Waning cresent"}
return item (moonPhase + 1) of descriptions & space & "moon"
. and the first ‘if . else .’ statement would be statistically a little faster if inverted like so:
if (m > February) then
set d to d + 28 + (m - 2) * 3059 / 100
else if (m = February) then
set d to d + 30
else
set d to d - 1
end if
In this version, ten of the twelve possible months are covered by the first test, so the second test (m = February) is only performed if ‘m’ is one of the other two months. In the original, the first test only caught January and so the second had to be done with all eleven of the other months. In this particular script, the difference is far too small to affect the user experience in any way, but it’s useful to think of such things when working out programme flows.
Thanks McUsrll,
That’s an impressive script, but WAY more complex than I need. Plus it doesn’t involve installing Satimage.osax. Thanks for sharing McUsrll. Also thanks to StefanK & Nigel for cleaning up my original script!
Actually you should look into McUsr and Nigel’s advice. On the surface something may look good, but there could be bugs in your script on certain dates. Believe me. I’ve found several anomallies on some developer’s date scripts. The only hard part is trying to understand how they got it so accurate. Well basically you need to look into everything.
I didn’t give any advice, and I like his script. Its cool to be used from the calendar or the like, so you know what to expect with regards to the moon. It should do niceley in a notification.
No, a leap year is a calendric invension, but a moon phase will occur one day earlier in a leap year, after feb the 29th, than it would have otherwise done.
Soxmonky’s script is quick, it is the kind of thing you’d use from the Calendar.app or something to not stall it. There is of course a tradeoff between speed and accuracy, but all that accuracy aren’t always needed, and when you are aware of it, that you may get a good hunch, but not total accuracy, then it is great. I think soxmonky stated that when he posted it.
Nice to see so many Moone Boy’s out there. This script is just a small piece of a much bigger script I have run in the morning. Accuracy isn’t all that important but speed is. There’s about 3-4 days leeway for each moon phase, I’m pretty sure this script doesn’t take into account leap years, thats above my pay grade.
The leap year may be somehow, baked into the formula for the moonphases for all we know. And the excempt for the leap years are century years that is not divisible by 400, like 1800, 1900 and so on.
As you probably know, the rationale behind leap years is that an astronomical year (the time it takes the earth to go round the sun) is approximately 365¼ (365.25) days. So if we normally have exactly 365 days in a calendar year, we have to add a day every fourth year to make up the accumulated four quarter-days’ difference.
But in fact, an astronomical year is closer to 365.2425 days ” three-quarters of a hundredth of a day less than 365¼. This means that every 100 leap years (or 400 years), we’ll have added 3 leap days too many. ((365 * 3 + 366) * 100 - 365.2425 * 400 = 3.) These three extra days are most conveniently and evenly omitted by only allowing one century year in every four to be a leap year. The century year which gets to remain a leap year is the one whose number is exactly divisible by 400. This is of course analogous to things at the lower-level: the last year of every four is a leap year, except that only the last century year of every four is a leap year.
Our proleptic Gregorian calendar only takes things to this level of accuracy, so while the number of days in a calendar year depends on the year itself and whereabouts in it you start counting, the length of 400 years is always exactly 365.2425 * 400, or 146097 days, wherever you start. This also happens to be an exact number of weeks, so the weekday-to-date cycle also repeats every 400 years! This has proved useful in the past when dealing with AppleScript date bugs or with dates outside the former official AppleScript date range (1 January 1000 00:00:00 to 31 December 9999 23:59:59). If something needed to be derived from a date which was outside the safe range, a date within the range could be used instead, provided it was a multiple of 400 years (12622780800 seconds) removed from the original. All the details would be exactly the same except for the year number.
PS. The “safe range” is currently less than 400 years wide ((current date) + 1.26227808E+10 is an hour out for dates during daylight-saving time), so the method just described isn’t recommended!