sun 0.1.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 62b638fc2309bc08dff55796cee15932fd4d791d
4
- data.tar.gz: c6c556fafabec3ea2d959d1c2c13c80299d15836
3
+ metadata.gz: 981419de39da6b66ce62873498c91aee04386fa0
4
+ data.tar.gz: 0232e38b4729004f092cfb1cb40e724c4167d3cb
5
5
  SHA512:
6
- metadata.gz: 0b8411da7c981e71efb2584e05278c7f001bb3ca069feb5281dcb7af8782b58d5f7d2ff83f7156ed14a2eb29c0412f8e91e789fbe3d6aaa9283a3637f54539ae
7
- data.tar.gz: 7747c1543b1769044b0430c7ed6257b88f4d903eb688e04aed82bc5521c3b016e2bdc3e6e942cf6ac77832b1d17473160273b5ce3fe187572d152883bf9a8b2c
6
+ metadata.gz: 01e62ce25b8f19b34c9be095521bb76c91cc534a5323154705b4ea0e3792f9bb6d9367369512f4cf292c0f37cf34de38ec7283fd6e671a0db27990b1c7be818f
7
+ data.tar.gz: 5845f933f5011c81a0089cb9f38eeff5862497c1d70b42fbd2cb58474a4fc2c771b19af6d7842d87b724576fa74a0166d72d67db8380e0ca0b010cd77e5b0094
data/.gitignore CHANGED
@@ -1,9 +1,6 @@
1
- /.bundle/
2
- /.yardoc
3
- /Gemfile.lock
4
- /_yardoc/
5
- /coverage/
6
- /doc/
7
- /pkg/
8
- /spec/reports/
9
- /tmp/
1
+ .bundle
2
+ .ruby-version
3
+ Gemfile.lock
4
+ coverage
5
+ pkg
6
+ tmp
data/README.md CHANGED
@@ -1,8 +1,16 @@
1
- # sun
1
+ # Sun
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/sun`. To experiment with that code, run `bin/consune` for an interactive prompt.
3
+ **Sunrise / sunset times for Ruby**
4
4
 
5
- TODO: Delete this and the text above, and describe your gem
5
+ * [Source Code]
6
+ * [API documentation]
7
+ * [Rubygem]
8
+
9
+ [Source Code]: https://github.com/allspiritseve/sun "Source code at Github"
10
+ [API documentation]: http://rubydoc.info/gems/sun/frames "RDoc API Documentation at RubyDoc.info"
11
+ [Rubygem]: http://rubygems.org/gems/sun "Ruby gem at RubyGems.org"
12
+
13
+ Sun is a solar calculator for Ruby based on the [National Oceanic & Atmospheric Administration (NOAA) solar calculator](http://www.esrl.noaa.gov/gmd/grad/solcalc/). Sunrise and sunset results are apparent times and not actual times (due to atmospheric refraction, apparent sunrise occurs shortly before the sun crosses above the horizon and apparent sunset occurs shortly after the sun crosses below the horizon).
6
14
 
7
15
  ## Installation
8
16
 
@@ -22,20 +30,46 @@ Or install it yourself as:
22
30
 
23
31
  ## Usage
24
32
 
25
- TODO: Write usage instructions here
33
+ ```ruby
34
+ time = Time.new(2015, 1, 1, 12, 0, 0, '-05:00')
35
+ latitude = 40.75
36
+ longitude = -73.99
26
37
 
27
- ## Development
38
+ # Sunrise
39
+ Sun.sunrise(time, latitude, longitude) # => 2015-01-01 07:20:02 -0500
28
40
 
29
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/consune` for an interactive prompt that will allow you to experiment.
41
+ # Solar noon
42
+ Sun.solar_noon(time, latitude, longitude) # => 2015-01-01 11:59:09 -0500
30
43
 
31
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
44
+ # Sunset
45
+ Sun.sunset(time, latitude, longitude) # => 2015-01-01 16:38:16 -0500
32
46
 
33
- ## Contributing
47
+ # Sunrise in minutes after midnight (UTC)
48
+ Sun.sunrise_minutes(time, latitude, longitude) # => 740.0366212342198
49
+
50
+ # Solar noon in minutes after midnight (UTC)
51
+ Sun.solar_noon(time, latitude, longitude) # => 1019.1596410575343
52
+
53
+ # Sunset in minutes after midnight (UTC)
54
+ Sun.sunset(time, latitude, longitude) # => 1298.2826608808487
55
+ ```
34
56
 
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/sun. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](contributor-covenant.org) code of conduct.
57
+ ## Notes
36
58
 
59
+ All of the above methods accept Date or Time objects for `time`. If a `Time` object is passed, the calculations will be performed on the return value of [`Time#to_date`](http://ruby-doc.org/stdlib-2.2.2/libdoc/date/rdoc/Time.html#method-i-to_date), which is timezone-dependent (for example, 1am in Michigan is 10pm on the previous day in California). To force calculations on a specific date regardless of timezone, pass a `Date` object.
60
+
61
+ Sun times are returned as [`Time`](http://ruby-doc.org/core-2.2.2/Time.html) objects in the local system timezone. To convert to a different timezone, you can use [`TZInfo::Timezone#utc_to_local`](http://www.rubydoc.info/gems/tzinfo/TZInfo/Timezone#utc_to_local-instance_method) or [`ActiveSupport::TimeZone#at`](http://api.rubyonrails.org/classes/ActiveSupport/TimeZone.html#method-i-at).
62
+
63
+ ## References
64
+
65
+ * [NOAA Solar Calculation Details](http://www.esrl.noaa.gov/gmd/grad/solcalc/calcdetails.html)
66
+ * [NOAA Solar Calculator](http://www.esrl.noaa.gov/gmd/grad/solcalc/)
67
+ * [Wikipedia: Sunrise equation](https://en.wikipedia.org/wiki/Sunrise_equation)
68
+
69
+ ## Contributing
70
+
71
+ Bug reports and pull requests are welcome on GitHub at https://github.com/allspiritseve/sun. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](contributor-covenant.org) code of conduct.
37
72
 
38
73
  ## License
39
74
 
40
75
  The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
41
-
data/Rakefile CHANGED
@@ -4,7 +4,7 @@ require "rake/testtask"
4
4
  Rake::TestTask.new(:test) do |t|
5
5
  t.libs << "test"
6
6
  t.libs << "lib"
7
- t.test_files = FileList['test/**/*_test.rb']
7
+ t.test_files = FileList['test/*_test.rb']
8
8
  end
9
9
 
10
10
  task :default => :test
@@ -0,0 +1,3 @@
1
+ machine:
2
+ ruby:
3
+ version: 2.2.2
data/lib/sun.rb CHANGED
@@ -1,34 +1,67 @@
1
+ require 'date'
1
2
  require 'sun/version'
2
3
 
3
4
  module Sun
5
+ # The approximate correction for atmospheric refraction at sunrise and sunset
4
6
  SOLAR_ZENITH = 90.833
5
7
 
6
- # Noon on January 1st, 2000
8
+ # 2000-01-01 12:00:00 UTC in Julian days
7
9
  JULIAN_CONSTANT = 2451545.to_r
8
10
 
9
- # Sun times
10
- def self.solar_noon(time, latitude, longitude)
11
- minutes = solar_noon_minutes(time, latitude, longitude)
12
- date_at_time(time.to_date, minutes)
11
+ class Error < StandardError
12
+ end
13
+
14
+ class InvalidTime < Error
15
+ end
16
+
17
+ class InvalidCoordinates < Error
13
18
  end
14
19
 
20
+ # Sun times (UTC)
21
+
15
22
  def self.sunrise(time, latitude, longitude)
16
- minutes = sunrise_minutes(time, latitude, longitude)
17
- date_at_time(time.to_date, minutes)
23
+ sun_time(:sunrise, time, latitude, longitude)
24
+ end
25
+
26
+ def self.solar_noon(time, latitude, longitude)
27
+ sun_time(:solar_noon, time, latitude, longitude)
18
28
  end
19
29
 
20
30
  def self.sunset(time, latitude, longitude)
21
- minutes = sunset_minutes(time, latitude, longitude)
22
- date_at_time(time.to_date, minutes)
31
+ sun_time(:sunset, time, latitude, longitude)
32
+ end
33
+
34
+ # Sun times in minutes after midnight (UTC)
35
+
36
+ def self.sunrise_minutes(time, latitude, longitude)
37
+ sun_time_minutes(:sunrise, time, latitude, longitude)
38
+ end
39
+
40
+ def self.solar_noon_minutes(time, latitude, longitude)
41
+ sun_time_minutes(:solar_noon, time, latitude, longitude)
42
+ end
43
+
44
+ def self.sunset_minutes(time, latitude, longitude)
45
+ sun_time_minutes(:sunset, time, latitude, longitude)
23
46
  end
24
47
 
25
48
  # Helpers
49
+
50
+ def self.date(time)
51
+ case time
52
+ when Date then time
53
+ when Time then time.to_date
54
+ else
55
+ raise InvalidTime, "must pass a Date or Time object"
56
+ end
57
+ end
58
+
26
59
  def self.degrees(radians)
27
- 180.0 * radians / Math::PI
60
+ Rational(180 * radians, Math::PI)
28
61
  end
29
62
 
30
63
  def self.radians(degrees)
31
- Math::PI * degrees / 180.0
64
+ Rational(Math::PI * degrees, 180)
32
65
  end
33
66
 
34
67
  def self.date_to_unix_time(date)
@@ -36,11 +69,42 @@ module Sun
36
69
  end
37
70
 
38
71
  def self.date_at_time(date, minutes)
39
- date_to_unix_time(date) + minutes * 60
72
+ Time.at(date_to_unix_time(date) + minutes * 60)
73
+ end
74
+
75
+ # Base our calculations off the astronomical julian date for our input time.
76
+ # Our formula is sensitive to time of day, so we ignore it in order to give
77
+ # consistent results for any time on the same date.
78
+ def self.sun_time(type, time, latitude, longitude)
79
+ date = date(time)
80
+ minutes = sun_time_minutes(type, date, latitude, longitude)
81
+ date_at_time(date, minutes)
40
82
  end
41
83
 
84
+ def self.sun_time_minutes(type, time, latitude, longitude)
85
+ date = date(time)
86
+ offset = offset_multiplier(type) * 4 * hour_angle(date, latitude)
87
+ 720 - (4 * longitude) - equation_of_time(date, longitude) + offset
88
+ rescue Math::DomainError
89
+ raise InvalidCoordinates, "Could not determine sun times for coordinates: #{latitude}, #{longitude}"
90
+ end
91
+
92
+ def self.offset_multiplier(type)
93
+ case type
94
+ when :sunrise then -1
95
+ when :solar_noon then 0
96
+ when :sunset then 1
97
+ end
98
+ end
99
+
100
+ # Calculations
101
+
42
102
  def self.julian_days(time)
43
- time.utc.to_datetime.ajd
103
+ if time.is_a?(Time)
104
+ time.to_datetime.ajd
105
+ else
106
+ date(time).ajd
107
+ end
44
108
  end
45
109
 
46
110
  def self.julian_century(time)
@@ -59,9 +123,8 @@ module Sun
59
123
  357.52911 + julian_century * (35999.05029 - 0.0001537 * julian_century)
60
124
  end
61
125
 
62
- # MOD(280.46646+G2*(36000.76983 + G2*0.0003032),360)
63
126
  def self.geometric_mean_longitude(julian_century)
64
- 280.46646 + julian_century * (36000.76983 + julian_century * 0.0003032) % 360
127
+ (280.46646 + julian_century * (36000.76983 + julian_century * 0.0003032)) % 360
65
128
  end
66
129
 
67
130
  def self.y(oblique_correction)
@@ -75,7 +138,6 @@ module Sun
75
138
  def self.equation_of_center(julian_century)
76
139
  geometric_mean_anomoly = geometric_mean_anomoly(julian_century)
77
140
  Math.sin(radians(geometric_mean_anomoly)) * (1.914602 - julian_century * (0.004817 + 0.000014 * julian_century)) + Math.sin(radians(2 * geometric_mean_anomoly)) * (0.019993 - 0.000101 * julian_century) + Math.sin(radians(3 * geometric_mean_anomoly)) * 0.00028
78
- # =SIN(RADIANS(J2))*(1.914602-G2*(0.004817+0.000014*G2))+SIN(RADIANS(2*J2))*(0.019993-0.000101*G2)+SIN(RADIANS(3*J2))*0.00028
79
141
  end
80
142
 
81
143
  def self.true_longitude(julian_century)
@@ -90,8 +152,8 @@ module Sun
90
152
  degrees(Math.asin(Math.sin(radians(oblique_correction)) * Math.sin(radians(apparent_longitude(julian_century)))))
91
153
  end
92
154
 
93
- def self.equation_of_time(time, longitude)
94
- julian_century = julian_century(time)
155
+ def self.equation_of_time(date, longitude)
156
+ julian_century = julian_century(date)
95
157
  oblique_correction = oblique_correction(julian_century)
96
158
  geometric_mean_anomoly = geometric_mean_anomoly(julian_century)
97
159
  geometric_mean_longitude = geometric_mean_longitude(julian_century)
@@ -100,22 +162,11 @@ module Sun
100
162
  4 * degrees(y * Math.sin(2 * radians(geometric_mean_longitude)) - 2 * eccentricity_of_earth_orbit * Math.sin(radians(geometric_mean_anomoly)) + 4 * eccentricity_of_earth_orbit * y * Math.sin(radians(geometric_mean_anomoly)) * Math.cos(2 * radians(geometric_mean_longitude)) - 0.5 * y * y * Math.sin(4 * radians(geometric_mean_longitude)) - 1.25 * eccentricity_of_earth_orbit * eccentricity_of_earth_orbit * Math.sin(2 * radians(geometric_mean_anomoly)))
101
163
  end
102
164
 
103
- def self.hour_angle(time, latitude)
104
- julian_century = julian_century(time)
165
+ def self.hour_angle(date, latitude)
166
+ julian_century = julian_century(date)
105
167
  oblique_correction = oblique_correction(julian_century)
106
168
  declination = declination(oblique_correction, julian_century)
107
- degrees(Math.acos(Math.cos(radians(90.833)) / (Math.cos(radians(latitude)) * Math.cos(radians(declination))) - Math.tan(radians(latitude)) * Math.tan(radians(declination))))
108
- end
109
-
110
- def self.solar_noon_minutes(time, latitude, longitude)
111
- 720 - (4 * longitude) - equation_of_time(time, longitude)
112
- end
113
-
114
- def self.sunrise_minutes(time, latitude, longitude)
115
- solar_noon_minutes(time, latitude, longitude) - 4 * hour_angle(time, latitude)
116
- end
117
-
118
- def self.sunset_minutes(time, latitude, longitude)
119
- solar_noon_minutes(time, latitude, longitude) + 4 * hour_angle(time, latitude)
169
+ res = Math.cos(radians(SOLAR_ZENITH)) / (Math.cos(radians(latitude)) * Math.cos(radians(declination))) - Math.tan(radians(latitude)) * Math.tan(radians(declination))
170
+ degrees(Math.acos(res))
120
171
  end
121
172
  end
@@ -1,3 +1,3 @@
1
1
  module Sun
2
- VERSION = "0.1.1"
2
+ VERSION = "1.0.0"
3
3
  end
@@ -9,18 +9,10 @@ Gem::Specification.new do |spec|
9
9
  spec.authors = ['Cory Kaufman-Schofield']
10
10
  spec.email = ['cory@corykaufman.com']
11
11
 
12
- spec.summary = 'Calculate sunrise and sunset for any place on earth'
12
+ spec.summary = 'Calculate sunrise and sunset times'
13
13
  spec.homepage = 'https://github.com/allspiritseve/sun'
14
14
  spec.license = 'MIT'
15
15
 
16
- # Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
17
- # delete this section to allow pushing this gem to any host.
18
- if spec.respond_to?(:metadata)
19
- spec.metadata['allowed_push_host'] = 'http://mygemserver.com'
20
- else
21
- raise 'RubyGems 2.0 or newer is required to protect against public gem pushes.'
22
- end
23
-
24
16
  spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^test/}) }
25
17
  spec.bindir = 'exe'
26
18
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
@@ -31,5 +23,5 @@ Gem::Specification.new do |spec|
31
23
  spec.add_development_dependency 'minitest'
32
24
  spec.add_development_dependency 'minitest-reporters'
33
25
  spec.add_development_dependency 'rake'
34
- spec.add_development_dependency 'tzinfo'
26
+ spec.add_development_dependency 'simplecov'
35
27
  end
metadata CHANGED
@@ -1,97 +1,97 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sun
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cory Kaufman-Schofield
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2015-09-04 00:00:00.000000000 Z
11
+ date: 2015-09-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '>='
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '0'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - '>='
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: byebug
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - '>='
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: '0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - '>='
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: minitest
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - '>='
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
47
  version: '0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - '>='
52
+ - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: minitest-reporters
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - '>='
59
+ - - ">="
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - '>='
66
+ - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rake
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - '>='
73
+ - - ">="
74
74
  - !ruby/object:Gem::Version
75
75
  version: '0'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - '>='
80
+ - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
83
  - !ruby/object:Gem::Dependency
84
- name: tzinfo
84
+ name: simplecov
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - '>='
87
+ - - ">="
88
88
  - !ruby/object:Gem::Version
89
89
  version: '0'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - '>='
94
+ - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
97
  description:
@@ -101,8 +101,8 @@ executables: []
101
101
  extensions: []
102
102
  extra_rdoc_files: []
103
103
  files:
104
- - .gitignore
105
- - .travis.yml
104
+ - ".gitignore"
105
+ - ".travis.yml"
106
106
  - CODE_OF_CONDUCT.md
107
107
  - Gemfile
108
108
  - LICENSE.txt
@@ -110,32 +110,32 @@ files:
110
110
  - Rakefile
111
111
  - bin/console
112
112
  - bin/setup
113
+ - circle.yml
113
114
  - lib/sun.rb
114
115
  - lib/sun/version.rb
115
116
  - sun.gemspec
116
117
  homepage: https://github.com/allspiritseve/sun
117
118
  licenses:
118
119
  - MIT
119
- metadata:
120
- allowed_push_host: http://mygemserver.com
120
+ metadata: {}
121
121
  post_install_message:
122
122
  rdoc_options: []
123
123
  require_paths:
124
124
  - lib
125
125
  required_ruby_version: !ruby/object:Gem::Requirement
126
126
  requirements:
127
- - - '>='
127
+ - - ">="
128
128
  - !ruby/object:Gem::Version
129
129
  version: '0'
130
130
  required_rubygems_version: !ruby/object:Gem::Requirement
131
131
  requirements:
132
- - - '>='
132
+ - - ">="
133
133
  - !ruby/object:Gem::Version
134
134
  version: '0'
135
135
  requirements: []
136
136
  rubyforge_project:
137
- rubygems_version: 2.0.14
137
+ rubygems_version: 2.4.8
138
138
  signing_key:
139
139
  specification_version: 4
140
- summary: Calculate sunrise and sunset for any place on earth
140
+ summary: Calculate sunrise and sunset times
141
141
  test_files: []