I'm currently reading through the MEAP book Tiny C Projects by Dan Gookin. In the opening chapter he presents a small daily greeting program which also reports the phase of the moon. The calculations in the book for this look very strange - he also states outright that he doesn't know where he first got this code from or even what it's doing; it also doesn't have any comments or links to any other explanatory information. This is my cleaned-up rendition of it:
int moonphase_from_tm(struct tm* datetime)
{
int year = datetime->tm_year;
int month = datetime->tm_mon;
int day = datetime->tm_mday;
if (month == 2)
{
day += 31;
}
else if (month > 2)
{
day += 59 + (month - 3) * 30.6 + 0.5;
}
int g = year % 19;
int e = (11 * g + 29) % 30;
if (e == 25 || e == 24)
{
++e;
}
int phase = ((((e + day) * 6 + 5) % 177) / 22 & 7);
return phase;
}
It returns an int
used to index a string out of a char*
array describing the current moon phase.
Can anybody figure out what this is actually doing? I looked up moon phase calculations on Google and can't find anything that bears more than a passing resemblance to this. It also isn't entirely accurate with the entire thing being calculated with ints (it's out by a day or so, checking against some moon-phase tracking websites), which makes finding something similar a little more difficult.
Below is the original old-style version as reproduced in the book; when calling it, the author adds 1900
to the date, but then this is immediately subtracted again on line 13 when assigning to g
, so I just didn't bother doing either:
int moonphase_book_verbatim(int year, int month, int day)
{
int d, g, e;
d = day;
if (month == 2)
{
d += 31;
}
else if (month > 2)
{
d += 59 + (month - 3) * 30.6 + 0.5;
}
g = (year - 1900) % 19;
e = (11 * g + 29) % 30;
if (e == 25 || e == 24)
{
++e;
}
return ((((e + d) * 6 + 5) % 177) / 22 & 7);
}