sunriseset 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gemtest ADDED
File without changes
data/History.txt ADDED
@@ -0,0 +1,2 @@
1
+ robertburrowes Mon Jan 14 13:52:40 2013 +1300
2
+ Initital commit. Code refactored from my sunriseset html generating utility leaving just he SunRiseSet class, to create the gem.
data/Manifest.txt ADDED
@@ -0,0 +1,6 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.md
4
+ Rakefile
5
+ lib/sunriseset.rb
6
+ test/manualtest.rb
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
+
@@ -0,0 +1,6 @@
1
+ #!/usr/local/bin/ruby
2
+
3
+ require '../lib/sunriseset.rb'
4
+
5
+ puts SunRiseSet.now
6
+
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: []