ruby-sun-times 0.1.4 → 0.1.5

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.
@@ -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