sunriseset 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gemtest +0 -0
- data/History.txt +2 -0
- data/Manifest.txt +6 -0
- data/README.md +83 -0
- data/Rakefile +16 -0
- data/lib/sunriseset.rb +525 -0
- data/test/manualtest.rb +6 -0
- metadata +97 -0
data/.gemtest
ADDED
File without changes
|
data/History.txt
ADDED
data/Manifest.txt
ADDED
data/README.md
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
# sunriseset
|
2
|
+
|
3
|
+
* http://rbur004.github.com/sunriseset/
|
4
|
+
* Source https://github.com/rbur004/sunriseset
|
5
|
+
* Gem https://rubygems.org/gems/sunriseset
|
6
|
+
|
7
|
+
## DESCRIPTION:
|
8
|
+
|
9
|
+
SunRiseSet is a ruby class calculates the times of the sunrise, solar noon and sunset.
|
10
|
+
It also calculates astronomical, naval and civil twilight times.
|
11
|
+
|
12
|
+
Not sure of the origin of the algorithm.
|
13
|
+
I have seen a fortran version http://www.srrb.noaa.gov/highlights/sunrise/program.txt
|
14
|
+
a .pl www.mso.anu.edu.au/~brian/grbs/astrosubs.pl and .vb versions for spreadsheets too.
|
15
|
+
All had the same comments, so are of a common origin.
|
16
|
+
|
17
|
+
## FEATURES/PROBLEMS:
|
18
|
+
|
19
|
+
|
20
|
+
|
21
|
+
## SYNOPSIS:
|
22
|
+
|
23
|
+
require 'rubygems'
|
24
|
+
require 'sunriseset'
|
25
|
+
|
26
|
+
latitude = -36.991
|
27
|
+
longitude = 174.487
|
28
|
+
vc = SunRiseSet.today(latitude,longitude) #Alternately vc = SunRiseSet.now(latitude,longitude)
|
29
|
+
#Or for a Given DateTime
|
30
|
+
vc = SunRiseSet.new(DateTime.now, latitude,longitude)
|
31
|
+
vc.to_s #or access individual attributes and use DateTime#strftime to format appropriately
|
32
|
+
|
33
|
+
## REQUIREMENTS:
|
34
|
+
|
35
|
+
* require 'rubygems'
|
36
|
+
* require 'date'
|
37
|
+
|
38
|
+
## INSTALL:
|
39
|
+
|
40
|
+
* sudo gem install versioncheck
|
41
|
+
|
42
|
+
## LICENSE:
|
43
|
+
|
44
|
+
(The MIT License)
|
45
|
+
|
46
|
+
Copyright (c) 2013
|
47
|
+
|
48
|
+
1. You may make and give away verbatim copies of the source form of the
|
49
|
+
software without restriction, provided that you duplicate all of the
|
50
|
+
original copyright notices and associated disclaimers.
|
51
|
+
|
52
|
+
2. You may modify your copy of the software in any way, provided that
|
53
|
+
you do at least ONE of the following:
|
54
|
+
* place your modifications in the Public Domain or otherwise make them Freely Available, such as by posting said modifications to Usenet or an equivalent medium, or by allowing the author to include your modifications in the software.
|
55
|
+
* use the modified software only within your corporation or organization.
|
56
|
+
* rename any non-standard executables so the names do not conflict with standard executables, which must also be provided.
|
57
|
+
* make other distribution arrangements with the author.
|
58
|
+
|
59
|
+
3. You may distribute the software in object code or executable form, provided that you do at least ONE of the following:
|
60
|
+
* distribute the executables and library files of the software,
|
61
|
+
together with instructions (in the manual page or equivalent)
|
62
|
+
on where to get the original distribution.
|
63
|
+
* accompany the distribution with the machine-readable source of
|
64
|
+
the software.
|
65
|
+
* give non-standard executables non-standard names, with
|
66
|
+
instructions on where to get the original software distribution.
|
67
|
+
* make other distribution arrangements with the author.
|
68
|
+
|
69
|
+
4. You may modify and include the part of the software into any other
|
70
|
+
software (possibly commercial). But some files or libraries used by
|
71
|
+
code in this distribution may not written by the author, so that they
|
72
|
+
are not under these terms.
|
73
|
+
|
74
|
+
5. The scripts and library files supplied as input to or produced as
|
75
|
+
output from the software do not automatically fall under the
|
76
|
+
copyright of the software, but belong to whomever generated them,
|
77
|
+
and may be sold commercially, and may be aggregated with this
|
78
|
+
software.
|
79
|
+
|
80
|
+
6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
|
81
|
+
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
82
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
83
|
+
PURPOSE.
|
data/Rakefile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# -*- ruby -*-
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
require 'hoe'
|
6
|
+
#require 'lib/sunriseset.rb'
|
7
|
+
Hoe.plugin :yard
|
8
|
+
|
9
|
+
Hoe.spec 'sunriseset' do
|
10
|
+
self.rubyforge_name = "sunriseset"
|
11
|
+
self.developer( "Rob Burrowes","r.burrowes@auckland.ac.nz")
|
12
|
+
|
13
|
+
self.yard_title = 'SunRiseSet'
|
14
|
+
self.yard_options = ['--markup', 'markdown', '--protected']
|
15
|
+
end
|
16
|
+
|
data/lib/sunriseset.rb
ADDED
@@ -0,0 +1,525 @@
|
|
1
|
+
require 'date'
|
2
|
+
|
3
|
+
#Calculates the sun rise and sunset times, with civil, naval and astronomical twilight values.
|
4
|
+
#Not sure of the origin of the code.
|
5
|
+
#I have seen a fortran version http://www.srrb.noaa.gov/highlights/sunrise/program.txt
|
6
|
+
#a .pl www.mso.anu.edu.au/~brian/grbs/astrosubs.pl
|
7
|
+
#and .vb versions too.
|
8
|
+
#All had the same comments, so are of a common origin.
|
9
|
+
class SunRiseSet
|
10
|
+
VERSION = '0.9.0'
|
11
|
+
|
12
|
+
#because I live here
|
13
|
+
LATITUDE_DEFAULT= -(36.0 + 59.0/60.0 + 27.60/3600)
|
14
|
+
LONGITUDE_DEFAULT= (174.0 + 29/60.0 + 13.20/3600)
|
15
|
+
|
16
|
+
#In degrees from the Zenith. Represents the Time when we turn car lights on and off
|
17
|
+
CIVIL_TWILIGHT=96
|
18
|
+
#In degrees from the Zenith. Represents the Time when we can see the first light (dawn)
|
19
|
+
NAVAL_TWILIGHT=102
|
20
|
+
#In degrees from the Zenith. Represents the Time when the sun is not interfering with viewing distant stars.
|
21
|
+
ASTRO_TWILIGHT=108
|
22
|
+
#0.833 is allowing for the bending in the atmosphere.
|
23
|
+
SUN_RISE_SET=90.833
|
24
|
+
|
25
|
+
# @return [DateTime] Naval Twilight begins (Sun is begining to lighten the sky )
|
26
|
+
attr_reader :astroTwilightStart
|
27
|
+
# @return [DateTime] Naval Twilight begins
|
28
|
+
attr_reader :navalTwilightStart
|
29
|
+
# @return [DateTime] Civil Twilight begins
|
30
|
+
attr_reader :civilTwilightStart
|
31
|
+
# @return [DateTime] Sun rise
|
32
|
+
attr_reader :sunrise
|
33
|
+
|
34
|
+
# @return [DateTime] Sun set
|
35
|
+
attr_reader :sunset
|
36
|
+
# @return [DateTime] End of Civil Twilight
|
37
|
+
attr_reader :civilTwilightEnd
|
38
|
+
# @return [DateTime] end of naval twilight
|
39
|
+
attr_reader :navalTwilightEnd
|
40
|
+
# @return [DateTime] end of astronomical twilight (sky is now fully dark)
|
41
|
+
attr_reader :astroTwilightEnd
|
42
|
+
|
43
|
+
# @return [DateTime] Sun is at the midpoint for today (varies throughout the year)
|
44
|
+
attr_reader :solNoon
|
45
|
+
|
46
|
+
|
47
|
+
# @return [SunRiseSet] Constructor for any datetime and location
|
48
|
+
# @param [DateTime, #jd, #offset] datetime
|
49
|
+
# @param [Float] latitude
|
50
|
+
# @param [Float] longitude
|
51
|
+
def initialize(datetime, latitude=LATITUDE_DEFAULT, longitude=LONGITUDE_DEFAULT)
|
52
|
+
@latitude, @longitude = latitude, longitude
|
53
|
+
@julian_date = DateTime.jd(datetime.jd.to_f)
|
54
|
+
@julian_day = @julian_date.jd.to_f #Shorthand for later use, where we want this value as a float.
|
55
|
+
@zone = datetime.offset #datetime.utc_offset/86400 #time zone offset + daylight savings as a fraction of a day
|
56
|
+
calcSun
|
57
|
+
end
|
58
|
+
|
59
|
+
# @return [SunRiseSet] Constructor for date == today, at location specified
|
60
|
+
# @param [Float] latitude
|
61
|
+
# @param [Float] longitude
|
62
|
+
def self.today(latitude=LATITUDE_DEFAULT, longitude=LONGITUDE_DEFAULT)
|
63
|
+
self.new(DateTime.now, latitude, longitude)
|
64
|
+
end
|
65
|
+
|
66
|
+
# @return [SunRiseSet] Constructor for date == today, at location specified
|
67
|
+
# @param [Float] latitude
|
68
|
+
# @param [Float] longitude
|
69
|
+
def self.now(latitude=LATITUDE_DEFAULT, longitude=LONGITUDE_DEFAULT)
|
70
|
+
self.new(DateTime.now, latitude, longitude)
|
71
|
+
end
|
72
|
+
|
73
|
+
# @return [String] dumps key attributes as a multiline string
|
74
|
+
def to_s
|
75
|
+
"Astro Twilight #{@astroTwilightStart.strftime('%H:%M:%S %d-%m')}\n" +
|
76
|
+
"Naval Twilight #{@navalTwilightStart.strftime('%H:%M:%S %d-%m')}\n" +
|
77
|
+
"Civil Twilight #{@civilTwilightStart.strftime('%H:%M:%S %d-%m')}\n" +
|
78
|
+
"Sun Rises #{@sunrise.strftime('%H:%M:%S %d-%m')}\n" +
|
79
|
+
"Solar noon #{@solNoon.strftime('%H:%M:%S %Z %d-%m')}\n" +
|
80
|
+
"Sun Sets #{@sunset.strftime('%H:%M:%S %d-%m')}\n" +
|
81
|
+
"End of Civil Twilight #{@civilTwilightEnd.strftime('%H:%M:%S %d-%m')}\n" +
|
82
|
+
"Naval Twilight #{@navalTwilightEnd.strftime('%H:%M:%S %d-%m')}\n" +
|
83
|
+
"Astro Twilight #{@astroTwilightEnd.strftime('%H:%M:%S %d-%m')}\n"
|
84
|
+
end
|
85
|
+
|
86
|
+
# @return [String] the constant VERSION
|
87
|
+
def version
|
88
|
+
VERSION
|
89
|
+
end
|
90
|
+
|
91
|
+
private
|
92
|
+
|
93
|
+
# calculate time of sunrise and sunset for the entered date
|
94
|
+
# and location. In the special cases near earth's poles,
|
95
|
+
# the date of nearest sunrise and set are reported.
|
96
|
+
# @return [nil] fills in class DateTime attributes
|
97
|
+
# :sunrise, :civilTwilightStart, :navalTwilightStart, :astroTwilightStart
|
98
|
+
# :sunset, :civilTwilightEnd, :navalTwilightEnd and :astroTwilightEnd
|
99
|
+
|
100
|
+
def calcSun
|
101
|
+
|
102
|
+
# Calculate sunrise for this date
|
103
|
+
# if no sunrise is found, set flag nosunrise
|
104
|
+
|
105
|
+
nosunrise = nosunset = false
|
106
|
+
begin
|
107
|
+
@sunrise = calcSunriseUTC(@julian_day)
|
108
|
+
@civilTwilightStart = calcSunriseUTC( @julian_day, CIVIL_TWILIGHT)
|
109
|
+
@navalTwilightStart = calcSunriseUTC( @julian_day, NAVAL_TWILIGHT)
|
110
|
+
@astroTwilightStart = calcSunriseUTC( @julian_day, ASTRO_TWILIGHT)
|
111
|
+
rescue Exception
|
112
|
+
@sunrise = @civilTwilightStart = @navalTwilightStart = @astroTwilightStart = nil
|
113
|
+
nosunrise = true
|
114
|
+
end
|
115
|
+
|
116
|
+
# Calculate sunset for this date
|
117
|
+
# if no sunrise is found, set flag nosunset
|
118
|
+
begin
|
119
|
+
@sunset = calcSunsetUTC(@julian_day)
|
120
|
+
@civilTwilightEnd = calcSunsetUTC( @julian_day, CIVIL_TWILIGHT)
|
121
|
+
@navalTwilightEnd = calcSunsetUTC( @julian_day, NAVAL_TWILIGHT)
|
122
|
+
@astroTwilightEnd = calcSunsetUTC( @julian_day, ASTRO_TWILIGHT)
|
123
|
+
rescue Exception
|
124
|
+
@sunset = @civilTwilightEnd = @navalTwilightEnd = @astroTwilightEnd = nil
|
125
|
+
nosunset = true
|
126
|
+
end
|
127
|
+
|
128
|
+
# Calculate solar noon for this date
|
129
|
+
t = calcTimeJulianCent( @julian_day )
|
130
|
+
|
131
|
+
@solNoon = to_datetime(@julian_day, calcSolNoonUTC(t))
|
132
|
+
|
133
|
+
# No sunrise or sunset found for today
|
134
|
+
doy = @julian_date.yday
|
135
|
+
if(nosunrise)
|
136
|
+
if ( ((@latitude > 66.4) && (doy > 79) && (doy < 267)) ||
|
137
|
+
((@latitude < -66.4) && ((doy < 83) || (doy > 263))) )
|
138
|
+
# if Northern hemisphere and spring or summer, OR
|
139
|
+
# if Southern hemisphere and fall or winter, use
|
140
|
+
# previous sunrise and next sunset
|
141
|
+
newjd = findRecentSunrise(@julian_day, @latitude, @longitude)
|
142
|
+
@sunrise = calcSunriseUTC(newjd) + @zone
|
143
|
+
elsif ( ((@latitude > 66.4) && ((doy < 83) || (doy > 263))) ||
|
144
|
+
((@latitude < -66.4) && (doy > 79) && (doy < 267)) )
|
145
|
+
# if Northern hemisphere and fall or winter, OR
|
146
|
+
# if Southern hemisphere and spring or summer, use
|
147
|
+
# next sunrise and previous sunset
|
148
|
+
newjd = findNextSunrise(@julian_day, @latitude, @longitude)
|
149
|
+
@sunrise = calcSunriseUTC(newjd) + @zone
|
150
|
+
else
|
151
|
+
raise("Cannot Find Sunrise!")
|
152
|
+
end
|
153
|
+
|
154
|
+
end
|
155
|
+
|
156
|
+
if(nosunset)
|
157
|
+
if ( ((@latitude > 66.4) && (doy > 79) && (doy < 267)) ||
|
158
|
+
((@latitude < -66.4) && ((doy < 83) || (doy > 263))) )
|
159
|
+
# if Northern hemisphere and spring or summer, OR
|
160
|
+
# if Southern hemisphere and fall or winter, use
|
161
|
+
# previous sunrise and next sunset
|
162
|
+
newjd = findNextSunset(@julian_day, @latitude, @longitude)
|
163
|
+
@sunset = calcSunsetUTC(newjd) + @zone
|
164
|
+
elsif ( ((@latitude > 66.4) && ((doy < 83) || (doy > 263))) ||
|
165
|
+
((@latitude < -66.4) && (doy > 79) && (doy < 267)) )
|
166
|
+
# if Northern hemisphere and fall or winter, OR
|
167
|
+
# if Southern hemisphere and spring or summer, use
|
168
|
+
# next sunrise and last sunset
|
169
|
+
newjd = findRecentSunset(@julian_day, @latitude, @longitude)
|
170
|
+
@sunset = calcSunsetUTC(newjd) + @zone
|
171
|
+
else
|
172
|
+
raise ("Cannot Find Sunset!")
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
# @param [Float] radian
|
178
|
+
# @return [Float] angle in degrees
|
179
|
+
def radToDeg(angleRad)
|
180
|
+
return (180.0 * angleRad / Math::PI)
|
181
|
+
end
|
182
|
+
|
183
|
+
# @param [Float] degrees
|
184
|
+
# @return [Float] angle in radians
|
185
|
+
def degToRad(angleDeg)
|
186
|
+
return (Math::PI * angleDeg / 180.0)
|
187
|
+
end
|
188
|
+
|
189
|
+
# convert Julian Day to centuries since J2000.0.
|
190
|
+
# @param [Float] julian_day Julian Day
|
191
|
+
# @return [Float] T value corresponding to the Julian Day
|
192
|
+
def calcTimeJulianCent(julian_day)
|
193
|
+
(julian_day - 2451545.0)/36525.0
|
194
|
+
end
|
195
|
+
|
196
|
+
# convert centuries since J2000.0 to Julian Day.
|
197
|
+
# @param [Float] t number of Julian centuries since J2000.0
|
198
|
+
# @return [Float] the Julian Day corresponding to the t value
|
199
|
+
def calcJDFromJulianCent(t)
|
200
|
+
t * 36525.0 + 2451545.0
|
201
|
+
end
|
202
|
+
|
203
|
+
# calculate the Geometric Mean Longitude of the Sun
|
204
|
+
# @param [Float] t number of Julian centuries since J2000.0
|
205
|
+
# @return [Float] the Geometric Mean Longitude of the Sun in degrees
|
206
|
+
def calcGeomMeanLongSun(t)
|
207
|
+
l0 = 280.46646 + t * (36000.76983 + 0.0003032 * t)
|
208
|
+
while(l0 > 360.0)
|
209
|
+
l0 -= 360.0
|
210
|
+
end
|
211
|
+
while(l0 < 0.0)
|
212
|
+
l0 += 360.0
|
213
|
+
end
|
214
|
+
return l0; # in degrees
|
215
|
+
end
|
216
|
+
|
217
|
+
# Calculate the Geometric Mean Anomaly of the Sun
|
218
|
+
# @param [Float] t number of Julian centuries since J2000.0
|
219
|
+
# @return [Float] the Geometric Mean Anomaly of the Sun in degrees
|
220
|
+
def calcGeomMeanAnomalySun(t)
|
221
|
+
357.52911 + t * (35999.05029 - 0.0001537 * t) #in degrees
|
222
|
+
end
|
223
|
+
|
224
|
+
# calculate the eccentricity of earth's orbit
|
225
|
+
# @param [Float] t number of Julian centuries since J2000.0
|
226
|
+
# @return [Float] the unitless eccentricity
|
227
|
+
def calcEccentricityEarthOrbit(t)
|
228
|
+
0.016708634 - t * (0.000042037 + 0.0000001267 * t) # unitless
|
229
|
+
end
|
230
|
+
|
231
|
+
# calculate the equation of center for the sun
|
232
|
+
# @param [Float] t number of Julian centuries since J2000.0
|
233
|
+
# @return [Float] in degrees
|
234
|
+
def calcSunEqOfCenter(t)
|
235
|
+
|
236
|
+
m = calcGeomMeanAnomalySun(t)
|
237
|
+
|
238
|
+
mrad = degToRad(m)
|
239
|
+
sinm = Math.sin(mrad)
|
240
|
+
sin2m = Math.sin(mrad+mrad)
|
241
|
+
sin3m = Math.sin(mrad+mrad+mrad)
|
242
|
+
|
243
|
+
sinm * (1.914602 - t * (0.004817 + 0.000014 * t)) + sin2m * (0.019993 - 0.000101 * t) + sin3m * 0.000289 # in degrees
|
244
|
+
end
|
245
|
+
|
246
|
+
# calculate the true longitude of the sun
|
247
|
+
# @param [Float] t number of Julian centuries since J2000.0
|
248
|
+
# @return [Float] sun's true longitude in degrees
|
249
|
+
def calcSunTrueLong(t)
|
250
|
+
calcGeomMeanLongSun(t) + calcSunEqOfCenter(t) # in degrees
|
251
|
+
end
|
252
|
+
|
253
|
+
# calculate the true anamoly of the sun
|
254
|
+
# @param [Float] t number of Julian centuries since J2000.0
|
255
|
+
# @return [Float] sun's true anamoly in degrees
|
256
|
+
def calcSunTrueAnomaly(t)
|
257
|
+
calcGeomMeanAnomalySun(t) + calcSunEqOfCenter(t) # in degrees
|
258
|
+
end
|
259
|
+
|
260
|
+
# calculate the distance to the sun in AU
|
261
|
+
# @param [Float] t number of Julian centuries since J2000.0
|
262
|
+
# @return [Float] sun radius vector in AUs
|
263
|
+
def calcSunRadVector(t)
|
264
|
+
v = calcSunTrueAnomaly(t)
|
265
|
+
e = calcEccentricityEarthOrbit(t)
|
266
|
+
|
267
|
+
(1.000001018 * (1 - e * e)) / (1 + e * Math.cos(degToRad(v))) # in AUs
|
268
|
+
end
|
269
|
+
|
270
|
+
# calculate the apparent longitude of the sun
|
271
|
+
# @param [Float] t number of Julian centuries since J2000.0
|
272
|
+
# @return [Float] sun's apparent longitude in degrees
|
273
|
+
def calcSunApparentLong(t)
|
274
|
+
o = calcSunTrueLong(t)
|
275
|
+
|
276
|
+
omega = 125.04 - 1934.136 * t
|
277
|
+
o - 0.00569 - 0.00478 * Math.sin(degToRad(omega)) # in degrees
|
278
|
+
end
|
279
|
+
|
280
|
+
# calculate the mean obliquity of the ecliptic
|
281
|
+
# @param [Float] t number of Julian centuries since J2000.0
|
282
|
+
# @return [Float] mean obliquity in degrees
|
283
|
+
def calcMeanObliquityOfEcliptic(t)
|
284
|
+
seconds = 21.448 - t*(46.8150 + t*(0.00059 - t*(0.001813)))
|
285
|
+
23.0 + (26.0 + (seconds/60.0))/60.0 # in degrees
|
286
|
+
end
|
287
|
+
|
288
|
+
# calculate the corrected obliquity of the ecliptic
|
289
|
+
# @param [Float] t number of Julian centuries since J2000.0
|
290
|
+
# @return [Float] corrected obliquity in degrees
|
291
|
+
def calcObliquityCorrection(t)
|
292
|
+
e0 = calcMeanObliquityOfEcliptic(t)
|
293
|
+
|
294
|
+
omega = 125.04 - 1934.136 * t
|
295
|
+
e0 + 0.00256 * Math.cos(degToRad(omega)) # in degrees
|
296
|
+
end
|
297
|
+
|
298
|
+
# calculate the right ascension of the sun
|
299
|
+
# @param [Float] t number of Julian centuries since J2000.0
|
300
|
+
# @return [Float] sun's right ascension in degrees
|
301
|
+
def calcSunRtAscension(t)
|
302
|
+
e = calcObliquityCorrection(t)
|
303
|
+
lambda = calcSunApparentLong(t)
|
304
|
+
|
305
|
+
tananum = (Math.cos(degToRad(e)) * Math.sin(degToRad(lambda)))
|
306
|
+
tanadenom = (Math.cos(degToRad(lambda)))
|
307
|
+
radToDeg(Math.atan2(tananum, tanadenom)) # in degrees
|
308
|
+
end
|
309
|
+
|
310
|
+
# calculate the declination of the sun
|
311
|
+
# @param [Float] t number of Julian centuries since J2000.0
|
312
|
+
# @return [Float] sun's declination in degrees
|
313
|
+
def calcSunDeclination(t)
|
314
|
+
e = calcObliquityCorrection(t)
|
315
|
+
lambda = calcSunApparentLong(t)
|
316
|
+
|
317
|
+
sint = Math.sin(degToRad(e)) * Math.sin(degToRad(lambda))
|
318
|
+
radToDeg(Math.asin(sint)) # in degrees
|
319
|
+
end
|
320
|
+
|
321
|
+
# calculate the difference between true solar time and mean solar time
|
322
|
+
# @param [Float] t number of Julian centuries since J2000.0
|
323
|
+
# @return [Float] equation of time in minutes of time
|
324
|
+
def calcEquationOfTime(t)
|
325
|
+
|
326
|
+
epsilon = calcObliquityCorrection(t)
|
327
|
+
l0 = calcGeomMeanLongSun(t)
|
328
|
+
e = calcEccentricityEarthOrbit(t)
|
329
|
+
m = calcGeomMeanAnomalySun(t)
|
330
|
+
|
331
|
+
y = Math.tan(degToRad(epsilon)/2.0)
|
332
|
+
y *= y
|
333
|
+
|
334
|
+
sin2l0 = Math.sin(2.0 * degToRad(l0))
|
335
|
+
sinm = Math.sin(degToRad(m))
|
336
|
+
cos2l0 = Math.cos(2.0 * degToRad(l0))
|
337
|
+
sin4l0 = Math.sin(4.0 * degToRad(l0))
|
338
|
+
sin2m = Math.sin(2.0 * degToRad(m))
|
339
|
+
|
340
|
+
radToDeg(y * sin2l0 - 2.0 * e * sinm + 4.0 * e * y * sinm * cos2l0 - 0.5 * y * y * sin4l0 - 1.25 * e * e * sin2m)*4.0 # in minutes of time
|
341
|
+
end
|
342
|
+
|
343
|
+
# calculate the hour angle of the sun at sunrise for the latitude
|
344
|
+
# @param [Float] solarDec declination angle of sun in degrees
|
345
|
+
# @param [SUN_RISE_SET,CIVIL_TWILIGHT,NAVAL_TWILIGHT,ASTRO_TWILIGHT] angle
|
346
|
+
# @return [Float] hour angle of sunrise in radians
|
347
|
+
# 0.833 is an approximation of the reflaction caused by the atmosphere
|
348
|
+
def calcHourAngleSunrise(solarDec, angle=SUN_RISE_SET)
|
349
|
+
latRad = degToRad(@latitude)
|
350
|
+
sdRad = degToRad(solarDec)
|
351
|
+
|
352
|
+
#HAarg = (Math.cos(degToRad(angle + 0.833))/(Math.cos(latRad)*Math.cos(sdRad))-Math.tan(latRad) * Math.tan(sdRad))
|
353
|
+
(Math.acos(Math.cos(degToRad(angle))/(Math.cos(latRad)*Math.cos(sdRad))-Math.tan(latRad) * Math.tan(sdRad))) # in radians
|
354
|
+
end
|
355
|
+
|
356
|
+
# calculate the hour angle of the sun at sunset for the
|
357
|
+
# @param [Float] solarDec declination angle of sun in degrees
|
358
|
+
# @param [SUN_RISE_SET,CIVIL_TWILIGHT,NAVAL_TWILIGHT,ASTRO_TWILIGHT] angle
|
359
|
+
# @return [Float] hour angle of sunset in radians
|
360
|
+
def calcHourAngleSunset( solarDec, angle=SUN_RISE_SET)
|
361
|
+
-calcHourAngleSunrise(solarDec,angle) # in radians
|
362
|
+
end
|
363
|
+
|
364
|
+
# calculate the Universal Coordinated Time (UTC) of sunrise
|
365
|
+
# for the given day at the given location on earth
|
366
|
+
# @param [Float] julian_day
|
367
|
+
# @param [SUN_RISE_SET,CIVIL_TWILIGHT,NAVAL_TWILIGHT,ASTRO_TWILIGHT] angle
|
368
|
+
# @return [DateTime] Date and Time of event
|
369
|
+
def calcSunriseUTC( julian_day, angle=SUN_RISE_SET)
|
370
|
+
|
371
|
+
t = calcTimeJulianCent( julian_day )
|
372
|
+
|
373
|
+
# *** Find the time of solar noon at the location, and use
|
374
|
+
# that declination. This is better than start of the
|
375
|
+
# Julian day
|
376
|
+
|
377
|
+
noonmin = calcSolNoonUTC(t)
|
378
|
+
tnoon = calcTimeJulianCent( julian_day+noonmin/1440.0)
|
379
|
+
|
380
|
+
# *** First pass to approximate sunrise (using solar noon)
|
381
|
+
|
382
|
+
eqTime = calcEquationOfTime(tnoon)
|
383
|
+
solarDec = calcSunDeclination(tnoon)
|
384
|
+
hourAngle = calcHourAngleSunrise(solarDec,angle)
|
385
|
+
delta = -@longitude - radToDeg(hourAngle)
|
386
|
+
timeDiff = 4 * delta; # in minutes of time
|
387
|
+
timeUTC = 720 + timeDiff - eqTime; # in minutes
|
388
|
+
|
389
|
+
# *** Second pass includes fractional jday in gamma calc
|
390
|
+
|
391
|
+
newt = calcTimeJulianCent(calcJDFromJulianCent(t) + timeUTC/1440.0)
|
392
|
+
eqTime = calcEquationOfTime(newt)
|
393
|
+
solarDec = calcSunDeclination(newt)
|
394
|
+
hourAngle = calcHourAngleSunrise(solarDec,angle)
|
395
|
+
delta = -@longitude - radToDeg(hourAngle)
|
396
|
+
timeDiff = 4 * delta
|
397
|
+
timeUTC = 720 + timeDiff - eqTime; # in minutes
|
398
|
+
|
399
|
+
to_datetime(julian_day,timeUTC)
|
400
|
+
end
|
401
|
+
|
402
|
+
# calculate the Universal Coordinated Time (UTC) of solar
|
403
|
+
# noon for the given day at the given location on earth
|
404
|
+
# @param [Float] t number of Julian centuries since J2000.0
|
405
|
+
# @return [Float] time in minutes from zero Z
|
406
|
+
def calcSolNoonUTC(t)
|
407
|
+
|
408
|
+
# First pass uses approximate solar noon to calculate eqtime
|
409
|
+
tnoon = calcTimeJulianCent(calcJDFromJulianCent(t) - @longitude/360.0)
|
410
|
+
eqTime = calcEquationOfTime(tnoon)
|
411
|
+
solNoonUTC = 720 - (@longitude * 4) - eqTime; # min
|
412
|
+
|
413
|
+
newt = calcTimeJulianCent(calcJDFromJulianCent(t) -0.5 + solNoonUTC/1440.0)
|
414
|
+
|
415
|
+
eqTime = calcEquationOfTime(newt)
|
416
|
+
solNoonUTC = 720 - (@longitude * 4) - eqTime; # min
|
417
|
+
|
418
|
+
return solNoonUTC
|
419
|
+
end
|
420
|
+
|
421
|
+
# calculate the Universal Coordinated Time (UTC) of sunset
|
422
|
+
# for the given day at the given location on earth
|
423
|
+
# @param [Float] julian_day
|
424
|
+
# @param [SUN_RISE_SET,CIVIL_TWILIGHT,NAVAL_TWILIGHT,ASTRO_TWILIGHT] angle
|
425
|
+
# @return [DateTime] Date and Time of event
|
426
|
+
def calcSunsetUTC(julian_day, angle=SUN_RISE_SET)
|
427
|
+
|
428
|
+
t = calcTimeJulianCent(julian_day)
|
429
|
+
|
430
|
+
# *** Find the time of solar noon at the location, and use
|
431
|
+
# that declination. This is better than start of the
|
432
|
+
# Julian day
|
433
|
+
|
434
|
+
noonmin = calcSolNoonUTC(t)
|
435
|
+
tnoon = calcTimeJulianCent(julian_day+noonmin/1440.0)
|
436
|
+
|
437
|
+
# First calculates sunrise and approx length of day
|
438
|
+
|
439
|
+
eqTime = calcEquationOfTime(tnoon)
|
440
|
+
solarDec = calcSunDeclination(tnoon)
|
441
|
+
hourAngle = calcHourAngleSunset(solarDec, angle)
|
442
|
+
|
443
|
+
delta = -@longitude - radToDeg(hourAngle)
|
444
|
+
timeDiff = 4 * delta
|
445
|
+
timeUTC = 720 + timeDiff - eqTime
|
446
|
+
|
447
|
+
# first pass used to include fractional day in gamma calc
|
448
|
+
|
449
|
+
newt = calcTimeJulianCent(calcJDFromJulianCent(t) + timeUTC/1440.0)
|
450
|
+
eqTime = calcEquationOfTime(newt)
|
451
|
+
solarDec = calcSunDeclination(newt)
|
452
|
+
hourAngle = calcHourAngleSunset(solarDec, angle)
|
453
|
+
|
454
|
+
delta = -@longitude - radToDeg(hourAngle)
|
455
|
+
timeDiff = 4 * delta
|
456
|
+
timeUTC = 720 + timeDiff - eqTime; # in minutes
|
457
|
+
|
458
|
+
to_datetime(julian_day,timeUTC)
|
459
|
+
end
|
460
|
+
|
461
|
+
# calculate the julian day of the most recent sunrise
|
462
|
+
# starting from the given day at the given location on earth
|
463
|
+
# @param [Float] julianday
|
464
|
+
# @return [Float] julian day of the most recent sunrise
|
465
|
+
def findRecentSunrise(julianday)
|
466
|
+
time = calcSunriseUTC(julianday)
|
467
|
+
while(!isNumber(time))
|
468
|
+
julianday -= 1.0
|
469
|
+
time = calcSunriseUTC(julianday)
|
470
|
+
end
|
471
|
+
|
472
|
+
return julianday
|
473
|
+
end
|
474
|
+
|
475
|
+
# calculate the julian day of the most recent sunset
|
476
|
+
# starting from the given day at the given location on earth
|
477
|
+
# @param [Float] julianday
|
478
|
+
# @return [Float] julian day of the most recent sunset
|
479
|
+
def findRecentSunset(julianday)
|
480
|
+
time = calcSunsetUTC(julianday)
|
481
|
+
while(!isNumber(time))
|
482
|
+
julianday -= 1.0
|
483
|
+
time = calcSunsetUTC(julianday)
|
484
|
+
end
|
485
|
+
|
486
|
+
return julianday
|
487
|
+
end
|
488
|
+
|
489
|
+
# calculate the julian day of the next sunrise
|
490
|
+
# starting from the given day at the given location on earth
|
491
|
+
# @param [Float] julianday
|
492
|
+
# @return [Float] julian day of the next sunrise
|
493
|
+
def findNextSunrise(julianday)
|
494
|
+
time = calcSunriseUTC(julianday)
|
495
|
+
while(!isNumber(time))
|
496
|
+
julianday += 1.0
|
497
|
+
time = calcSunriseUTC(julianday)
|
498
|
+
end
|
499
|
+
|
500
|
+
return julianday
|
501
|
+
end
|
502
|
+
|
503
|
+
# calculate the julian day of the next sunset
|
504
|
+
# starting from the given day at the given location on earth
|
505
|
+
# @param [Float] julianday
|
506
|
+
# @return [Float] julian day of the next sunset
|
507
|
+
def findNextSunset(julianday)
|
508
|
+
time = calcSunsetUTC(julianday)
|
509
|
+
while(!isNumber(time))
|
510
|
+
julianday += 1.0
|
511
|
+
time = calcSunsetUTC(julianday)
|
512
|
+
end
|
513
|
+
|
514
|
+
return julianday
|
515
|
+
end
|
516
|
+
|
517
|
+
# convert julian day and minutes to datetime
|
518
|
+
# @param [Float] minutes
|
519
|
+
# @return [DateTime]
|
520
|
+
def to_datetime(x,minutes)
|
521
|
+
jd = DateTime.jd(@julian_day) + (minutes/1440.0) + @zone
|
522
|
+
end
|
523
|
+
|
524
|
+
end
|
525
|
+
|
data/test/manualtest.rb
ADDED
metadata
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sunriseset
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.9.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Rob Burrowes
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-01-14 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: hoe-yard
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 0.1.2
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 0.1.2
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: hoe
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '3.1'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '3.1'
|
46
|
+
description: ! "SunRiseSet is a ruby class calculates the times of the sunrise, solar
|
47
|
+
noon and sunset.\nIt also calculates astronomical, naval and civil twilight times.\n\nNot
|
48
|
+
sure of the origin of the algorithm.\nI have seen a fortran version http://www.srrb.noaa.gov/highlights/sunrise/program.txt\na
|
49
|
+
.pl www.mso.anu.edu.au/~brian/grbs/astrosubs.pl and .vb versions for spreadsheets
|
50
|
+
too. \nAll had the same comments, so are of a common origin."
|
51
|
+
email:
|
52
|
+
- r.burrowes@auckland.ac.nz
|
53
|
+
executables: []
|
54
|
+
extensions: []
|
55
|
+
extra_rdoc_files:
|
56
|
+
- History.txt
|
57
|
+
- Manifest.txt
|
58
|
+
files:
|
59
|
+
- History.txt
|
60
|
+
- Manifest.txt
|
61
|
+
- README.md
|
62
|
+
- Rakefile
|
63
|
+
- lib/sunriseset.rb
|
64
|
+
- test/manualtest.rb
|
65
|
+
- .gemtest
|
66
|
+
homepage: http://rbur004.github.com/sunriseset/
|
67
|
+
licenses: []
|
68
|
+
post_install_message:
|
69
|
+
rdoc_options:
|
70
|
+
- --markup
|
71
|
+
- markdown
|
72
|
+
- --protected
|
73
|
+
- --title
|
74
|
+
- SunRiseSet
|
75
|
+
- --quiet
|
76
|
+
require_paths:
|
77
|
+
- lib
|
78
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
79
|
+
none: false
|
80
|
+
requirements:
|
81
|
+
- - ! '>='
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0'
|
84
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
85
|
+
none: false
|
86
|
+
requirements:
|
87
|
+
- - ! '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
requirements: []
|
91
|
+
rubyforge_project: sunriseset
|
92
|
+
rubygems_version: 1.8.24
|
93
|
+
signing_key:
|
94
|
+
specification_version: 3
|
95
|
+
summary: SunRiseSet is a ruby class calculates the times of the sunrise, solar noon
|
96
|
+
and sunset
|
97
|
+
test_files: []
|