ruby-sun-times 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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