class MoonPhases

Credits {github.com/tingletech/moon-phase tingletech}

Constants

JULIAN_DAYS_IN_MONTH
LIMIT_JULIAN_CALENDAR
YEAR_IN_DAYS

Attributes

age[R]
constellation[R]
date[R]
detailed_age[R]
detailed_constellation[R]
detailed_distance[R]
detailed_position[R]
distance[R]
latitude[R]
longitude[R]
magnitude[R]
phase[R]
sweep[R]

Public Class Methods

new(date = Date.today) click to toggle source
# File lib/astro_calc/moon_phases.rb, line 16
def initialize(date = Date.today)
  @date = date
  perform_calculations
end

Public Instance Methods

normalize(value) click to toggle source

Normalizes the value to be in the range 0..1

@param value [Float] the value to normalize @return [Float] the normalized value

# File lib/astro_calc/moon_phases.rb, line 110
def normalize(value)
  value -= value.floor 
  value += 1 if value < 0
  value
end
perform_calculations() click to toggle source
# File lib/astro_calc/moon_phases.rb, line 21
def perform_calculations
  year  = @date.year
  month = @date.month
  day   = @date.day

  #calculate the Julian date at 12h UT
  y = year - ((12 - month) / 10.0).floor
  m = month + 9 
  m = m - 12 if m >= 12
  
  k1 = (YEAR_IN_DAYS * (y + 4712)).floor
  k2 = (30.6 * m + 0.5 ).floor
  k3 = (((y / 100) + 49) * 0.75).floor - 38
  
  julian_day = k1 + k2 + day + 59                                    # for Julian calendar
  julian_day = julian_day - k3 if julian_day > LIMIT_JULIAN_CALENDAR # for Gregorian calendar
      
  #calculate moons age in Julian days
  i_phase  = normalize((julian_day - 2451550.1 ) / JULIAN_DAYS_IN_MONTH)
  @age = i_phase * JULIAN_DAYS_IN_MONTH
  
  @phase = case @age
    when 1.84566..5.53699 then "waxing crescent"
    when 5.53669..9.22831 then "first quarter"
    when 9.22831..12.91963 then "waxing gibbous"
    when 12.91963..16.61096 then "full moon"
    when 16.61096..20.30228 then "waning gibbous"
    when 20.30228..20.30228 then "last quarter"
    when 20.30228..27.68493 then "waning crescent"
    else "new moon"
  end
  
  #convert phase to radians
  i_phase_radians = i_phase * 2 * Math::PI  

  #calculate moon's distance
  distance_phase = 2 * Math::PI * normalize((julian_day - 2451562.2 ) / 27.55454988)
  @distance = 60.4 - 3.3 * Math.cos(distance_phase) - 0.6 * Math.cos(2 * i_phase_radians - distance_phase) - 0.5 * Math.cos(2 * i_phase_radians)

  #calculate moon's ecliptic latitude
  normal = 2 * Math::PI * normalize((julian_day - 2451565.2) / 27.212220817)
  @latitude = (5.1 * Math.sin(normal)).round(3)

  #calculate moon's ecliptic longitude
  real_phase = normalize((julian_day - 2451555.8) / 27.321582241)
  @longitude = (360 * real_phase + 6.3 * Math::sin(distance_phase) + 1.3 * Math.sin(2 * i_phase_radians - distance_phase) + 0.7 * Math.sin(2 * i_phase_radians)).round(3)

  @constellation = case @longitude
    when 33.18..51.16 then "Aries"
    when 51.16..93.44 then "Taurus"
    when 93.44..119.48 then "Gemini"
    when 119.48..135.30 then "Cancer"
    when 135.30..173.34 then "Leo"
    when 173.34..224.17 then "Virgo"
    when 224.17..242.57 then "Libra"
    when 242.57..271.26 then "Scorpio"
    when 271.26..302.49 then "Sagittarius"
    when 302.49..311.72 then "Capricorn"
    when 311.72..348.58 then "Aquarius"
    else "Pisces"
  end

  # the "sweep-flag" and the direction of movement change every quarter moon
  # zero and one are both new moon; 0.50 is full moon
  case i_phase
  when 0.25..0.50 then
    @sweep     = [0, 0];
    @magnitude = 20 * (i_phase - 0.25) * 4
  when 0.50..0.75 then
    @sweep     = [1, 1];
    @magnitude = 20 - 20 * (i_phase - 0.50) * 4
  when 0.75..1.00 then
    @sweep     = [0, 1];
    @magnitude = 20 * (i_phase - 0.75) * 4
  else 
    @sweep     = [1, 0];
    @magnitude = 20 - 20 * i_phase   * 4
  end

  @detailed_position      = "Ecliptic position : λ #{@longitude} - β #{@latitude}"
  @detailed_age           = "Current cycle age #{(@age).round(2)} days"
  @detailed_distance      = "Distance is #{(@distance).round(2)} earth radii"
  @detailed_constellation = "The #{@phase} moon is in #{@constellation}"    
end
svg() click to toggle source

Calculates the magnification for a given telescope and eyepiece

@return [String] the SVG output

# File lib/astro_calc/moon_phases.rb, line 135
def svg
  output = ""
  output << "<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100% 100%' version='1.1' class='astro_moon_phase'>"
  output << "<image xlink:href='moon.jpg; x='0' y='0' height='200px' width='200px'/>"
  output << "<path d='m100,0 a#{@magnitude.round(2)},20 0 1,#{@sweep[0]} 0,150 a20,20 0 1,#{@sweep[1]} 0,-150' class='astro_moon'></path>"
  output << "</svg>"
  output.html_safe
end
unicode() click to toggle source

Provides the unicode characters for the moon phase

@return [String] the unicode string showing the moon phase

# File lib/astro_calc/moon_phases.rb, line 119
def unicode  
  case @phase 
    when 0.0625..0.1875 then "🌒"
    when 0.1875..0.3125 then "🌓"
    when 0.3125..0.4375 then "🌔"
    when 0.4375..0.5625 then "🌕"
    when 0.5625..0.6875 then "🌖"
    when 0.6875..0.8125 then "🌗"
    when 0.8125..0.9375 then "🌘"
    else "🌑"      
  end
end