class Prayertimes::Calculate

Public Class Methods

new(method = "MWL") click to toggle source
# File lib/prayertimes.rb, line 97
def initialize(method = "MWL")
        @@methods.each do |method, config|
                @@defaultParams.each do |name, value|
                        # if name in config['params'] || config['params'][name] != nil
                        config['params'][name] = value
                        # end
                end
        end

        @@calcMethod = method #if method in @@methods else 'MWL'

        params = @@methods[@@calcMethod]['params']
        params.each do |name, value|
                @@settings[name] = value
        end

        @@timeNames.each do |name, value|
                @@offset[name] = 0
        end

end

Public Instance Methods

adjust(params) click to toggle source
# File lib/prayertimes.rb, line 129
def adjust(params)
        @@settings.update(params)
end
adjustHLTime(time, base, angle, night, direction = nil) click to toggle source

adjust a time for higher latitudes

# File lib/prayertimes.rb, line 369
def adjustHLTime(time, base, angle, night, direction = nil)
        portion = self.nightPortion(angle, night)
        diff =  direction == 'ccw' ? self.timeDiff(time, base) : self.timeDiff(base, time)
        if time.nan? or diff > portion
                time = base + ( direction == 'ccw' ? -portion : portion)
        end
        return time
end
adjustHighLats(times) click to toggle source

adjust times for locations in higher latitudes

# File lib/prayertimes.rb, line 358
def adjustHighLats(times)
        params = @@settings
        nightTime = self.timeDiff(times['sunset'], times['sunrise']) # sunset to sunrise
        times['imsak'] = self.adjustHLTime(times['imsak'], times['sunrise'], self.eval(params['imsak']), nightTime, 'ccw')
        times['fajr']  = self.adjustHLTime(times['fajr'], times['sunrise'], self.eval(params['fajr']), nightTime, 'ccw')
        times['isha']  = self.adjustHLTime(times['isha'], times['sunset'], self.eval(params['isha']), nightTime)
        times['maghrib'] = self.adjustHLTime(times['maghrib'], times['sunset'], self.eval(params['maghrib']), nightTime)
        return times
end
adjustTimes(times) click to toggle source

adjust times in a prayer time array

# File lib/prayertimes.rb, line 301
def adjustTimes(times)
        params = @@settings
        tzAdjust = @timeZone - @lng / 15.0
        times.each do |t,v|
                times[t] += tzAdjust
        end

        if params['highLats'] != nil
                times = self.adjustHighLats(times)
        end

        if self.isMin(params['imsak'])
                times['imsak'] = times['fajr'] - self.eval(params['imsak']) / 60.0
        end
        # need to ask about '@@settings
        if self.isMin(params['maghrib'])
                times['maghrib'] = times['sunset'] - self.eval(params['maghrib']) / 60.0
        end

        if self.isMin(params['isha'])
                times['isha'] = times['maghrib'] - self.eval(params['isha']) / 60.0
        end
        times['dhuhr'] += self.eval(params['dhuhr']) / 60.0

        return times
end
arccos(x) click to toggle source
# File lib/prayertimes.rb, line 426
def arccos(x) return ((Math.acos(x)* 180.0) / Math::PI); end
arccot(x) click to toggle source
# File lib/prayertimes.rb, line 429
def arccot(x) return ((Math.atan(1.0/x)* 180.0) / Math::PI); end
arcsin(x) click to toggle source
# File lib/prayertimes.rb, line 425
def arcsin(x) return ((Math.asin(x)* 180.0) / Math::PI); end
arctan(x) click to toggle source
# File lib/prayertimes.rb, line 427
def arctan(x) return ((Math.atan(x)* 180.0) / Math::PI); end
arctan2(y, x) click to toggle source
# File lib/prayertimes.rb, line 430
def arctan2(y, x) return ((Math.atan2(y, x)* 180.0) / Math::PI); end
asrFactor(asrParam) click to toggle source

get asr shadow factor

# File lib/prayertimes.rb, line 329
def asrFactor(asrParam)
        methods = {'Standard'=> 1, 'Hanafi'=> 2}
        return methods[asrParam] ? methods[asrParam] : self.eval(asrParam)
end
asrTime(factor, time) click to toggle source

compute asr time

# File lib/prayertimes.rb, line 221
def asrTime(factor, time)
        decl = self.sunPosition(@jDate + time)[0]
        angle = -self.arccot(factor + self.tan((@lat - decl).abs))
        return self.sunAngleTime(angle, time)
end
computePrayerTimes(times) click to toggle source

compute prayer times at given julian date

# File lib/prayertimes.rb, line 260
def computePrayerTimes(times)
        times   = self.dayPortion(times)
        params  = @@settings

        imsak   = self.sunAngleTime(self.eval(params['imsak']), times['imsak'], 'ccw')
        fajr    = self.sunAngleTime(self.eval(params['fajr']), times['fajr'], 'ccw')
        sunrise = self.sunAngleTime(self.riseSetAngle(@elv), times['sunrise'], 'ccw')
        dhuhr   = self.midDay(times['dhuhr'])
        asr     = self.asrTime(self.asrFactor(params['asr']), times['asr'])
        sunset  = self.sunAngleTime(self.riseSetAngle(@elv), times['sunset'])
        maghrib = self.sunAngleTime(self.eval(params['maghrib']), times['maghrib'])
        isha    = self.sunAngleTime(self.eval(params['isha']), times['isha'])
        return {
                'imsak'=> imsak, 'fajr'=> fajr, 'sunrise'=> sunrise, 'dhuhr'=> dhuhr,
                'asr'=> asr, 'sunset'=> sunset, 'maghrib'=> maghrib, 'isha'=> isha
        }
end
computeTimes() click to toggle source

compute prayer times

# File lib/prayertimes.rb, line 279
def computeTimes
        times = {
                'imsak'=> 5, 'fajr'=> 5, 'sunrise'=> 6, 'dhuhr'=> 12,
                'asr'=> 13, 'sunset'=> 18, 'maghrib'=> 18, 'isha'=> 18
        }
        # main iterations
        @@numIterations.times do
                times = self.computePrayerTimes(times)
        end
        times = self.adjustTimes(times)
        # add midnight time
        if @@settings['midnight'] == 'Jafari'
                times['midnight'] = times['sunset'] + self.timeDiff(times['sunset'], times['fajr']) / 2
        else
                times['midnight'] = times['sunset'] + self.timeDiff(times['sunset'], times['sunrise']) / 2
        end

        times = self.tuneTimes(times)
        return self.modifyFormats(times)
end
cos(d) click to toggle source
# File lib/prayertimes.rb, line 422
def cos(d) return Math.cos((d) * Math::PI / 180); end
dayPortion(times) click to toggle source

convert hours to day portions

# File lib/prayertimes.rb, line 392
def dayPortion(times)
        times.each do |key, value|
                times[key] = value /= 24.0
        end
        return times
end
eval(st) click to toggle source

convert given string into a number

# File lib/prayertimes.rb, line 408
def eval(st)
        val = st.to_s.split('[^0-9.+-]')[0]
        return   val ? val.to_f : 0
end
fix(a, mode) click to toggle source
# File lib/prayertimes.rb, line 435
def fix(a, mode)
        if a.nan?
                return a
        end
        a = a - mode * ((a / mode).floor)
        return  a < 0 ? a + mode : a
end
fixangle(angle) click to toggle source
# File lib/prayertimes.rb, line 432
def fixangle(angle) return self.fix(angle, 360.0); end
fixhour(hour) click to toggle source
# File lib/prayertimes.rb, line 433
def fixhour(hour) return self.fix(hour, 24.0); end
getDefaults() click to toggle source
# File lib/prayertimes.rb, line 149
def getDefaults
        return @@methods
end
getFormattedTime(time, format, suffixes = nil) click to toggle source

convert float time to the given format (see timeFormats)

# File lib/prayertimes.rb, line 174
def getFormattedTime(time, format, suffixes = nil)
        
        return self.invalidTime if time.nan?

        return time if format == 'Float'

        suffixes = @@timeSuffixes if suffixes == nil

        time = self.fixhour(time+ 0.5/ 60)  # add 0.5 minutes to round
        hours = time.floor

        minutes = ((time - hours)* 60).floor
        suffix = format == '12h' ? suffixes[ hours < 12 ? 0 : 1 ]  : ''
        if format == "24h"
                formattedTime = "#{hours}:#{minutes}"
        else
                formattedTime = "#{(hours+11)%12+1}:#{minutes}"
        end
        
        return formattedTime + suffix

end
getMethod() click to toggle source
# File lib/prayertimes.rb, line 137
def getMethod
        return @@calcMethod
end
getOffsets() click to toggle source
# File lib/prayertimes.rb, line 145
def getOffsets
        return @@offset
end
getSettings() click to toggle source
# File lib/prayertimes.rb, line 141
def getSettings
        return @@settings
end
getTimes(date, coords, timezone, dst = 0, format = nil) click to toggle source

return prayer times for a given date

# File lib/prayertimes.rb, line 154
def getTimes(date, coords, timezone, dst = 0, format = nil)
        @lat = coords[0]
        @lng = coords[1]
        @elv =  coords.length >2 ? coords[2] : 0

        if format != nil
                @@timeFormat = format
        end

        if Date.parse(date)
                date = Date.parse(date)
                date = [date.year, date.month, date.day]
        end

        @timeZone = timezone + (dst ? 1 : 0)
        @jDate = self.julian(date[0], date[1], date[2]) - @lng / (15 * 24.0)
        return self.computeTimes
end
isMin(arg) click to toggle source

detect if input contains 'min'

# File lib/prayertimes.rb, line 414
def isMin(arg)
        return arg.to_s.include?('min')
end
julian(year, month, day) click to toggle source

convert Gregorian date to Julian day Ref: Astronomical Algorithms by Jean Meeus

# File lib/prayertimes.rb, line 247
def julian(year, month, day)
        if month <= 2
                year -= 1
                month += 12
        end
        a = (year / 100).floor
        b = 2 - a + (a / 4).floor
        return (365.25 * (year + 4716)).floor + (30.6001 * (month + 1)).floor + day + b - 1524.5
end
midDay(time) click to toggle source

compute mid-day time

# File lib/prayertimes.rb, line 200
def midDay(time)
        eqt = self.sunPosition(@jDate + time)[1]
        return self.fixhour(12 - eqt)
end
modifyFormats(times) click to toggle source

convert times to given time format

# File lib/prayertimes.rb, line 350
def modifyFormats(times)
        times.each do |name, value|
                times[name] = self.getFormattedTime(times[name], @@timeFormat)
        end
        return times
end
nightPortion(angle, night) click to toggle source

the night portion used for adjusting times in higher latitudes

# File lib/prayertimes.rb, line 379
def nightPortion(angle, night)
        method = @@settings['highLats']
        portion = 1/2.0  # midnight
        if method == 'AngleBased'
                portion = 1/60.0 * angle
        end
        if method == 'OneSeventh'
                portion = 1/7.0
        end
        return portion * night
end
riseSetAngle(elevation = 0) click to toggle source

return sun angle for sunset/sunrise

# File lib/prayertimes.rb, line 335
def riseSetAngle(elevation = 0)
        elevation =  elevation == nil ? 0 : elevation
        return 0.833 + 0.0347 * Math.sqrt(elevation) # an approximation
end
setMethod(method) click to toggle source
# File lib/prayertimes.rb, line 122
def setMethod(method)
        if @@methods[method]
                self.adjust(@@methods[method]["params"])
                @@calcMethod = method
        end
end
sin(d) click to toggle source
# File lib/prayertimes.rb, line 421
def sin(d) return Math.sin((d) * Math::PI / 180); end
sunAngleTime(angle, time, direction = nil) click to toggle source

compute the time at which sun reaches a specific angle below horizon

# File lib/prayertimes.rb, line 206
def sunAngleTime(angle, time, direction = nil)
        angle
        time
        begin
                decl = self.sunPosition(@jDate + time)[0]
                noon = self.midDay(time)
                t = 1/15.0* self.arccos((-self.sin(angle)- self.sin(decl)* self.sin(@lat))/ (self.cos(decl)* self.cos(@lat)))
                        
                return noon + (direction == 'ccw' ? -t  : t)
        rescue 
                return ('nan').to_f
        end
end
sunPosition(jd) click to toggle source

compute declination angle of sun and equation of time Ref: aa.usno.navy.mil/faq/docs/SunApprox.php

# File lib/prayertimes.rb, line 229
def sunPosition(jd)
        d = jd - 2451545.0
        g = self.fixangle(357.529 + 0.98560028* d)
        q = self.fixangle(280.459 + 0.98564736* d)
        l = self.fixangle(q + 1.915* self.sin(g) + 0.020* self.sin(2*g))

        r = 1.00014 - 0.01671*self.cos(g) - 0.00014*self.cos(2*g)
        e = 23.439 - 0.00000036* d

        ra = self.arctan2(self.cos(e)* self.sin(l), self.cos(l))/ 15.0
        eqt = q/15.0 - self.fixhour(ra)
        decl = self.arcsin(self.sin(e)* self.sin(l))

        return [decl, eqt]
end
tan(d) click to toggle source
# File lib/prayertimes.rb, line 423
def tan(d) return Math.tan((d) * Math::PI / 180); end
timeDiff(time1, time2) click to toggle source

compute the difference between two times

# File lib/prayertimes.rb, line 403
def timeDiff(time1, time2)
        return self.fixhour(time2- time1)
end
tune(timeOffsets) click to toggle source
# File lib/prayertimes.rb, line 133
def tune(timeOffsets)
        @@offset.update(timeOffsets)
end
tuneTimes(times) click to toggle source

apply offset to the times

# File lib/prayertimes.rb, line 341
def tuneTimes(times)
        times.each do |name, value|
                @@offset
                times[name] += @@offset[name] / 60.0
        end
        return times
end