ruby-sun-times 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/COPYING ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Joe Yates
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,35 @@
1
+ == SunTimes
2
+
3
+ Calculates sunrise and sunset times.
4
+
5
+ An implementation of the algorithm descibed at http://williams.best.vwh.net/sunrise_sunset_algorithm.htm
6
+
7
+ == References
8
+
9
+ * http://www.astro.uu.nl/~strous/AA/en/reken/zonpositie.html - Calculations
10
+ * http://williams.best.vwh.net/sunrise_sunset_algorithm.htm - Algorithm
11
+ * http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/264573 - Ken Bloom's implementation
12
+
13
+ == Licence
14
+
15
+ This code is free to use under the terms of the MIT licence:
16
+
17
+ Copyright (c) 2010 Joe Yates
18
+
19
+ Permission is hereby granted, free of charge, to any person obtaining a copy
20
+ of this software and associated documentation files (the "Software"), to
21
+ deal in the Software without restriction, including without limitation the
22
+ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
23
+ sell copies of the Software, and to permit persons to whom the Software is
24
+ furnished to do so, subject to the following conditions:
25
+
26
+ The above copyright notice and this permission notice shall be included in
27
+ all copies or substantial portions of the Software.
28
+
29
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
31
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
32
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
33
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
34
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
35
+ IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,48 @@
1
+ require 'rubygems'
2
+ require 'rake/gempackagetask'
3
+ require 'rake/rdoctask'
4
+ require 'rake/testtask'
5
+ require 'rake/clean'
6
+
7
+ $:.unshift(File.dirname(__FILE__) + '/lib')
8
+ require 'sun_times'
9
+
10
+ RDOC_OPTS = ['--quiet', '--title', 'Sun Times Calculator', '--main', 'README', '--inline-source']
11
+ CLEAN.include 'doc'
12
+
13
+ task :default => :test
14
+
15
+ spec = Gem::Specification.new do |s|
16
+ s.name = 'ruby-sun-times'
17
+ s.summary = 'Module which calculates sunrise and sunset times'
18
+ s.version = SunTimes::VERSION::STRING
19
+
20
+ s.homepage = 'http://github.com/joeyates/ruby-sun-times'
21
+ s.author = 'Joe Yates'
22
+ s.email = 'joe.g.yates@gmail.com'
23
+
24
+ s.files = ['README', 'COPYING', 'Rakefile'] + FileList['{lib,test}/**/*.rb']
25
+ s.require_paths = ['lib']
26
+
27
+ s.has_rdoc = true
28
+ s.rdoc_options += RDOC_OPTS
29
+ s.extra_rdoc_files = ['README', 'COPYING']
30
+
31
+ s.test_file = 'test/test_all.rb'
32
+ end
33
+
34
+ Rake::TestTask.new do |t|
35
+ t.libs << 'test'
36
+ t.test_files = FileList['test/*_test.rb']
37
+ t.verbose = true
38
+ end
39
+
40
+ Rake::RDocTask.new do |rdoc|
41
+ rdoc.rdoc_dir = 'doc/rdoc'
42
+ rdoc.options += RDOC_OPTS
43
+ rdoc.main = "README"
44
+ rdoc.rdoc_files.add ['README', 'COPYING', 'lib/**/*.rb']
45
+ end
46
+
47
+ Rake::GemPackageTask.new(spec) do |pkg|
48
+ end
data/lib/sun_times.rb ADDED
@@ -0,0 +1,158 @@
1
+ #--
2
+ # Copyright (c) 2010 Joe Yates
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+
24
+ # Algorithm from http://williams.best.vwh.net/sunrise_sunset_algorithm.htm
25
+
26
+ require 'date'
27
+
28
+ module SunTimes
29
+
30
+ module VERSION #:nodoc:
31
+ MAJOR = 0
32
+ MINOR = 1
33
+ TINY = 1
34
+
35
+ STRING = [MAJOR, MINOR, TINY].join('.')
36
+ end
37
+
38
+ DEFAULT_ZENITH = 90.83333
39
+ KNOWN_EVENTS = [:rise, :set]
40
+
41
+ # Helper method: calculates sunrise, with the same parameters as calculate
42
+ def SunTimes.rise(date, latitude, longitude, options = {})
43
+ calculate(:rise, date, latitude, longitude, options)
44
+ end
45
+
46
+ # Helper method: calculates sunset, with the same parameters as calculate
47
+ def SunTimes.set(date, latitude, longitude, options = {})
48
+ calculate(:set, date, latitude, longitude, options)
49
+ end
50
+
51
+ # Calculates the sunrise or sunset time for a specific date and location
52
+ #
53
+ # ==== Parameters
54
+ # * +event+ - One of :rise, :set.
55
+ # * +date+ - An object that responds to yday.
56
+ # * +latitude+ - The latitude of the location in degrees.
57
+ # * +longitude+ - The longitude of the location in degrees.
58
+ # * +options+ - Additional option is <tt>:zenith</tt>.
59
+ #
60
+ # ==== Example
61
+ # SunTimes.calculate(:rise, Date.new(2010, 3, 8), 43.779, 11.432)
62
+ # > Mon Mar 08 05:39:53 UTC 2010
63
+ def SunTimes.calculate(event, date, latitude, longitude, options = {})
64
+ raise "Unknown event '#{ event }'" if KNOWN_EVENTS.find_index(event).nil?
65
+ zenith = options.delete(:zenith) || DEFAULT_ZENITH
66
+
67
+ # lngHour
68
+ longitude_hour = longitude / 15.0
69
+
70
+ # t
71
+ base_time = event == :rise ? 6.0 : 18.0
72
+ approximate_time = date.yday + (base_time - longitude_hour) / 24.0
73
+
74
+ # M
75
+ mean_sun_anomaly = (0.9856 * approximate_time) - 3.289
76
+
77
+ # L
78
+ sun_true_longitude = mean_sun_anomaly +
79
+ (1.916 * Math.sin(degrees_to_radians(mean_sun_anomaly))) +
80
+ (0.020 * Math.sin(2 * degrees_to_radians(mean_sun_anomaly))) +
81
+ 282.634
82
+ sun_true_longitude = coerce_degrees(sun_true_longitude)
83
+
84
+ # RA
85
+ tan_right_ascension = 0.91764 * Math.tan(degrees_to_radians(sun_true_longitude))
86
+ sun_right_ascension = radians_to_degrees(Math.atan(tan_right_ascension))
87
+ sun_right_ascension = coerce_degrees(sun_right_ascension)
88
+
89
+ # right ascension value needs to be in the same quadrant as L
90
+ sun_true_longitude_quadrant = (sun_true_longitude / 90.0).floor * 90.0
91
+ sun_right_ascension_quadrant = (sun_right_ascension / 90.0).floor * 90.0
92
+ sun_right_ascension += (sun_true_longitude_quadrant - sun_right_ascension_quadrant)
93
+
94
+ # RA = RA / 15
95
+ sun_right_ascension_hours = sun_right_ascension / 15.0
96
+
97
+ sin_declination = 0.39782 * Math.sin(degrees_to_radians(sun_true_longitude))
98
+ cos_declination = Math.cos(Math.asin(sin_declination))
99
+
100
+ cos_local_hour_angle =
101
+ (Math.cos(degrees_to_radians(zenith)) - (sin_declination * Math.sin(degrees_to_radians(latitude)))) /
102
+ (cos_declination * Math.cos(degrees_to_radians(latitude)))
103
+
104
+ # the sun never rises on this location (on the specified date)
105
+ return nil if cos_local_hour_angle > 1
106
+ # the sun never sets on this location (on the specified date)
107
+ return nil if cos_local_hour_angle < -1
108
+
109
+ # H
110
+ suns_local_hour =
111
+ if event == :rise
112
+ 360 - radians_to_degrees(Math.acos(cos_local_hour_angle))
113
+ else
114
+ radians_to_degrees(Math.acos(cos_local_hour_angle))
115
+ end
116
+
117
+ # H = H / 15
118
+ suns_local_hour_hours = suns_local_hour / 15.0
119
+
120
+ # T = H + RA - (0.06571 * t) - 6.622
121
+ local_mean_time = suns_local_hour_hours + sun_right_ascension_hours - (0.06571 * approximate_time) - 6.622
122
+
123
+ # UT = T - lngHour
124
+ gmt_hours = local_mean_time - longitude_hour
125
+ gmt_hours -= 24.0 if gmt_hours > 24
126
+ gmt_hours += 24.0 if gmt_hours < 0
127
+
128
+ hour = gmt_hours.floor
129
+ hour_remainder = (gmt_hours.to_f - hour.to_f) * 60.0
130
+ minute = hour_remainder.floor
131
+ seconds = (hour_remainder - minute) * 60.0
132
+
133
+ Time.gm(date.year, date.month, date.day, hour, minute, seconds)
134
+ end
135
+
136
+ private
137
+
138
+ def SunTimes.degrees_to_radians(d)
139
+ d.to_f / 360.0 * 2.0 * Math::PI
140
+ end
141
+
142
+ def SunTimes.radians_to_degrees(r)
143
+ r.to_f * 360.0 / (2.0 * Math::PI)
144
+ end
145
+
146
+ def SunTimes.coerce_degrees(d)
147
+ if d < 0
148
+ d += 360
149
+ return coerce_degrees(d)
150
+ end
151
+ if d >= 360
152
+ d -= 360
153
+ return coerce_degrees(d)
154
+ end
155
+ d
156
+ end
157
+
158
+ end
@@ -0,0 +1,39 @@
1
+ # encoding: utf-8
2
+ $:.unshift(File.dirname(__FILE__) + '/../lib')
3
+ require 'test/unit'
4
+ require 'sun_times'
5
+
6
+ class SunTimesTest < Test::Unit::TestCase
7
+
8
+ def test_rise_20100308_pontassieve
9
+ rise = SunTimes.calculate(:rise, Date.new(2010, 3, 8), 43.779, 11.432)
10
+ assert_equal(rise.to_i, 1268026793)
11
+ end
12
+
13
+ def test_set_20100308_pontassieve
14
+ rise = SunTimes.calculate(:set, Date.new(2010, 3, 8), 43.779, 11.432)
15
+ assert_equal(rise.to_i, 1268068276)
16
+ end
17
+
18
+ def test_rise_helper
19
+ rise = SunTimes.rise(Date.new(2010, 3, 8), 43.779, 11.432)
20
+ assert_equal(rise.to_i, 1268026793)
21
+ end
22
+
23
+ def test_set_helper
24
+ rise = SunTimes.set(Date.new(2010, 3, 8), 43.779, 11.432)
25
+ assert_equal(rise.to_i, 1268068276)
26
+ end
27
+
28
+ def test_midnight_sun_on_20100621_north_cape
29
+ rise = SunTimes.calculate(:rise, Date.new(2010, 6, 21), 71.170219, 25.785556)
30
+ assert_nil(rise)
31
+ set = SunTimes.calculate(:set, Date.new(2010, 6, 21), 71.170219, 25.785556)
32
+ assert_nil(set)
33
+ end
34
+
35
+ def test_unknown_event
36
+ assert_raise(RuntimeError) { SunTimes.calculate(:foo, Date.new(2010, 3, 8), 43.779, 11.432) }
37
+ end
38
+
39
+ end
data/test/test_all.rb ADDED
@@ -0,0 +1,3 @@
1
+ Dir[File.dirname(__FILE__)+'/*_test.rb'].each do |test|
2
+ require test
3
+ end
metadata ADDED
@@ -0,0 +1,66 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ruby-sun-times
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Joe Yates
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-03-09 00:00:00 +01:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description:
17
+ email: joe.g.yates@gmail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README
24
+ - COPYING
25
+ files:
26
+ - README
27
+ - COPYING
28
+ - Rakefile
29
+ - lib/sun_times.rb
30
+ - test/calculate_test.rb
31
+ - test/test_all.rb
32
+ has_rdoc: true
33
+ homepage: http://github.com/joeyates/ruby-sun-times
34
+ licenses: []
35
+
36
+ post_install_message:
37
+ rdoc_options:
38
+ - --quiet
39
+ - --title
40
+ - Sun Times Calculator
41
+ - --main
42
+ - README
43
+ - --inline-source
44
+ require_paths:
45
+ - lib
46
+ required_ruby_version: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: "0"
51
+ version:
52
+ required_rubygems_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: "0"
57
+ version:
58
+ requirements: []
59
+
60
+ rubyforge_project:
61
+ rubygems_version: 1.3.5
62
+ signing_key:
63
+ specification_version: 3
64
+ summary: Module which calculates sunrise and sunset times
65
+ test_files:
66
+ - test/test_all.rb