airac 1.0.0

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 471214b4bbc235944a133c4e4fb5b18889a88daab2ac740cc46b6d49af0389a2
4
+ data.tar.gz: a2fec0e51d6625e029beaa45b5dc4e6490158773f69c738096cda61aff575909
5
+ SHA512:
6
+ metadata.gz: 79b78dbb5606224cc47d4750875373d3cf3fcbe04791d14415b26b7a37d96521759c85261a3796285ec42dc8c74c644608d1ee2aa81a6837f0480dec4094d404
7
+ data.tar.gz: 2e69a17ad1aa19ca18cdbc469b762f726dbdcf528f3c5fe13068e27d52856fa14d1eafa79c0e4be331f0cbfdfbd900b459375efa114e680f2941460cfac04cc1
checksums.yaml.gz.sig ADDED
Binary file
data/CHANGELOG.md ADDED
@@ -0,0 +1,6 @@
1
+ ## 1.0.0
2
+
3
+ #### Initial Implementation
4
+ * Require Ruby 3
5
+ * Simple AIRAC calculations and comparisons
6
+ * CLI tool
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2022 Sven Schwyn
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,86 @@
1
+ [![Version](https://img.shields.io/gem/v/airac.svg?style=flat)](https://rubygems.org/gems/airac)
2
+ [![Tests](https://img.shields.io/github/workflow/status/svoop/airac/Test.svg?style=flat&label=tests)](https://github.com/svoop/airac/actions?workflow=Test)
3
+ [![Code Climate](https://img.shields.io/codeclimate/maintainability/svoop/airac.svg?style=flat)](https://codeclimate.com/github/svoop/airac/)
4
+ [![Donorbox](https://img.shields.io/badge/donate-on_donorbox-yellow.svg)](https://donorbox.org/bitcetera)
5
+
6
+ # AIRAC
7
+
8
+ [AIRAC cycle](https://en.wikipedia.org/wiki/Aeronautical_Information_Publication) calculations for Ruby.
9
+
10
+ * [Homepage](https://github.com/svoop/airac)
11
+ * [API](https://www.rubydoc.info/gems/airac)
12
+ * Author: [Sven Schwyn - Bitcetera](https://bitcetera.com)
13
+
14
+ ## Install
15
+
16
+ ### Security
17
+
18
+ This gem is [cryptographically signed](https://guides.rubygems.org/security/#using-gems) in order to assure it hasn't been tampered with. Unless already done, please add the author's public key as a trusted certificate now:
19
+
20
+ ```
21
+ gem cert --add <(curl -Ls https://raw.github.com/svoop/airac/main/certs/svoop.pem)
22
+ ```
23
+
24
+ ### Bundler
25
+
26
+ Add the following to the <tt>Gemfile</tt> or <tt>gems.rb</tt> of your [Bundler](https://bundler.io) powered Ruby project:
27
+
28
+ ```ruby
29
+ gem airac
30
+ ```
31
+
32
+ And then install the bundle:
33
+
34
+ ```
35
+ bundle install --trust-policy MediumSecurity
36
+ ```
37
+
38
+ ## Usage
39
+
40
+ You can use this gem in your Ruby project:
41
+
42
+ ```ruby
43
+ cycle = AIRAC::Cycle.new('2018-01-01')
44
+ cycle.date # => #<Date: 2017-12-07 ((2458095j,0s,0n),+0s,2299161j)>
45
+ cycle.id # => 1713
46
+ (cycle + 5).id # => 1804
47
+ (cycle - 5).id # => 1708
48
+ ```
49
+
50
+ The cycle can be formatted similar to `Date#strftime`, however, the placeholder `%i` represents the AIRAC cycle ID:
51
+
52
+ ```ruby
53
+ cycle = AIRAC::Cycle.new('2018-01-01')
54
+ cycle.to_s # "1713 2017-12-07"
55
+ cycle.to_s("@%i as per %b %-d, %Y") # => "@1713 as per Dec 7, 2017"
56
+ ```
57
+
58
+ The current AIRAC cycle scheme started on 2015-06-25, therefore any calculation which leads to dates prior to inception will cause an error:
59
+
60
+ ```ruby
61
+ (cycle - 100).id # => ArgumentError
62
+ ```
63
+
64
+ The `AIRAC::Cycle` class implements `Comparable` and its instances can safely be used s `Hash` keys.
65
+
66
+ If you prefer to do the math on the shell, the `airac` executable is your friend:
67
+
68
+ ```shell
69
+ airac --help
70
+ ```
71
+
72
+ ## Development
73
+
74
+ To install the development dependencies and then run the test suite:
75
+
76
+ ```
77
+ bundle install
78
+ bundle exec rake # run tests once
79
+ bundle exec guard # run tests whenever files are modified
80
+ ```
81
+
82
+ You're welcome to [submit issues](https://github.com/svoop/airac/issues) and contribute code by [forking the project and submitting pull requests](https://docs.github.com/en/get-started/quickstart/fork-a-repo).
83
+
84
+ ## License
85
+
86
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/exe/airac ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/inline'
4
+
5
+ gemfile do
6
+ source 'https://rubygems.org'
7
+ ruby '>= 3.0.0'
8
+ gem 'airac'
9
+ end
10
+
11
+ AIRAC::Executable.new.run
@@ -0,0 +1,104 @@
1
+ module AIRAC
2
+
3
+ # AIRAC cycle date calculations
4
+ #
5
+ # @example
6
+ # cycle = AIRAC::Cycle.new('2018-01-01')
7
+ # cycle.date # => #<Date: 2017-12-07 ((2458095j,0s,0n),+0s,2299161j)>
8
+ # cycle.id # => 1713
9
+ # (cycle + 5).id # => 1804
10
+ # (cycle - 5).id # => 1708
11
+ # (cycle - 100).id # => ArgumentError
12
+ class Cycle
13
+ include Comparable
14
+
15
+ # First AIRAC date following the last cycle length modification
16
+ ROOT_DATE = Date.parse('2015-06-25').freeze
17
+
18
+ # Length of one AIRAC cycle
19
+ DAYS_PER_CYCLE = 28
20
+
21
+ # @return [Date] AIRAC effective on date
22
+ attr_reader :date
23
+
24
+ # @return [Integer] AIRAC cycle ID
25
+ attr_reader :id
26
+
27
+ # @param raw_cycle [Date, String, nil] either a four digit AIRAC cycle ID
28
+ # or any date within the AIRAC cycle
29
+ def initialize(raw_cycle=nil)
30
+ if raw_cycle.to_s.match?(/\A\d{4}\z/)
31
+ @id = raw_cycle.to_s
32
+ @date = date_for_id(@id)
33
+ else
34
+ raw_cycle = raw_cycle ? Date.parse(raw_cycle.to_s) : Date.today
35
+ fail(ArgumentError, "cannot calculate dates before #{ROOT_DATE}") if raw_cycle < ROOT_DATE
36
+ @date = date_for_date_within(raw_cycle)
37
+ @id = id_for(@date)
38
+ end
39
+ end
40
+
41
+ # @return [String]
42
+ def inspect
43
+ %Q(#<#{self.class} #{id} #{date}>)
44
+ end
45
+
46
+ # @param template [String, nil] strftime template with %i for AIRAC cycle
47
+ # (default: '%i %Y-%m-%d')
48
+ # @return [String]
49
+ def to_s(template=nil)
50
+ date.strftime((template || '%i %Y-%m-%d').sub(/%i/, id))
51
+ end
52
+
53
+ # @param days [Numerical] add this many days
54
+ # @return [AIRAC::Cycle] new object with offset applied
55
+ def +(cycles)
56
+ AIRAC::Cycle.new(@date + cycles * DAYS_PER_CYCLE)
57
+ end
58
+
59
+ # @param cycles [Numerical] subtract this many cycles
60
+ # @return [AIRAC::Cycle] new object with offset applied
61
+ def -(cycles)
62
+ self + -cycles
63
+ end
64
+
65
+ # @see Object#<=>
66
+ # @return [Integer]
67
+ def <=>(other)
68
+ id <=> other.id
69
+ end
70
+
71
+ # @see Object#==
72
+ # @return [Boolean]
73
+ def ==(other)
74
+ self.class === other && (self <=> other).zero?
75
+ end
76
+ alias_method :eql?, :==
77
+
78
+ # @see Object#hash
79
+ # @return [Integer]
80
+ def hash
81
+ to_s.hash
82
+ end
83
+
84
+ private
85
+
86
+ # Find the AIRAC date for given date within the cycle
87
+ def date_for_date_within(date_within)
88
+ ROOT_DATE + (date_within - ROOT_DATE).to_i / DAYS_PER_CYCLE * DAYS_PER_CYCLE
89
+ end
90
+
91
+ # Find the AIRAC date for given cycle ID
92
+ def date_for_id(id)
93
+ year = (Date.today.year.to_s[0,2] + id[0,2]).to_i
94
+ preceding_cycle = self.class.new(Date.parse("#{year}-01-01") - 1)
95
+ (preceding_cycle + id[2,2].to_i).date
96
+ end
97
+
98
+ # Find the AIRAC ID for the AIRAC +date+
99
+ def id_for(date)
100
+ '%04d' % ((date.year % 100) * 100 + ((date.yday - 1) / DAYS_PER_CYCLE) + 1)
101
+ end
102
+
103
+ end
104
+ end
@@ -0,0 +1,45 @@
1
+ module AIRAC
2
+
3
+ # Executable instantiated by the console tools
4
+ class Executable
5
+ attr_reader :options
6
+
7
+ def initialize
8
+ @options = {
9
+ format: nil,
10
+ offset: 0
11
+ }
12
+ OptionParser.new do |o|
13
+ o.banner = <<~END
14
+ Calculate AIRAC cycle from four digit ID or date within (default: today).
15
+ Usage: #{File.basename($0)} [options] [cycle]
16
+ END
17
+ o.on('-f', '--format TEMPLATE', String, "Template for strftime with %i for cycle ID") { @options[:format] = _1 }
18
+ o.on('-o', '--offset INTEGER', Integer, "Offset by this many cycles") { @options[:offset] = _1.to_i }
19
+ o.on('-A', '--about', 'show author/license information and exit') { about }
20
+ o.on('-V', '--version', 'show version and exit') { version }
21
+ end.parse!
22
+ @options[:raw_cycle] = ARGV.shift || Date.today
23
+ end
24
+
25
+ def run
26
+ puts (AIRAC::Cycle.new(options[:raw_cycle]) + options[:offset].to_i).to_s(options[:format])
27
+ rescue => error
28
+ message = error.respond_to?(:original_message) ? error.original_message : error.message
29
+ puts "ERROR: #{message}"
30
+ end
31
+
32
+ private
33
+
34
+ def about
35
+ puts 'Written by Sven Schwyn (bitcetera.com) and distributed under MIT license.'
36
+ exit
37
+ end
38
+
39
+ def version
40
+ puts AIRAC::VERSION
41
+ exit
42
+ end
43
+
44
+ end
45
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AIRAC
4
+ VERSION = "1.0.0"
5
+ end
data/lib/airac.rb ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'optparse'
4
+ require 'date'
5
+
6
+ require_relative "airac/version"
7
+ require_relative "airac/executable"
8
+ require_relative "airac/cycle"
data.tar.gz.sig ADDED
@@ -0,0 +1 @@
1
+ HRh���a�� �� ����/e8����q���F��ˑU�t�@�sB�=P,_�H7�$���_�=ߏ��!�A4��o��t��oLȈP����p�7��Q6�tۥk�X���9b���� kW����nȫ��}����>�RA\a(ھ����e%����Q����+(����#x�A��)���M��'�A�3�[\ٌ$�D���,��U��f�$m�� ��u�.Oeh�R��@���^�Ң��e���n�:��
metadata ADDED
@@ -0,0 +1,203 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: airac
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Sven Schwyn
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain:
11
+ - |
12
+ -----BEGIN CERTIFICATE-----
13
+ MIIDcDCCAligAwIBAgIBATANBgkqhkiG9w0BAQUFADA/MQ0wCwYDVQQDDARydWJ5
14
+ MRkwFwYKCZImiZPyLGQBGRYJYml0Y2V0ZXJhMRMwEQYKCZImiZPyLGQBGRYDY29t
15
+ MB4XDTIxMTEwODE0MzIyM1oXDTIyMTEwODE0MzIyM1owPzENMAsGA1UEAwwEcnVi
16
+ eTEZMBcGCgmSJomT8ixkARkWCWJpdGNldGVyYTETMBEGCgmSJomT8ixkARkWA2Nv
17
+ bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANwuD4geNdhpSVNJTtHb
18
+ fmVAoPxmER4oyGgaVJSidn/OjU5PcpdypMI/WIxfvjfFizq6kQYAsJZbCr6fG+UN
19
+ 2dZGMXcAC/uKQL5nYESjCPJ4IJP/SC+fiiEpxHQk7PNFoiUVRUieUZIAfHZAdnY3
20
+ ye1/niW7ud0vwKIMrysKWxjgkE0Y6Af1QLzV/6brVRRC5MvHIzYJd8BiSP+wY1O8
21
+ VElw1f6d90KEz2vaQfX7vCxrzIbvAnYiSvM0AIPy/zigTqpW6w3w4sQxQj81oQ9U
22
+ 9vDYtQzXj0c9VrSLvb0DgiGug2cU2bDjA4L3cBE1szX4tbfo8syYqMq51/kTGDxW
23
+ YNUCAwEAAaN3MHUwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAwHQYDVR0OBBYEFJ8r
24
+ wy1HraZDqg3Khf9UonMWMtJUMB0GA1UdEQQWMBSBEnJ1YnlAYml0Y2V0ZXJhLmNv
25
+ bTAdBgNVHRIEFjAUgRJydWJ5QGJpdGNldGVyYS5jb20wDQYJKoZIhvcNAQEFBQAD
26
+ ggEBACI7lJKRbnRjz0T4Wb9jH4SE0A2yaHAoBzj96luVDjNyoRT3688trEZS75Sg
27
+ GKfChxqKncBrSpxJ0YfWbymNHfUrKhcdSifJ/TtUrTasm6LSnJYLOnLKDO3v8eL3
28
+ gRTq8a5wA7Xtijx3MJEyzdeUh7N+UMKuPps/flPgH5yabUxgxrvuhrXF7Z96nrsP
29
+ EOmNMTc8H7wo4BAKfuMcI/Gh2oCf+tAhr0bGsXyBikmJ6XA45mrOMgv19M1+aMpn
30
+ 1+2Y1+i+4jd1B7qxIgOLxQTNIJiwE0sqU1itFfuesfgUACS7M0IV9u9Bp4hBGNEw
31
+ 5JcY2h7owdMxXIvgk1oakgldFJc=
32
+ -----END CERTIFICATE-----
33
+ date: 2022-01-22 00:00:00.000000000 Z
34
+ dependencies:
35
+ - !ruby/object:Gem::Dependency
36
+ name: rake
37
+ requirement: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ type: :development
43
+ prerelease: false
44
+ version_requirements: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ - !ruby/object:Gem::Dependency
50
+ name: minitest
51
+ requirement: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ type: :development
57
+ prerelease: false
58
+ version_requirements: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ - !ruby/object:Gem::Dependency
64
+ name: minitest-reporters
65
+ requirement: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ - !ruby/object:Gem::Dependency
78
+ name: minitest-sound
79
+ requirement: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ type: :development
85
+ prerelease: false
86
+ version_requirements: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ - !ruby/object:Gem::Dependency
92
+ name: minitest-focus
93
+ requirement: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ type: :development
99
+ prerelease: false
100
+ version_requirements: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ - !ruby/object:Gem::Dependency
106
+ name: guard
107
+ requirement: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ type: :development
113
+ prerelease: false
114
+ version_requirements: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ version: '0'
119
+ - !ruby/object:Gem::Dependency
120
+ name: guard-minitest
121
+ requirement: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ type: :development
127
+ prerelease: false
128
+ version_requirements: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - ">="
131
+ - !ruby/object:Gem::Version
132
+ version: '0'
133
+ - !ruby/object:Gem::Dependency
134
+ name: yard
135
+ requirement: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - ">="
138
+ - !ruby/object:Gem::Version
139
+ version: '0'
140
+ type: :development
141
+ prerelease: false
142
+ version_requirements: !ruby/object:Gem::Requirement
143
+ requirements:
144
+ - - ">="
145
+ - !ruby/object:Gem::Version
146
+ version: '0'
147
+ description: |
148
+ Calculations for AIRAC (Aeronautical Information Regulation And Control)
149
+ cycles.
150
+ email:
151
+ - ruby@bitcetera.com
152
+ executables:
153
+ - airac
154
+ extensions: []
155
+ extra_rdoc_files:
156
+ - README.md
157
+ - CHANGELOG.md
158
+ - LICENSE.txt
159
+ files:
160
+ - CHANGELOG.md
161
+ - LICENSE.txt
162
+ - README.md
163
+ - exe/airac
164
+ - lib/airac.rb
165
+ - lib/airac/cycle.rb
166
+ - lib/airac/executable.rb
167
+ - lib/airac/version.rb
168
+ homepage: https://github.com/svoop/airac
169
+ licenses:
170
+ - MIT
171
+ metadata:
172
+ homepage_uri: https://github.com/svoop/airac
173
+ changelog_uri: https://github.com/svoop/airac/blob/main/CHANGELOG.md
174
+ source_code_uri: https://github.com/svoop/airac
175
+ documentation_uri: https://www.rubydoc.info/gems/airac
176
+ bug_tracker_uri: https://github.com/svoop/airac/issues
177
+ post_install_message:
178
+ rdoc_options:
179
+ - "--title"
180
+ - AIRAC Calculations
181
+ - "--main"
182
+ - README.md
183
+ - "--line-numbers"
184
+ - "--inline-source"
185
+ - "--quiet"
186
+ require_paths:
187
+ - lib
188
+ required_ruby_version: !ruby/object:Gem::Requirement
189
+ requirements:
190
+ - - ">="
191
+ - !ruby/object:Gem::Version
192
+ version: 3.0.0
193
+ required_rubygems_version: !ruby/object:Gem::Requirement
194
+ requirements:
195
+ - - ">="
196
+ - !ruby/object:Gem::Version
197
+ version: '0'
198
+ requirements: []
199
+ rubygems_version: 3.3.5
200
+ signing_key:
201
+ specification_version: 4
202
+ summary: AIRAC cycle calculations
203
+ test_files: []
metadata.gz.sig ADDED
Binary file