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.
- data/.travis.yml +7 -0
- data/README.md +12 -2
- data/lib/sun_times.rb +86 -29
- data/lib/sun_times/version.rb +2 -2
- data/spec/unit/ruby_sun_times_spec.rb +56 -42
- metadata +69 -47
- checksums.yaml +0 -7
data/.travis.yml
ADDED
data/README.md
CHANGED
@@ -1,6 +1,16 @@
|
|
1
|
-
#
|
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
|
|
data/lib/sun_times.rb
CHANGED
@@ -25,50 +25,75 @@
|
|
25
25
|
|
26
26
|
require 'date'
|
27
27
|
|
28
|
-
|
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
|
-
|
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
|
-
#
|
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
|
-
|
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
|
-
|
65
|
-
|
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 =
|
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
|
132
|
-
return calculate(event, next_day.new_offset, latitude, longitude
|
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
|
136
|
-
return calculate(event, previous_day.new_offset, latitude, longitude
|
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
|
-
|
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
|
206
|
+
def degrees_to_radians(d)
|
150
207
|
d.to_f / 360.0 * 2.0 * Math::PI
|
151
208
|
end
|
152
209
|
|
153
|
-
def
|
210
|
+
def radians_to_degrees(r)
|
154
211
|
r.to_f * 360.0 / (2.0 * Math::PI)
|
155
212
|
end
|
156
213
|
|
157
|
-
def
|
214
|
+
def coerce_degrees(d)
|
158
215
|
if d < 0
|
159
216
|
d += 360
|
160
217
|
return coerce_degrees(d)
|
data/lib/sun_times/version.rb
CHANGED
@@ -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
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
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
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
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
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
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 =
|
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 '
|
52
|
-
result =
|
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
|
-
|
57
|
-
|
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
|
-
|
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 =
|
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 =
|
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
|
-
|
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
|
-
|
12
|
-
|
13
|
-
|
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
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
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
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
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
|
-
|
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
|
-
|
73
|
+
|
61
74
|
post_install_message:
|
62
75
|
rdoc_options: []
|
63
|
-
|
76
|
+
|
77
|
+
require_paths:
|
64
78
|
- lib
|
65
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
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:
|
100
|
+
rubygems_version: 1.6.2
|
78
101
|
signing_key:
|
79
|
-
specification_version:
|
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
|