ruby-sun-times 0.1.4 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.8.7
4
+ - 1.9.3
5
+ - 2.0.0
6
+ script: "bundle exec rspec"
7
+ cache: bundler
data/README.md CHANGED
@@ -1,6 +1,16 @@
1
- # SunTimes
1
+ # ruby-sun-times [![Build Status](https://travis-ci.org/joeyates/ruby-sun-times.png?branch=master)][Continuous Integration]
2
2
 
3
- Calculates sunrise and sunset times.
3
+ *Calculates sunrise and sunset times*
4
+
5
+ * [Source Code]
6
+ * [API documentation]
7
+ * [Rubygem]
8
+ * [Continuous Integration]
9
+
10
+ [Source Code]: https://github.com/joeyates/ruby-sun-times "Source code at GitHub"
11
+ [API documentation]: http://rubydoc.info/gems/ruby-sun-times/frames "RDoc API Documentation at Rubydoc.info"
12
+ [Rubygem]: http://rubygems.org/gems/ruby-sun-times "Ruby gem at rubygems.org"
13
+ [Continuous Integration]: http://travis-ci.org/joeyates/ruby-sun-times "Build status by Travis-CI"
4
14
 
5
15
  An implementation of the algorithm descibed at http://williams.best.vwh.net/sunrise_sunset_algorithm.htm
6
16
 
@@ -25,50 +25,75 @@
25
25
 
26
26
  require 'date'
27
27
 
28
- module SunTimes
28
+ class SunTimes
29
29
  DEFAULT_ZENITH = 90.83333
30
30
  KNOWN_EVENTS = [:rise, :set]
31
31
  DEGREES_PER_HOUR = 360.0 / 24.0
32
32
 
33
- # Helper method: calculates sunrise, with the same parameters as calculate
33
+ attr_reader :options
34
+
35
+ # Deprecated: use SunTimes.new.rise(...)
34
36
  def self.rise(date, latitude, longitude, options = {})
35
- calculate(:rise, date, latitude, longitude, options)
37
+ new(options).calculate(:rise, date, latitude, longitude, options)
36
38
  end
37
39
 
38
- # Helper method: calculates sunset, with the same parameters as calculate
40
+ # Deprecated: use SunTimes.new.set(...)
39
41
  def self.set(date, latitude, longitude, options = {})
40
- calculate(:set, date, latitude, longitude, options)
42
+ new(options).calculate(:set, date, latitude, longitude, options)
43
+ end
44
+
45
+ # Deprecated: use SunTimes.new.rise/set(...)
46
+ def self.calculate(event, date, latitude, longitude, options = {})
47
+ new(options).calculate(event, date, latitude, longitude)
41
48
  end
42
49
 
43
- # Calculates the sunrise or sunset time for a specific date and location
44
- #
45
- # ==== Parameters
46
- # * +event+ - One of :rise, :set.
47
- # * +date+ - An object that responds to :to_datetime.
48
- # * +latitude+ - The latitude of the location in degrees.
49
- # * +longitude+ - The longitude of the location in degrees.
50
50
  # * +options+ -
51
51
  # * <tt>:never_rises_result</tt> - the value to be returned if the sun never rises on the supplied date,
52
52
  # * <tt>:never_sets_result</tt> - the value to be returned if the sun never sets on the supplied date,
53
53
  # * <tt>:zenith</tt> - default 90.83333
54
- #
55
- # ==== Example
56
- # SunTimes.calculate(:rise, Date.new(2010, 3, 8), 43.779, 11.432)
57
- # > Mon Mar 08 05:39:53 UTC 2010
58
- def self.calculate(event, date, latitude, longitude, options = {})
59
- options = {
54
+ def initialize(options = {})
55
+ @options = {
60
56
  :never_sets_result => nil,
61
57
  :never_rises_result => nil,
62
58
  :zenith => DEFAULT_ZENITH,
63
59
  }.merge(options)
64
- datetime = date.to_datetime
65
- raise "Unknown event '#{ event }'" if KNOWN_EVENTS.find_index(event).nil?
60
+ end
61
+
62
+ # Calculates the sunrise time for a specific date and location
63
+ #
64
+ # ==== Parameters
65
+ # * +date+ - An object that responds to :to_datetime.
66
+ # * +latitude+ - The latitude of the location in degrees.
67
+ # * +longitude+ - The longitude of the location in degrees.
68
+ #
69
+ # ==== Example
70
+ # SunTimes.new.rise(Date.new(2010, 3, 8), 43.779, 11.432)
71
+ # > Mon Mar 08 05:39:53 UTC 2010
72
+ def rise(date, latitude, longitude)
73
+ calculate(:rise, date, latitude, longitude)
74
+ end
75
+
76
+ # calculates sunset, see #rise for parameters
77
+ def set(date, latitude, longitude)
78
+ calculate(:set, date, latitude, longitude)
79
+ end
80
+
81
+ private
82
+
83
+ def calculate(event, date, latitude, longitude)
84
+ datetime = to_datetime(date)
85
+ raise "Unknown event '#{event}'" unless KNOWN_EVENTS.include?(event)
66
86
 
67
87
  # lngHour
68
88
  longitude_hour = longitude / DEGREES_PER_HOUR
69
89
 
70
90
  # t
71
- base_time = event == :rise ? 6.0 : 18.0
91
+ base_time =
92
+ if event == :rise
93
+ 6.0
94
+ else
95
+ 18.0
96
+ end
72
97
  approximate_time = datetime.yday + (base_time - longitude_hour) / 24.0
73
98
 
74
99
  # M
@@ -128,12 +153,12 @@ module SunTimes
128
153
  offset_hours = datetime.offset * 24.0
129
154
 
130
155
  if gmt_hours + offset_hours < 0
131
- next_day = datetime.next_day
132
- return calculate(event, next_day.new_offset, latitude, longitude, options = {})
156
+ next_day = next_day(datetime)
157
+ return calculate(event, next_day.new_offset, latitude, longitude)
133
158
  end
134
159
  if gmt_hours + offset_hours > 24
135
- previous_day = datetime.prev_day
136
- return calculate(event, previous_day.new_offset, latitude, longitude, options = {})
160
+ previous_day = prev_day(datetime)
161
+ return calculate(event, previous_day.new_offset, latitude, longitude)
137
162
  end
138
163
 
139
164
  hour = gmt_hours.floor
@@ -144,17 +169,49 @@ module SunTimes
144
169
  Time.gm(datetime.year, datetime.month, datetime.day, hour, minute, seconds)
145
170
  end
146
171
 
147
- private
172
+ ############################
173
+ # ruby 1.8 compatibility
174
+
175
+ def to_datetime(date)
176
+ if date.respond_to?(:to_datetime)
177
+ date.to_datetime
178
+ else
179
+ values = [
180
+ date.year,
181
+ date.month,
182
+ date.day,
183
+ ]
184
+ [:hour, :minute, :second, :zone].each do |m|
185
+ values <<
186
+ if date.respond_to?(m)
187
+ date.send(m)
188
+ else
189
+ 0
190
+ end
191
+ end
192
+ DateTime.new(*values)
193
+ end
194
+ end
195
+
196
+ def prev_day(datetime)
197
+ datetime - 1
198
+ end
199
+
200
+ def next_day(datetime)
201
+ datetime + 1
202
+ end
203
+
204
+ ############################
148
205
 
149
- def self.degrees_to_radians(d)
206
+ def degrees_to_radians(d)
150
207
  d.to_f / 360.0 * 2.0 * Math::PI
151
208
  end
152
209
 
153
- def self.radians_to_degrees(r)
210
+ def radians_to_degrees(r)
154
211
  r.to_f * 360.0 / (2.0 * Math::PI)
155
212
  end
156
213
 
157
- def self.coerce_degrees(d)
214
+ def coerce_degrees(d)
158
215
  if d < 0
159
216
  d += 360
160
217
  return coerce_degrees(d)
@@ -1,8 +1,8 @@
1
- module SunTimes
1
+ class SunTimes
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 0
4
4
  MINOR = 1
5
- TINY = 4
5
+ TINY = 5
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
@@ -1,101 +1,115 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe SunTimes do
4
+ let(:options) { {} }
4
5
  let(:day) { Date.new(2010, 3, 8) }
5
6
  let(:latitude) { 43.779 }
6
7
  let(:longitude) { 11.432 }
7
- let(:rise) { Time.gm(2010, 3, 8, 5, 39, 53) }
8
- let(:set) { Time.gm(2010, 3, 8, 17, 11, 16) }
9
8
  let(:midsummer) { Date.new(2010, 6, 21) }
10
9
  let(:midwinter) { Date.new(2010, 12, 21) }
11
10
  let(:north_cape_latitude) { 71.170219 }
12
11
  let(:north_cape_longitude) { 25.785556 }
13
12
 
14
- describe '#calculate' do
15
- context ':rise' do
16
- it 'returns the sunrise time' do
17
- result = SunTimes.calculate(:rise, day, latitude, longitude)
18
- expect(result).to be_within(1).of(rise)
13
+ subject { described_class.new(options) }
14
+
15
+ shared_examples_for 'never sets and never rises options' do |method|
16
+ context ':never_rises_result' do
17
+ let(:options) do
18
+ {
19
+ :never_rises_result => :never_rises,
20
+ :never_sets_result => :never_sets,
21
+ }
19
22
  end
20
- end
21
23
 
22
- context ':set' do
23
- it 'returns the sunset time' do
24
- result = SunTimes.calculate(:set, day, latitude, longitude)
25
- expect(result).to be_within(1).of(set)
24
+ context 'never rises' do
25
+ it 'uses the supplied value' do
26
+ result = subject.send(method, midwinter, north_cape_latitude, north_cape_longitude)
27
+ expect(result).to eq(:never_rises)
28
+ end
26
29
  end
27
- end
28
30
 
29
- context 'unknown event' do
30
- it 'fails' do
31
- expect {
32
- SunTimes.calculate(:foo, day, latitude, longitude)
33
- }.to raise_error(RuntimeError, /unknown event/i)
31
+ context 'never sets' do
32
+ it 'uses the supplied value' do
33
+ result = subject.send(method, midsummer, north_cape_latitude, north_cape_longitude)
34
+ expect(result).to eq(:never_sets)
35
+ end
34
36
  end
35
37
  end
38
+ end
36
39
 
40
+ shared_examples_for 'timezones' do |method|
37
41
  context 'with timezone' do
38
42
  let(:zone) { Rational(-8, 24) }
39
43
  let(:day_with_zone) { DateTime.new(2011, 12, 13, 0, 0, 0, zone) }
40
44
 
41
45
  it 'calculates according to the supplied value' do
42
- set = SunTimes.calculate(:set, day_with_zone, 45.52, -122.681944)
46
+ set = subject.send(method, day_with_zone, 45.52, -122.681944)
43
47
  result_datetime = DateTime.new(set.year, set.month, set.day, set.hour, set.min, set.sec, 0)
44
48
 
45
49
  expect(result_datetime).to be > day_with_zone
46
50
  expect(result_datetime).to be <= day_with_zone + 1
47
51
  end
48
52
  end
53
+ end
49
54
 
55
+ shared_examples_for 'no event' do |method|
50
56
  context 'midnight sun' do
51
- it 'rise is nil' do
52
- result = SunTimes.calculate(:rise, midsummer, north_cape_latitude, north_cape_longitude)
57
+ it 'is nil' do
58
+ result = subject.send(method, midsummer, north_cape_latitude, north_cape_longitude)
53
59
  expect(result).to be_nil
54
60
  end
61
+ end
55
62
 
56
- it 'set is nil' do
57
- result = SunTimes.calculate(:set, midsummer, north_cape_latitude, north_cape_longitude)
63
+ context 'continuous night' do
64
+ it 'is nil' do
65
+ result = subject.send(method, midwinter, north_cape_latitude, north_cape_longitude)
58
66
  expect(result).to be_nil
59
67
  end
60
68
  end
69
+ end
61
70
 
71
+ shared_examples_for 'limiting cases' do |method|
62
72
  context 'last day of the year' do
63
73
  let(:zone) { Rational(-8, 24) }
64
74
  let(:day) { DateTime.new(2013, 12, 31, 8, 59, 5, zone) }
65
75
 
66
76
  it 'calculates correctly' do
67
- SunTimes.calculate(:set, day, 47.5, -122)
68
- end
69
- end
70
-
71
- context 'options' do
72
- context ':never_rises_result' do
73
- it 'uses the supplied value, instead of nil' do
74
- result = SunTimes.calculate(:rise, midwinter, north_cape_latitude, north_cape_longitude, {:never_rises_result => :never_rises})
75
- expect(result).to eq(:never_rises)
76
- end
77
- end
78
-
79
- context ':never_sets_result' do
80
- it 'uses the supplied value, instead of nil' do
81
- result = SunTimes.calculate(:rise, midsummer, north_cape_latitude, north_cape_longitude, {:never_sets_result => :never_sets})
82
- expect(result).to eq(:never_sets)
83
- end
77
+ subject.send(method, day, 47.5, -122)
84
78
  end
85
79
  end
86
80
  end
87
81
 
88
82
  describe '#rise' do
83
+ let(:rise) { Time.gm(2010, 3, 8, 5, 39, 53) }
84
+
89
85
  it 'returns the sunrise time' do
90
- result = SunTimes.rise(day, latitude, longitude)
86
+ result = subject.rise(day, latitude, longitude)
91
87
  expect(result).to be_within(1).of(rise)
92
88
  end
89
+
90
+ include_examples 'timezones', :rise
91
+ include_examples 'limiting cases', :rise
92
+ include_examples 'no event', :rise
93
+
94
+ context 'options' do
95
+ include_examples 'never sets and never rises options', :rise
96
+ end
93
97
  end
94
98
 
95
99
  describe '#set' do
100
+ let(:set) { Time.gm(2010, 3, 8, 17, 11, 16) }
101
+
96
102
  it 'returns the sunset time' do
97
- result = SunTimes.set(day, latitude, longitude)
103
+ result = subject.set(day, latitude, longitude)
98
104
  expect(result).to be_within(1).of(set)
99
105
  end
106
+
107
+ include_examples 'timezones', :set
108
+ include_examples 'limiting cases', :set
109
+ include_examples 'no event', :rise
110
+
111
+ context 'options' do
112
+ include_examples 'never sets and never rises options', :set
113
+ end
100
114
  end
101
115
  end
metadata CHANGED
@@ -1,51 +1,63 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: ruby-sun-times
3
- version: !ruby/object:Gem::Version
4
- version: 0.1.4
3
+ version: !ruby/object:Gem::Version
4
+ hash: 17
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 5
10
+ version: 0.1.5
5
11
  platform: ruby
6
- authors:
12
+ authors:
7
13
  - Joe Yates
8
14
  autorequire:
9
15
  bindir: bin
10
16
  cert_chain: []
11
- date: 2014-01-01 00:00:00.000000000 Z
12
- dependencies:
13
- - !ruby/object:Gem::Dependency
17
+
18
+ date: 2014-01-04 00:00:00 +01:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
14
22
  name: pry
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - '>='
18
- - !ruby/object:Gem::Version
19
- version: '0'
20
- type: :development
21
23
  prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - '>='
25
- - !ruby/object:Gem::Version
26
- version: '0'
27
- - !ruby/object:Gem::Dependency
28
- name: rspec
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - '>='
32
- - !ruby/object:Gem::Version
33
- version: '0'
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
34
33
  type: :development
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: rspec
35
37
  prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - '>='
39
- - !ruby/object:Gem::Version
40
- version: '0'
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ hash: 3
44
+ segments:
45
+ - 0
46
+ version: "0"
47
+ type: :development
48
+ version_requirements: *id002
41
49
  description:
42
50
  email: joe.g.yates@gmail.com
43
51
  executables: []
52
+
44
53
  extensions: []
54
+
45
55
  extra_rdoc_files: []
46
- files:
56
+
57
+ files:
47
58
  - .gitignore
48
59
  - .rspec
60
+ - .travis.yml
49
61
  - COPYING
50
62
  - Gemfile
51
63
  - README.md
@@ -55,30 +67,40 @@ files:
55
67
  - ruby-sun-times.gemspec
56
68
  - spec/spec_helper.rb
57
69
  - spec/unit/ruby_sun_times_spec.rb
70
+ has_rdoc: true
58
71
  homepage: https://github.com/joeyates/ruby-sun-times
59
72
  licenses: []
60
- metadata: {}
73
+
61
74
  post_install_message:
62
75
  rdoc_options: []
63
- require_paths:
76
+
77
+ require_paths:
64
78
  - lib
65
- required_ruby_version: !ruby/object:Gem::Requirement
66
- requirements:
67
- - - '>='
68
- - !ruby/object:Gem::Version
69
- version: '0'
70
- required_rubygems_version: !ruby/object:Gem::Requirement
71
- requirements:
72
- - - '>='
73
- - !ruby/object:Gem::Version
74
- version: '0'
79
+ required_ruby_version: !ruby/object:Gem::Requirement
80
+ none: false
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ hash: 3
85
+ segments:
86
+ - 0
87
+ version: "0"
88
+ required_rubygems_version: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ hash: 3
94
+ segments:
95
+ - 0
96
+ version: "0"
75
97
  requirements: []
98
+
76
99
  rubyforge_project:
77
- rubygems_version: 2.0.3
100
+ rubygems_version: 1.6.2
78
101
  signing_key:
79
- specification_version: 4
102
+ specification_version: 3
80
103
  summary: Module which calculates sunrise and sunset times
81
- test_files:
104
+ test_files:
82
105
  - spec/spec_helper.rb
83
106
  - spec/unit/ruby_sun_times_spec.rb
84
- has_rdoc:
checksums.yaml DELETED
@@ -1,7 +0,0 @@
1
- ---
2
- SHA1:
3
- metadata.gz: ecb13177df09644d48fc75563740cec84495ce00
4
- data.tar.gz: c9002e7be0138db8ba4409844d97f7ecab102187
5
- SHA512:
6
- metadata.gz: 7b0a05c96603d12fcc58821a79b39ccc74a7f0b7034540b32c5aafba39cd41035dc330bb10eadcceefd4a4a8f11be523c6678901b0d600ee964d2e47a1ff1dee
7
- data.tar.gz: 35671f27cd9a50ca1e1db445021a870bf87abb13257c544acd169e1c2a09c15088b7b7a2a26672a6d83c0060d42867729654d9e80efcbf7f973c472b96434735