Class: SolarEventCalculator
- Inherits:
-
Object
- Object
- SolarEventCalculator
- Defined in:
- lib/solareventcalculator.rb
Instance Method Summary collapse
- #compute_astronomical_sunrise(timezone) ⇒ Object
- #compute_astronomical_sunset(timezone) ⇒ Object
- #compute_civil_sunrise(timezone) ⇒ Object
- #compute_civil_sunset(timezone) ⇒ Object
- #compute_cosine_sun_declination(sinSunDeclination) ⇒ Object
- #compute_cosine_sun_local_hour(sunTrueLong, zenith) ⇒ Object
- #compute_lnghour ⇒ Object
- #compute_local_hour_angle(cosSunLocalHour, isSunrise) ⇒ Object
- #compute_local_mean_time(sunTrueLong, longHour, t, sunLocalHour) ⇒ Object
- #compute_longitude_hour(isSunrise) ⇒ Object
- #compute_nautical_sunrise(timezone) ⇒ Object
- #compute_nautical_sunset(timezone) ⇒ Object
- #compute_official_sunrise(timezone) ⇒ Object
- #compute_official_sunset(timezone) ⇒ Object
- #compute_right_ascension(sunTrueLong) ⇒ Object
- #compute_sin_sun_declination(sunTrueLong) ⇒ Object
- #compute_sun_mean_anomaly(longHour) ⇒ Object
- #compute_sun_true_longitude(meanAnomaly) ⇒ Object
- #compute_utc_astronomical_sunrise ⇒ Object
- #compute_utc_astronomical_sunset ⇒ Object
- #compute_utc_civil_sunrise ⇒ Object
- #compute_utc_civil_sunset ⇒ Object
- #compute_utc_nautical_sunrise ⇒ Object
- #compute_utc_nautical_sunset ⇒ Object
- #compute_utc_official_sunrise ⇒ Object
- #compute_utc_official_sunset ⇒ Object
- #compute_utc_solar_event(zenith, isSunrise) ⇒ Object
- #convert_to_datetime(time) ⇒ Object
- #degrees_as_rads(degrees) ⇒ Object
- #get_utc_offset(timezone) ⇒ Object
-
#initialize(date, latitude, longitude) ⇒ SolarEventCalculator
constructor
A new instance of SolarEventCalculator.
- #pad_minutes(minutes) ⇒ Object
- #put_in_range(number, lower, upper, adjuster) ⇒ Object
- #put_in_timezone(utcTime, timezone) ⇒ Object
- #put_ra_in_correct_quadrant(sunTrueLong) ⇒ Object
- #rads_as_degrees(radians) ⇒ Object
Constructor Details
#initialize(date, latitude, longitude) ⇒ SolarEventCalculator
Returns a new instance of SolarEventCalculator.
11 12 13 14 15 |
# File 'lib/solareventcalculator.rb', line 11 def initialize(date, latitude, longitude) @date = date @latitude = latitude @longitude = longitude end |
Instance Method Details
#compute_astronomical_sunrise(timezone) ⇒ Object
190 191 192 |
# File 'lib/solareventcalculator.rb', line 190 def compute_astronomical_sunrise(timezone) put_in_timezone(compute_utc_solar_event(108, true), timezone) end |
#compute_astronomical_sunset(timezone) ⇒ Object
194 195 196 |
# File 'lib/solareventcalculator.rb', line 194 def compute_astronomical_sunset(timezone) put_in_timezone(compute_utc_solar_event(108, false), timezone) end |
#compute_civil_sunrise(timezone) ⇒ Object
166 167 168 |
# File 'lib/solareventcalculator.rb', line 166 def compute_civil_sunrise(timezone) put_in_timezone(compute_utc_solar_event(96, true), timezone) end |
#compute_civil_sunset(timezone) ⇒ Object
170 171 172 |
# File 'lib/solareventcalculator.rb', line 170 def compute_civil_sunset(timezone) put_in_timezone(compute_utc_solar_event(96, false), timezone) end |
#compute_cosine_sun_declination(sinSunDeclination) ⇒ Object
67 68 69 70 |
# File 'lib/solareventcalculator.rb', line 67 def compute_cosine_sun_declination(sinSunDeclination) cosDec = BigDecimal.new(Math.cos(Math.asin(sinSunDeclination)).to_s) cosDec.round(4) end |
#compute_cosine_sun_local_hour(sunTrueLong, zenith) ⇒ Object
72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/solareventcalculator.rb', line 72 def compute_cosine_sun_local_hour(sunTrueLong, zenith) cosZenith = BigDecimal.new(Math.cos(degrees_as_rads(BigDecimal.new(zenith.to_s))).to_s) sinLatitude = BigDecimal.new(Math.sin(degrees_as_rads(@latitude)).to_s) cosLatitude = BigDecimal.new(Math.cos(degrees_as_rads(@latitude)).to_s) sinSunDeclination = compute_sin_sun_declination(sunTrueLong) top = cosZenith - (sinSunDeclination * sinLatitude) bottom = compute_cosine_sun_declination(sinSunDeclination) * cosLatitude cosLocalHour = top / bottom cosLocalHour.round(4) end |
#compute_lnghour ⇒ Object
17 18 19 20 |
# File 'lib/solareventcalculator.rb', line 17 def compute_lnghour lngHour = @longitude / BigDecimal.new("15") lngHour.round(4) end |
#compute_local_hour_angle(cosSunLocalHour, isSunrise) ⇒ Object
85 86 87 88 89 90 91 92 |
# File 'lib/solareventcalculator.rb', line 85 def compute_local_hour_angle(cosSunLocalHour, isSunrise) acosH = BigDecimal.new(Math.acos(cosSunLocalHour).to_s) acosHDegrees = rads_as_degrees(acosH) localHourAngle = (isSunrise) ? BigDecimal.new("360") - acosHDegrees : acosHDegrees localHourAngle = localHourAngle / BigDecimal.new("15") localHourAngle.round(4) end |
#compute_local_mean_time(sunTrueLong, longHour, t, sunLocalHour) ⇒ Object
94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/solareventcalculator.rb', line 94 def compute_local_mean_time(sunTrueLong, longHour, t, sunLocalHour) h = sunLocalHour ra = put_ra_in_correct_quadrant(sunTrueLong) parens = BigDecimal.new("0.06571") * t time = h + ra - parens - BigDecimal.new("6.622") utcTime = time - longHour utcTime = put_in_range(utcTime, 0, 24, 24) utcTime.round(4) end |
#compute_longitude_hour(isSunrise) ⇒ Object
22 23 24 25 26 |
# File 'lib/solareventcalculator.rb', line 22 def compute_longitude_hour(isSunrise) minuend = (isSunrise) ? BigDecimal.new("6") : BigDecimal.new("18") longHour = @date.yday + ((minuend - compute_lnghour) / BigDecimal.new("24")) longHour.round(4) end |
#compute_nautical_sunrise(timezone) ⇒ Object
182 183 184 |
# File 'lib/solareventcalculator.rb', line 182 def compute_nautical_sunrise(timezone) put_in_timezone(compute_utc_solar_event(102, true), timezone) end |
#compute_nautical_sunset(timezone) ⇒ Object
186 187 188 |
# File 'lib/solareventcalculator.rb', line 186 def compute_nautical_sunset(timezone) put_in_timezone(compute_utc_solar_event(102, false), timezone) end |
#compute_official_sunrise(timezone) ⇒ Object
174 175 176 |
# File 'lib/solareventcalculator.rb', line 174 def compute_official_sunrise(timezone) put_in_timezone(compute_utc_solar_event(90.8333, true), timezone) end |
#compute_official_sunset(timezone) ⇒ Object
178 179 180 |
# File 'lib/solareventcalculator.rb', line 178 def compute_official_sunset(timezone) put_in_timezone(compute_utc_solar_event(90.8333, false), timezone) end |
#compute_right_ascension(sunTrueLong) ⇒ Object
44 45 46 47 48 49 50 |
# File 'lib/solareventcalculator.rb', line 44 def compute_right_ascension(sunTrueLong) tanL = BigDecimal.new(Math.tan(degrees_as_rads(sunTrueLong).to_f).to_s) ra = rads_as_degrees(BigDecimal.new(Math.atan(BigDecimal.new("0.91764") * tanL).to_s)) ra = put_in_range(ra, 0, 360, 360) ra.round(4) end |
#compute_sin_sun_declination(sunTrueLong) ⇒ Object
61 62 63 64 65 |
# File 'lib/solareventcalculator.rb', line 61 def compute_sin_sun_declination(sunTrueLong) sinL = BigDecimal.new(Math.sin(degrees_as_rads(sunTrueLong).to_f).to_s) sinDec = sinL * BigDecimal.new("0.39782") sinDec.round(4) end |
#compute_sun_mean_anomaly(longHour) ⇒ Object
28 29 30 31 |
# File 'lib/solareventcalculator.rb', line 28 def compute_sun_mean_anomaly(longHour) constant = BigDecimal.new("0.9856") ((longHour * constant) - BigDecimal.new("3.289")).round(4) end |
#compute_sun_true_longitude(meanAnomaly) ⇒ Object
33 34 35 36 37 38 39 40 41 42 |
# File 'lib/solareventcalculator.rb', line 33 def compute_sun_true_longitude(meanAnomaly) mAsRads = degrees_as_rads(meanAnomaly) sinM = BigDecimal.new(Math.sin(mAsRads.to_f).to_s) sinTwoM = BigDecimal.new(Math.sin((2 * mAsRads).to_f).to_s) firstParens = BigDecimal.new("1.916") * sinM secondParens = BigDecimal.new("0.020") * sinTwoM trueLong = meanAnomaly + firstParens + secondParens + BigDecimal.new("282.634") trueLong = put_in_range(trueLong, 0, 360, 360) trueLong.round(4) end |
#compute_utc_astronomical_sunrise ⇒ Object
154 155 156 |
# File 'lib/solareventcalculator.rb', line 154 def compute_utc_astronomical_sunrise convert_to_datetime(compute_utc_solar_event(108, true)) end |
#compute_utc_astronomical_sunset ⇒ Object
158 159 160 |
# File 'lib/solareventcalculator.rb', line 158 def compute_utc_astronomical_sunset convert_to_datetime(compute_utc_solar_event(108, false)) end |
#compute_utc_civil_sunrise ⇒ Object
130 131 132 |
# File 'lib/solareventcalculator.rb', line 130 def compute_utc_civil_sunrise convert_to_datetime(compute_utc_solar_event(96, true)) end |
#compute_utc_civil_sunset ⇒ Object
134 135 136 |
# File 'lib/solareventcalculator.rb', line 134 def compute_utc_civil_sunset convert_to_datetime(compute_utc_solar_event(96, false)) end |
#compute_utc_nautical_sunrise ⇒ Object
146 147 148 |
# File 'lib/solareventcalculator.rb', line 146 def compute_utc_nautical_sunrise convert_to_datetime(compute_utc_solar_event(102, true)) end |
#compute_utc_nautical_sunset ⇒ Object
150 151 152 |
# File 'lib/solareventcalculator.rb', line 150 def compute_utc_nautical_sunset convert_to_datetime(compute_utc_solar_event(102, false)) end |
#compute_utc_official_sunrise ⇒ Object
138 139 140 |
# File 'lib/solareventcalculator.rb', line 138 def compute_utc_official_sunrise convert_to_datetime(compute_utc_solar_event(90.8333, true)) end |
#compute_utc_official_sunset ⇒ Object
142 143 144 |
# File 'lib/solareventcalculator.rb', line 142 def compute_utc_official_sunset convert_to_datetime(compute_utc_solar_event(90.8333, false)) end |
#compute_utc_solar_event(zenith, isSunrise) ⇒ Object
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
# File 'lib/solareventcalculator.rb', line 106 def compute_utc_solar_event(zenith, isSunrise) longHour = compute_lnghour eventLongHour = compute_longitude_hour(isSunrise) meanAnomaly = compute_sun_mean_anomaly(eventLongHour) sunTrueLong = compute_sun_true_longitude(meanAnomaly) cosineSunLocalHour = compute_cosine_sun_local_hour(sunTrueLong, zenith) if(cosineSunLocalHour > BigDecimal.new("1") || cosineSunLocalHour < BigDecimal.new("-1")) return nil end sunLocalHour = compute_local_hour_angle(cosineSunLocalHour, isSunrise) localMeanTime = compute_local_mean_time(sunTrueLong, longHour, eventLongHour, sunLocalHour) timeParts = localMeanTime.to_f.to_s.split('.') mins = BigDecimal.new("." + timeParts[1]) * BigDecimal.new("60") mins = mins.truncate() mins = pad_minutes(mins.to_i) hours = timeParts[0] Time.utc(@date.year, @date.mon, @date.mday, hours, pad_minutes(mins.to_i)) end |
#convert_to_datetime(time) ⇒ Object
162 163 164 |
# File 'lib/solareventcalculator.rb', line 162 def convert_to_datetime(time) DateTime.parse("#{@date.strftime}T#{time.hour}:#{time.min}:00+0000") unless time == nil end |
#degrees_as_rads(degrees) ⇒ Object
236 237 238 239 240 |
# File 'lib/solareventcalculator.rb', line 236 def degrees_as_rads(degrees) pi = BigDecimal(Math::PI.to_s) radian = pi / BigDecimal.new("180") degrees * radian end |
#get_utc_offset(timezone) ⇒ Object
212 213 214 215 216 |
# File 'lib/solareventcalculator.rb', line 212 def get_utc_offset(timezone) tz = TZInfo::Timezone.get(timezone) noonUTC = Time.gm(@date.year, @date.mon, @date.mday, 12, 0) tz.utc_to_local(noonUTC) - noonUTC end |
#pad_minutes(minutes) ⇒ Object
218 219 220 221 222 223 224 |
# File 'lib/solareventcalculator.rb', line 218 def pad_minutes(minutes) if(minutes < 10) "0" + minutes.to_s else minutes end end |
#put_in_range(number, lower, upper, adjuster) ⇒ Object
226 227 228 229 230 231 232 233 234 |
# File 'lib/solareventcalculator.rb', line 226 def put_in_range(number, lower, upper, adjuster) if number > upper then number -= adjuster elsif number < lower then number += adjuster else number end end |
#put_in_timezone(utcTime, timezone) ⇒ Object
198 199 200 201 202 203 204 205 206 207 208 209 210 |
# File 'lib/solareventcalculator.rb', line 198 def put_in_timezone(utcTime, timezone) tz = TZInfo::Timezone.get(timezone) # puts "UTCTime #{utcTime}" local = utcTime + get_utc_offset(timezone) # puts "LocalTime #{local}" offset = (get_utc_offset(timezone) / 60 / 60).to_i offset = (offset > 0) ? "+" + offset.to_s : offset.to_s timeInZone = DateTime.parse("#{@date.strftime}T#{local.strftime('%H:%M:%S')}#{offset}") # puts "CALC:timeInZone #{timeInZone}" timeInZone end |
#put_ra_in_correct_quadrant(sunTrueLong) ⇒ Object
52 53 54 55 56 57 58 59 |
# File 'lib/solareventcalculator.rb', line 52 def put_ra_in_correct_quadrant(sunTrueLong) lQuadrant = BigDecimal.new("90") * (sunTrueLong / BigDecimal.new("90")).floor raQuadrant = BigDecimal.new("90") * (compute_right_ascension(sunTrueLong) / BigDecimal.new("90")).floor ra = compute_right_ascension(sunTrueLong) + (lQuadrant - raQuadrant) ra = ra / BigDecimal.new("15") ra.round(4) end |
#rads_as_degrees(radians) ⇒ Object
242 243 244 245 246 |
# File 'lib/solareventcalculator.rb', line 242 def rads_as_degrees(radians) pi = BigDecimal(Math::PI.to_s) degree = BigDecimal.new("180") / pi radians * degree end |