sundial 0.0.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/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm use 1.9.3@bobtime --create
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in sundial.gemspec
4
+ gemspec
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,77 @@
1
+ require './lib/sundial'
2
+ puts
3
+ puts
4
+
5
+ @s = Sundial.new
6
+
7
+ def printer(str)
8
+ print str, @s.send(str.strip.intern), "\n"
9
+ end
10
+
11
+ #
12
+ #@s.address = "201 West Broad Street, Richmond, VA"
13
+ #@s.address = "6526 Stuart Ave, Richmond, VA, 23226"
14
+ #@s.date = (Date.today + 110.days + 1.year).jd
15
+
16
+ #@s.address = "Amsterdam, Netherlands"
17
+ @s.address = @s.external_ip
18
+ #@s.date = Date.parse("2004-04-01").jd
19
+ #@s.date = Date.parse("2011-12-24").jd
20
+
21
+
22
+ #puts "lat_long", @s.lat_long
23
+
24
+ printer " latitude "
25
+ printer ' longitude '
26
+ printer ' longitude_west '
27
+ #printer ' get_offset '
28
+ printer 'get_timezone_offset '
29
+
30
+ puts "Driver Block One ----------------------"
31
+ printer " current_julian_date "
32
+ print " JULIAN_2000 ", "2451545", "\n"
33
+ printer ' jrd '
34
+ printer " current_julian_cycle "
35
+ printer ' solar_mean_anomaly '
36
+ printer " equation_of_center "
37
+ printer " ecliptic_longitude "
38
+ printer " right_ascension "
39
+ printer "declination_of_the_sun "
40
+ puts
41
+
42
+ puts "Driver Block Two ----------------------"
43
+ printer " l_sun "
44
+ printer " jpp "
45
+ printer " sunset_jd_two "
46
+ puts
47
+
48
+ puts "Driver Block Three ----------------------"
49
+ printer " sidereal_time "
50
+ printer " hour_angle "
51
+ printer " hour_angle_two "
52
+ printer "approximate_solar_noon "
53
+ printer " solar_transit "
54
+ puts
55
+
56
+ puts "Driver Block Four"
57
+ printer ' wiki_set '
58
+ printer ' sunrise_jd '
59
+ printer " sunset_jd "
60
+ printer " sunrise "
61
+ printer " sunset "
62
+ printer " sunrise_f "
63
+ printer " sunset_f "
64
+ printer ' length_of_day '
65
+ printer ' asn_date '
66
+
67
+ def format_datetime(dt)
68
+ dt.strftime("%B %e %Y %T")
69
+ end
70
+
71
+ puts "the equivalent of 9 AM on the solstice on this day would be", format_datetime(@s.nine)
72
+ puts "the equivalent of 5 pm on the solstice on this day would be", format_datetime(@s.five)
73
+
74
+
75
+
76
+
77
+ # Looks like the times are good, need to grab the timezone of the address being used and offset the UTC results by that much
@@ -0,0 +1,8 @@
1
+ class Numeric
2
+ def degrees
3
+ self * Math::PI / 180
4
+ end
5
+ def radians
6
+ self * 180 / Math::PI
7
+ end
8
+ end
@@ -0,0 +1,3 @@
1
+ module Sundial
2
+ VERSION = "0.0.1"
3
+ end
data/lib/sundial.rb ADDED
@@ -0,0 +1,228 @@
1
+ require 'date'
2
+ require 'geokit'
3
+ require 'open-uri'
4
+ require 'json'
5
+ require 'active_support/time'
6
+
7
+ require_relative 'numeric_extensions'
8
+
9
+ class Sundial
10
+
11
+ attr_accessor :address, :date, :ip, :offset, :ll
12
+
13
+ def initialize
14
+ @address = "Richmond, Virginia"
15
+ end
16
+
17
+ JULIAN_2000 = 2451545
18
+
19
+ def local_time
20
+ DateTime.now
21
+ end
22
+
23
+ def whatismyip
24
+ "http://www.whatismyip.org/"
25
+ end
26
+
27
+ def current_julian_date
28
+ # http://stackoverflow.com/questions/5095456/using-the-ruby-date-class-for-astronomical-data
29
+ @date || Date.today.jd
30
+ end
31
+
32
+ def external_ip
33
+ @ip ||= open(whatismyip).read
34
+ @ip
35
+ # '75.75.82.80'
36
+ end
37
+
38
+ def lat_long
39
+ @ll ||= Geokit::Geocoders::MultiGeocoder.geocode(@address)
40
+ end
41
+
42
+ def longitude
43
+ lat_long.lng
44
+ end
45
+
46
+ def latitude
47
+ lat_long.lat
48
+ end
49
+
50
+ def longitude_west
51
+ -longitude
52
+ end
53
+
54
+
55
+
56
+ def get_offset
57
+ # see also http://www.hostip.info/
58
+ foo = open("http://www.earthtools.org/timezone-1.1/#{latitude}/#{longitude}").read
59
+ bar = foo.match(/<offset>(.*)<\/offset>/) if foo
60
+ if bar
61
+ @offset = bar[1].to_i
62
+ end
63
+ end
64
+
65
+ def get_timezone_offset
66
+ foo = open("http://www.askgeo.com/api/123016/vgdgoafgkvgdk6i9j26unjep4/timezone.json?points=#{latitude}%2C#{longitude}").read
67
+ bar = JSON.parse(foo)
68
+ if bar && bar['message'] == 'ok'
69
+ @offset = bar['data'].first['currentOffsetMs'].to_i / 3600000
70
+ end
71
+ end
72
+
73
+ def jrd
74
+ current_julian_date - JULIAN_2000
75
+ end
76
+
77
+ def current_julian_cycle
78
+ (current_julian_date - JULIAN_2000 - 0.0009 - (longitude_west / 360.0)).round
79
+ end
80
+
81
+
82
+ def solar_mean_anomaly # Mearth
83
+ # returns in degrees, 87.18
84
+ # Not sure if using approximate_solar_noon instead of current_julian_date is helpful or not
85
+ # Following this http://www.astro.uu.nl/~strous/AA/en/reken/zonpositie.html using current_julian_date
86
+ # ((357.5291 + 0.98560028 * (approximate_solar_noon - JULIAN_2000)) % 360).round(4) # this one is how wikipedia has it
87
+ ((357.5291 + 0.98560028 * (current_julian_date - JULIAN_2000)) % 360).round(4) # this on better for netherlands
88
+ end
89
+
90
+ def equation_of_center # Cearth
91
+ # returns in degrees 1.91
92
+ ((1.9148 * Math.sin(solar_mean_anomaly.degrees)) + (0.0200 * Math.sin((2 * solar_mean_anomaly).degrees)) + (0.0003 * Math.sin((3 * solar_mean_anomaly).degrees))).round(4)
93
+ end
94
+
95
+ def ecliptic_longitude # λsun
96
+ # returns in degrees 12.0321
97
+ # (solar_mean_anomaly + 102.9372 + 180) % 180
98
+ (solar_mean_anomaly + 102.9372 + equation_of_center + 180) % 360
99
+ end
100
+
101
+ def obliquity_of_the_equator # ε
102
+ 23.45
103
+ end
104
+
105
+ def l_sun
106
+ (solar_mean_anomaly + 102.9372 + 180) % 180
107
+ end
108
+
109
+ def sunset_jd_two
110
+ jpp + 0.0053 * Math.sin(solar_mean_anomaly.degrees) - 0.0069 * Math.sin((2 * l_sun).degrees)
111
+ end
112
+
113
+ def approximate_solar_noon # J(*)
114
+ (JULIAN_2000 + 0.0009 + (longitude_west / 360.0) + current_julian_cycle).round(4)
115
+ end
116
+
117
+ def asn_date
118
+ DateTime.jd(approximate_solar_noon)
119
+ end
120
+
121
+ def solar_transit
122
+ # Losing a lot of precision here :(
123
+ # not sure of these units, 2453097.0113
124
+ # 2453097.01224153
125
+ # (current_julian_date + (0.0053 * Math.sin(solar_mean_anomaly.degrees)) - (0.0069 * Math.sin((2 * ecliptic_longitude).degrees))).round(4)
126
+ (approximate_solar_noon + (0.0053 * Math.sin(solar_mean_anomaly.degrees)) - (0.0069 * Math.sin((2 * ecliptic_longitude).degrees))).round(4)
127
+ end
128
+
129
+ def declination_of_the_sun # δsun
130
+ # returns in degrees 4.7585
131
+ (Math.asin(Math.sin(ecliptic_longitude.degrees) * Math.sin(23.45.degrees))).round(5).radians
132
+ end
133
+
134
+
135
+ def right_ascension # αsun
136
+ (ecliptic_longitude + (-2.4680 * Math.sin((2 * ecliptic_longitude).degrees)) + (0.0530 * Math.sin((4 * ecliptic_longitude).degrees)) - (0.0014 * Math.sin((6 * ecliptic_longitude).degrees))).round(4)
137
+ end
138
+
139
+ def sidereal_time # θ
140
+ (((280.1600 + 360.9856235 * (current_julian_date - JULIAN_2000)) - (longitude_west)) % 360).round(4)
141
+ end
142
+
143
+ def hour_angle_two
144
+ sidereal_time - right_ascension
145
+ end
146
+
147
+ def hour_angle
148
+ # returns output in degrees
149
+ top = Math.sin(-0.83.degrees) - (Math.sin(latitude.degrees) * Math.sin(declination_of_the_sun.degrees))
150
+ bottom = Math.cos(latitude.degrees) * Math.cos(declination_of_the_sun.degrees)
151
+ tb = top / bottom
152
+ if((tb < -1.0) || (tb > 1.0))
153
+ return 0 # there is no sunrise or sunset on the given date for the given lat / long.
154
+ # Not sure what to return here, just hope for now that it doesn't happen.
155
+ end
156
+ # acos will blow up if input not in range (-1..1)
157
+ (Math.acos(tb).radians).round(4)
158
+ end
159
+
160
+ def jpp
161
+ JULIAN_2000 + 0.0009 + (hour_angle + (longitude_west)) * 1 / 360.0 + 1 * current_julian_cycle
162
+ end
163
+
164
+ def wiki_set # ends up close to sunset_jd, which is good i think
165
+ JULIAN_2000 + 0.0009 + (((hour_angle + (longitude_west)) / 360) + current_julian_cycle + 0.0053 * Math.sin(solar_mean_anomaly.degrees)) - 0.0069 * Math.sin((2 * ecliptic_longitude).degrees)
166
+ end
167
+
168
+ def sunset_jd
169
+ # puts "#{JULIAN_2000} + 0.0009 + (((#{hour_angle} + #{longitude}) / 360.0 ) + #{current_julian_cycle} + 0.0053 * Math.sin(#{solar_mean_anomaly})) - 0.0069 * Math.sin(2 * #{ecliptic_longitude})"
170
+ # foo = JULIAN_2000 + 0.0009 + (((hour_angle + longitude) / 360.0 ) + current_julian_cycle + 0.0053 * Math.sin(solar_mean_anomaly)) - 0.0069 * Math.sin(2 * ecliptic_longitude)
171
+ foo = jpp + 0.0053 * Math.sin(solar_mean_anomaly.degrees) - 0.0069 * Math.sin((2 * ecliptic_longitude).degrees)
172
+ foo.round(4)
173
+ end
174
+
175
+ def sunrise_jd
176
+ foo = solar_transit - (sunset_jd - solar_transit)
177
+ foo.round(4)
178
+ end
179
+
180
+ def sunset
181
+ foo = DateTime.jd(sunset_jd) + 12.hours
182
+ # foo = foo.new_offset(local_time.offset)
183
+ foo
184
+ end
185
+
186
+ def sunrise
187
+ foo = DateTime.jd(sunrise_jd) + 12.hours
188
+ # foo = foo.new_offset(local_time.offset)
189
+ foo
190
+ end
191
+
192
+ def sunrise_f
193
+ (sunrise + @offset.to_i.hours)
194
+ end
195
+
196
+ def sunset_f
197
+ (sunset + @offset.to_i.hours)
198
+ end
199
+
200
+ def length_of_day
201
+ (sunset - sunrise) * 24
202
+ end
203
+
204
+ def hour_ratio
205
+ length_of_day / 12.0
206
+ end
207
+
208
+ def nine
209
+ sunrise_f + (2 * hour_ratio).hours
210
+ end
211
+
212
+ def five
213
+ sunrise_f + (10 * hour_ratio).hours
214
+ end
215
+
216
+ def format_datetime(dt)
217
+ dt.strftime("%B %e %Y %T")
218
+ end
219
+
220
+
221
+
222
+
223
+
224
+ end
225
+
226
+
227
+
228
+ #Sundial.new.get_location
data/sundial.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "sundial/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "sundial"
7
+ s.version = Sundial::VERSION
8
+ s.authors = ["Bob Larrick"]
9
+ s.email = ["larrick@gmail.com"]
10
+ s.homepage = "https://github.com/deathbob/Sundial"
11
+ s.summary = %q{Gem to calculate the sunrise and sunset at your location}
12
+ s.description = %q{This gem calculates the sunrise and sunset at your current location.}
13
+
14
+ s.rubyforge_project = "sundial"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ # specify any dependencies here; for example:
22
+ # s.add_development_dependency "rspec"
23
+ s.add_runtime_dependency "activesupport"
24
+ s.add_runtime_dependency "geokit"
25
+
26
+ end
@@ -0,0 +1,121 @@
1
+ require 'minitest/autorun'
2
+
3
+ cal = File.join(File.dirname(__FILE__), '..', 'lib', 'sundial.rb')
4
+
5
+ puts File.exists? cal
6
+
7
+ require_relative File.join('..', 'lib', 'sundial')
8
+
9
+ class SunCalculatorTest < MiniTest::Unit::TestCase
10
+ def setup
11
+ @sc = Sundial.new
12
+ end
13
+
14
+ def test_local_time
15
+ assert @sc.local_time.to_i == DateTime.now.to_i
16
+ end
17
+
18
+ def test_julian_2000
19
+ assert Sundial::JULIAN_2000 == 2451545
20
+ end
21
+
22
+ def test_whatismyip
23
+ assert @sc.whatismyip == "http://www.whatismyip.org/"
24
+ end
25
+
26
+ describe Sundial do
27
+ before do
28
+ @sc = Sundial.new
29
+ end
30
+
31
+ describe 'current_julian_date' do
32
+ it 'should be today when no default is given' do
33
+ @sc.current_julian_date.must_equal Date.today.jd
34
+ end
35
+ it 'should be the default if default is given' do
36
+ cow = (Date.today - 1.days).jd
37
+ @sc.date = cow
38
+ @sc.current_julian_date.must_equal cow
39
+ end
40
+ end
41
+
42
+ describe 'address' do
43
+ # Address just needs to be something that can be geocoded.
44
+ it 'should default to my address' do
45
+ @sc.address.must_equal "Richmond, Virginia"
46
+ end
47
+
48
+ it 'should be whatever is given if set' do
49
+ cow = "71.1.2.3"
50
+ @sc.address = cow
51
+ @sc.address.must_equal cow
52
+ end
53
+ end
54
+
55
+ describe 'lat_long' do
56
+ before do
57
+ @latlng = Geokit::LatLng.new(37.5407246, -77.4360481)
58
+ @foo = Geokit::GeoLoc.new({:city =>'Richmond', :state => 'VA', :lat => @latlng.lat, :lng => @latlng.lng, :country_code => "US"})
59
+ end
60
+ # How to work VCR in here?
61
+ # it 'should geocode the default address' do
62
+ # @sc.lat_long.must_equal @foo
63
+ # end
64
+
65
+ describe 'given default address geocoded correctly' do
66
+ before do
67
+ @sc.ll = @foo
68
+ end
69
+ it 'should set latitude' do
70
+ @sc.latitude.must_be_close_to @latlng.lat
71
+ end
72
+ it 'should set longitude' do
73
+ @sc.longitude.must_be_close_to @latlng.lng
74
+ end
75
+ it 'should set the longitude_west to negative latitude' do
76
+ @sc.longitude_west.must_equal -@sc.longitude
77
+ end
78
+ describe "Getting the offset for the lat & lng" do
79
+ it 'should get_offset' do
80
+ @sc.get_offset.must_equal -5
81
+ @sc.offset.must_equal -5
82
+ end
83
+ it 'should get_timezone_offset' do
84
+ @sc.get_timezone_offset.must_equal -4
85
+ @sc.offset.must_equal -4
86
+ end
87
+ end
88
+ end
89
+
90
+ end
91
+
92
+ describe 'jrd' do
93
+ it 'should be the current_julian_date - JULIAN_2000' do
94
+ @sc.jrd.must_equal @sc.current_julian_date - Sundial::JULIAN_2000
95
+ end
96
+ end
97
+
98
+ end
99
+
100
+ end
101
+
102
+ # cloony
103
+
104
+ # expected_musts = %w(must_be
105
+ # must_be_close_to
106
+ # must_be_empty
107
+ # must_be_instance_of
108
+ # must_be_kind_of
109
+ # must_be_nil
110
+ # must_be_same_as
111
+ # must_be_silent
112
+ # must_be_within_delta
113
+ # must_be_within_epsilon
114
+ # must_equal
115
+ # must_include
116
+ # must_match
117
+ # must_output
118
+ # must_raise
119
+ # must_respond_to
120
+ # must_send
121
+ # must_throw)
metadata ADDED
@@ -0,0 +1,77 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sundial
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Bob Larrick
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-04-05 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: activesupport
16
+ requirement: &70204155777920 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70204155777920
25
+ - !ruby/object:Gem::Dependency
26
+ name: geokit
27
+ requirement: &70204155777420 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70204155777420
36
+ description: This gem calculates the sunrise and sunset at your current location.
37
+ email:
38
+ - larrick@gmail.com
39
+ executables: []
40
+ extensions: []
41
+ extra_rdoc_files: []
42
+ files:
43
+ - .rvmrc
44
+ - Gemfile
45
+ - Rakefile
46
+ - examples/driver.rb
47
+ - lib/numeric_extensions.rb
48
+ - lib/sundial.rb
49
+ - lib/sundial/version.rb
50
+ - sundial.gemspec
51
+ - test/sun_calculator_test.rb
52
+ homepage: https://github.com/deathbob/Sundial
53
+ licenses: []
54
+ post_install_message:
55
+ rdoc_options: []
56
+ require_paths:
57
+ - lib
58
+ required_ruby_version: !ruby/object:Gem::Requirement
59
+ none: false
60
+ requirements:
61
+ - - ! '>='
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ required_rubygems_version: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ requirements: []
71
+ rubyforge_project: sundial
72
+ rubygems_version: 1.8.15
73
+ signing_key:
74
+ specification_version: 3
75
+ summary: Gem to calculate the sunrise and sunset at your location
76
+ test_files:
77
+ - test/sun_calculator_test.rb