Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
A failed attempt at converting the moon-phase finding Ruby script to a Bash shell script.

Trying to Convert the Ruby Moon Phase-finder to Bash

2013-04-02, 10:28pm

Below is my feeble attempt to convert the moon-phase Ruby script into Bash.

Unfortunately, this doesn't work for two reasons:

  1. I don't know shell scripting very well.
  2. Bash arithmetic can't handle anything other than integers.

There is a chance that cal() or date() could handle some of this, but I don't understand either of them well enough. I also have a suspicion that the way I'm using 'Julian' in this code is an inaccurate descriptor of what's being calculated. I should have read up on moon phase calculating or read through the source of the other libraries around GitHub that are doing this, but I was rushing to make this a fast, fun thing so I didn't get mired in the literature like I want to now.

In any case, here's as far as I got before giving up for the night.

# Convert a date to Julian.
function convert_to_julian {
a=(14-$2)/12
y=$1+4800-a
m=(12*a)-3+$2
converted_date=$(($3 + $(($((153*$m+2))/5)) + $((365*$y)) + $(($y/4)) - $(($y/100)) + $(($y/400)) - $((32045))))
}
# Define the phases of the moon.
function get_moon_phase {
convert_to_julian $1 $2 $3 | date +%Y\ %m\ %d
today=$converted_date
convert_to_julian 2000 1 6
converter=$converted_date
phase_number=$(($(($today - $converter))%29))
if [ phase_number -lt "1.84566" ]; then phase_icon="πŸŒ‘" # new
elif [ phase_number -lt "5.53699" ]; then phase_icon="πŸŒ’" # waxing crescent
elif [ phase_number -lt "9.22831" ]; then phase_icon="πŸŒ“" # first quarter
elif [ phase_number -lt "12.91963" ]; then phase_icon="πŸŒ”" # waxing gibbous
elif [ phase_number -lt "16.61096" ]; then phase_icon="πŸŒ•" # full
elif [ phase_number -lt "20.30228" ]; then phase_icon="πŸŒ–" # waning gibbous
elif [ phase_number -lt "23.99361" ]; then phase_icon="πŸŒ—" # last quarter
elif [ phase_number -lt "27.68493" ]; then phase_icon="🌘" # waning crescent
else phase_icon="πŸŒ‘" # new
fi
}
get_moon_phase
echo $phase_icon

m8x60mm commented Apr 13, 2015

  1. If you want to take your bash-fu to the next level, I recommend reading the FAQ and other bash-related materials at wooledge.org.
  2. A very old trick for doing floating-point math when only integer math is available: remap the number space. For example, suppose your code never needs a number greater than 2,000, less than 0, or with more than 5 digits after the decimal point. In that case you could just multiply everything by 100,000, and the biggest number should still be within the 2,147,483,647 limit on typical 32-bit systems. Of course, it's much more general to just use the suggestions in the above-mentioned bash FAQ, but I'd probably do the remap thing in the trivial cases just because it's, well, a trivial case.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment