Module: Sun
- Defined in:
- lib/sun.rb,
lib/sun/version.rb
Defined Under Namespace
Classes: Error, InvalidCoordinates, InvalidTime
Constant Summary
collapse
- SOLAR_ZENITH =
The approximate correction for atmospheric refraction at sunrise and sunset
90.833
- JULIAN_CONSTANT =
2000-01-01 12:00:00 UTC in Julian days
2451545.to_r
- VERSION =
"1.0.1"
Class Method Summary
collapse
-
.apparent_longitude(julian_century) ⇒ Object
-
.date(time) ⇒ Object
-
.date_at_time(date, minutes) ⇒ Object
-
.date_to_unix_time(date) ⇒ Object
-
.declination(oblique_correction, julian_century) ⇒ Object
-
.degrees(radians) ⇒ Object
-
.eccentricity_of_earth_orbit(julian_century) ⇒ Object
-
.equation_of_center(julian_century) ⇒ Object
-
.equation_of_time(date, longitude) ⇒ Object
-
.geometric_mean_anomoly(julian_century) ⇒ Object
-
.geometric_mean_longitude(julian_century) ⇒ Object
-
.hour_angle(date, latitude) ⇒ Object
-
.julian_century(time) ⇒ Object
-
.julian_days(time) ⇒ Object
-
.mean_obliquity_of_ecliptic(julian_century) ⇒ Object
-
.oblique_correction(julian_century) ⇒ Object
-
.offset_multiplier(type) ⇒ Object
-
.radians(degrees) ⇒ Object
-
.solar_noon(time, latitude, longitude) ⇒ Object
-
.solar_noon_minutes(time, latitude, longitude) ⇒ Object
-
.sun_time(type, time, latitude, longitude) ⇒ Object
Base our calculations off the astronomical julian date for our input time.
-
.sun_time_minutes(type, time, latitude, longitude) ⇒ Object
-
.sunrise(time, latitude, longitude) ⇒ Object
-
.sunrise_minutes(time, latitude, longitude) ⇒ Object
Sun times in minutes after midnight (UTC).
-
.sunset(time, latitude, longitude) ⇒ Object
-
.sunset_minutes(time, latitude, longitude) ⇒ Object
-
.true_longitude(julian_century) ⇒ Object
-
.y(oblique_correction) ⇒ Object
Class Method Details
.apparent_longitude(julian_century) ⇒ Object
151
152
153
|
# File 'lib/sun.rb', line 151
def self.apparent_longitude(julian_century)
true_longitude(julian_century) - 0.00569 - 0.00478 * Math.sin(radians(125.04 - 1934.136 * julian_century))
end
|
.date(time) ⇒ Object
50
51
52
53
54
55
56
57
|
# File 'lib/sun.rb', line 50
def self.date(time)
case time
when Date then time
when Time then time.to_date
else
raise InvalidTime, "must pass a Date or Time object"
end
end
|
.date_at_time(date, minutes) ⇒ Object
71
72
73
|
# File 'lib/sun.rb', line 71
def self.date_at_time(date, minutes)
Time.at(date_to_unix_time(date) + minutes * 60)
end
|
.date_to_unix_time(date) ⇒ Object
67
68
69
|
# File 'lib/sun.rb', line 67
def self.date_to_unix_time(date)
Time.utc(date.year, date.month, date.day).to_i
end
|
.declination(oblique_correction, julian_century) ⇒ Object
155
156
157
|
# File 'lib/sun.rb', line 155
def self.declination(oblique_correction, julian_century)
degrees(Math.asin(Math.sin(radians(oblique_correction)) * Math.sin(radians(apparent_longitude(julian_century)))))
end
|
.degrees(radians) ⇒ Object
59
60
61
|
# File 'lib/sun.rb', line 59
def self.degrees(radians)
Rational(180 * radians, Math::PI)
end
|
.eccentricity_of_earth_orbit(julian_century) ⇒ Object
138
139
140
|
# File 'lib/sun.rb', line 138
def self.eccentricity_of_earth_orbit(julian_century)
0.016708634 - julian_century * (0.000042037 + 0.0000001267 * julian_century)
end
|
.equation_of_center(julian_century) ⇒ Object
142
143
144
145
|
# File 'lib/sun.rb', line 142
def self.equation_of_center(julian_century)
geometric_mean_anomoly = geometric_mean_anomoly(julian_century)
Math.sin(radians(geometric_mean_anomoly)) * (1.914602 - julian_century * (0.004817 + 0.000014 * julian_century)) + Math.sin(radians(2 * geometric_mean_anomoly)) * (0.019993 - 0.000101 * julian_century) + Math.sin(radians(3 * geometric_mean_anomoly)) * 0.00028
end
|
.equation_of_time(date, longitude) ⇒ Object
159
160
161
162
163
164
165
166
167
|
# File 'lib/sun.rb', line 159
def self.equation_of_time(date, longitude)
julian_century = julian_century(date)
oblique_correction = oblique_correction(julian_century)
geometric_mean_anomoly = geometric_mean_anomoly(julian_century)
geometric_mean_longitude = geometric_mean_longitude(julian_century)
eccentricity_of_earth_orbit = eccentricity_of_earth_orbit(julian_century)
y = y(oblique_correction)
4 * degrees(y * Math.sin(2 * radians(geometric_mean_longitude)) - 2 * eccentricity_of_earth_orbit * Math.sin(radians(geometric_mean_anomoly)) + 4 * eccentricity_of_earth_orbit * y * Math.sin(radians(geometric_mean_anomoly)) * Math.cos(2 * radians(geometric_mean_longitude)) - 0.5 * y * y * Math.sin(4 * radians(geometric_mean_longitude)) - 1.25 * eccentricity_of_earth_orbit * eccentricity_of_earth_orbit * Math.sin(2 * radians(geometric_mean_anomoly)))
end
|
.geometric_mean_anomoly(julian_century) ⇒ Object
126
127
128
|
# File 'lib/sun.rb', line 126
def self.geometric_mean_anomoly(julian_century)
357.52911 + julian_century * (35999.05029 - 0.0001537 * julian_century)
end
|
.geometric_mean_longitude(julian_century) ⇒ Object
130
131
132
|
# File 'lib/sun.rb', line 130
def self.geometric_mean_longitude(julian_century)
(280.46646 + julian_century * (36000.76983 + julian_century * 0.0003032)) % 360
end
|
.hour_angle(date, latitude) ⇒ Object
169
170
171
172
173
174
175
|
# File 'lib/sun.rb', line 169
def self.hour_angle(date, latitude)
julian_century = julian_century(date)
oblique_correction = oblique_correction(julian_century)
declination = declination(oblique_correction, julian_century)
res = Math.cos(radians(SOLAR_ZENITH)) / (Math.cos(radians(latitude)) * Math.cos(radians(declination))) - Math.tan(radians(latitude)) * Math.tan(radians(declination))
degrees(Math.acos(res))
end
|
.julian_century(time) ⇒ Object
114
115
116
|
# File 'lib/sun.rb', line 114
def self.julian_century(time)
(julian_days(time) - JULIAN_CONSTANT) / 36525
end
|
.julian_days(time) ⇒ Object
106
107
108
109
110
111
112
|
# File 'lib/sun.rb', line 106
def self.julian_days(time)
if time.is_a?(Time)
time.to_datetime.ajd
else
date(time).ajd
end
end
|
.mean_obliquity_of_ecliptic(julian_century) ⇒ Object
118
119
120
|
# File 'lib/sun.rb', line 118
def self.mean_obliquity_of_ecliptic(julian_century)
23 + (26 + ((21.448 - julian_century * (46.815 + julian_century * (0.00059 - julian_century * 0.001813)))) / 60) / 60
end
|
.oblique_correction(julian_century) ⇒ Object
122
123
124
|
# File 'lib/sun.rb', line 122
def self.oblique_correction(julian_century)
mean_obliquity_of_ecliptic(julian_century) + 0.00256 * Math.cos(radians(125.04 - 1934.136 * julian_century))
end
|
.offset_multiplier(type) ⇒ Object
96
97
98
99
100
101
102
|
# File 'lib/sun.rb', line 96
def self.offset_multiplier(type)
case type
when :sunrise then -1
when :solar_noon then 0
when :sunset then 1
end
end
|
.radians(degrees) ⇒ Object
63
64
65
|
# File 'lib/sun.rb', line 63
def self.radians(degrees)
Rational(Math::PI * degrees, 180)
end
|
.solar_noon(time, latitude, longitude) ⇒ Object
26
27
28
|
# File 'lib/sun.rb', line 26
def self.solar_noon(time, latitude, longitude)
sun_time(:solar_noon, time, latitude, longitude)
end
|
.solar_noon_minutes(time, latitude, longitude) ⇒ Object
40
41
42
|
# File 'lib/sun.rb', line 40
def self.solar_noon_minutes(time, latitude, longitude)
sun_time_minutes(:solar_noon, time, latitude, longitude)
end
|
.sun_time(type, time, latitude, longitude) ⇒ Object
Base our calculations off the astronomical julian date for our input time. Our formula is sensitive to time of day, so we ignore it in order to give consistent results for any time on the same date.
78
79
80
81
82
|
# File 'lib/sun.rb', line 78
def self.sun_time(type, time, latitude, longitude)
date = date(time)
minutes = sun_time_minutes(type, date, latitude, longitude)
date_at_time(date, minutes)
end
|
.sun_time_minutes(type, time, latitude, longitude) ⇒ Object
84
85
86
87
88
89
90
91
92
93
94
|
# File 'lib/sun.rb', line 84
def self.sun_time_minutes(type, time, latitude, longitude)
date = date(time)
if offset_multiplier(type) == 0
offset = 0
else
offset = offset_multiplier(type) * 4 * hour_angle(date, latitude)
end
720 - (4 * longitude) - equation_of_time(date, longitude) + offset
rescue Math::DomainError
raise InvalidCoordinates, "Could not determine sun times for coordinates: #{latitude}, #{longitude}"
end
|
.sunrise(time, latitude, longitude) ⇒ Object
22
23
24
|
# File 'lib/sun.rb', line 22
def self.sunrise(time, latitude, longitude)
sun_time(:sunrise, time, latitude, longitude)
end
|
.sunrise_minutes(time, latitude, longitude) ⇒ Object
Sun times in minutes after midnight (UTC)
36
37
38
|
# File 'lib/sun.rb', line 36
def self.sunrise_minutes(time, latitude, longitude)
sun_time_minutes(:sunrise, time, latitude, longitude)
end
|
.sunset(time, latitude, longitude) ⇒ Object
30
31
32
|
# File 'lib/sun.rb', line 30
def self.sunset(time, latitude, longitude)
sun_time(:sunset, time, latitude, longitude)
end
|
.sunset_minutes(time, latitude, longitude) ⇒ Object
44
45
46
|
# File 'lib/sun.rb', line 44
def self.sunset_minutes(time, latitude, longitude)
sun_time_minutes(:sunset, time, latitude, longitude)
end
|
.true_longitude(julian_century) ⇒ Object
147
148
149
|
# File 'lib/sun.rb', line 147
def self.true_longitude(julian_century)
geometric_mean_longitude(julian_century) + equation_of_center(julian_century)
end
|
.y(oblique_correction) ⇒ Object
134
135
136
|
# File 'lib/sun.rb', line 134
def self.y(oblique_correction)
Math.tan(radians(Rational(oblique_correction, 2))) * Math.tan(radians(Rational(oblique_correction, 2)))
end
|