season-formats 0.0.1 → 0.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 3edf7f8a24831832e08bcabae591f569f7ef9891
4
- data.tar.gz: 020f1325519b1406904320bb3027cc0ec9dccc98
2
+ SHA256:
3
+ metadata.gz: bbeb9fcb1439350cbd232816b8d9da2863084b8eae239fd24557e25e6423ab53
4
+ data.tar.gz: '0827fe61278de19885d3f9402a4b0c7c66375364919e4c652db56e9810c89e9c'
5
5
  SHA512:
6
- metadata.gz: 3a184826449d5adf254f059ad1b3b2a103356cf2c69676976ae349690407da0a53f01a0ed81ebfd8a490c38ffae32951e56005cf50484c2e08cec723233d7216
7
- data.tar.gz: 6f2d7c7822729d1fb2eba10804b5a7474dbdea1ee27a83c9b64df29b3ecd228811a655938f8bf307584645e03920a09a855fb4e0d44ccb6f03ebb9138ea1754b
6
+ metadata.gz: da35a1b898745e61deea9a27470f6a17fc00b69b09c8e078a25ad88ec0c185db57b8ad12075a4b01604bb7fe0b361ec9c8b78949761758084928ebae3bf8cbb8
7
+ data.tar.gz: ed5dfac8bb326f16445c06f6d7fb5efc5a73a7496b3e36f37a90a4e7f57f97d97395be76a24ed30ce249d80099084db6f71bbacefb9d8994260427a5b018e76b
data/CHANGELOG.md CHANGED
@@ -1,3 +1,5 @@
1
- ### 0.0.1 / 2020-11-22
2
-
3
- * Everything is new. First release.
1
+ ### 0.1.0
2
+
3
+ ### 0.0.1 / 2020-11-22
4
+
5
+ * Everything is new. First release.
data/Manifest.txt CHANGED
@@ -1,11 +1,9 @@
1
1
  CHANGELOG.md
2
2
  Manifest.txt
3
3
  README.md
4
- Rakefile
5
4
  lib/season-formats.rb
6
5
  lib/season-formats/season.rb
6
+ lib/season-formats/season_more.rb
7
7
  lib/season-formats/version.rb
8
8
  lib/season.rb
9
9
  lib/season/formats.rb
10
- test/helper.rb
11
- test/test_season.rb
data/README.md CHANGED
@@ -1,188 +1,187 @@
1
- # season-formats - read / parse and print seasons (using an academic or calendar year)
2
-
3
-
4
- * home :: [github.com/sportdb/sport.db](https://github.com/sportdb/sport.db)
5
- * bugs :: [github.com/sportdb/sport.db/issues](https://github.com/sportdb/sport.db/issues)
6
- * gem :: [rubygems.org/gems/season-formats](https://rubygems.org/gems/season-formats)
7
- * rdoc :: [rubydoc.info/gems/season-formats](http://rubydoc.info/gems/season-formats)
8
- * forum :: [opensport](http://groups.google.com/group/opensport)
9
-
10
-
11
-
12
- ## Usage
13
-
14
-
15
- The idea is to follow the `Date` class and make `Season`
16
- into a top-level free-standing class. Let's say you have
17
- the season (using an academic year):
18
-
19
- ```
20
- 2020/21 # or
21
- 2020/1 # or
22
- 2020/2021 # or
23
- 2020-21
24
- ...
25
- ```
26
-
27
-
28
- Using
29
-
30
- ``` ruby
31
- require "season/formats"
32
-
33
- season = Season.parse( "2020/21" ) # or
34
- season = Season.parse( "2020/1" ) # or
35
- season = Season.parse( "2020/2021" ) # or
36
- season = Season.parse( "2020-21" ) # or
37
-
38
- season.start_year #=> 2020
39
- season.end_year #=> 2021
40
-
41
- season.academic? # or
42
- season.academic_year? #=> true
43
-
44
- season.to_s #=> "2020/21"
45
- season.to_path #=> "2020-21"
46
- ```
47
-
48
- you can parse the season into its components, that is, the
49
- start year (`start_year`) and end year (`end year`).
50
-
51
- Using the `academic?` / `academic_year?`
52
- or `calendar?` / `calendar_year?` / `year?` helpers
53
- lets you check if the season uses an academic year (e.g. 2020/2021)
54
- or a calendar year (e.g. 2020).
55
-
56
-
57
- ``` ruby
58
- season = Season.parse( "2020" )
59
-
60
- season.start_year #=> 2020
61
- season.end_year #=> 2020
62
-
63
- season.calendar? # or
64
- season.calendar_year? # or
65
- season.year? #=> true
66
-
67
- season.to_s #=> "2020"
68
- season.to_path #=> "2020"
69
- ```
70
-
71
- Using `to_s` gets you back a canonical / normalized name
72
- (e.g. 2020/21 or 2020). For use in file names / paths
73
- use `to_path` (2020-21 or 2020).
74
-
75
-
76
-
77
-
78
- Like `Date` you can initialize `Season` with a "to-the-metal"
79
- year or years as integer numbers e.g.:
80
-
81
- ``` ruby
82
- season = Season.new( 2020, 2021 )
83
-
84
- season.start_year #=> 2020
85
- season.end_year #=> 2021
86
-
87
- season.academic? # or
88
- season.academic_year? #=> true
89
-
90
- season.to_s #=> "2020/21"
91
- season.to_path #=> "2020-21"
92
-
93
- # -or-
94
-
95
- season = Season.new( 2020 )
96
-
97
- season.start_year #=> 2020
98
- season.end_year #=> 2020
99
-
100
- season.calendar? # or
101
- season.calendar_year? # or
102
- season.year? #=> true
103
-
104
- season.to_s #=> "2020"
105
- season.to_path #=> "2020"
106
- ```
107
-
108
-
109
- If you want to support / allow both string and integers in your
110
- arguments, use the `Kernel#Season` method, that is,
111
- a shortcut for `Season.convert`. Example:
112
-
113
- ``` ruby
114
- season = Season( "2020/21" ) # or
115
- season = Season( "2020/1" ) # or
116
- season = Season( "2020/2021" ) # or
117
- season = Season( "2020-21" ) # or
118
- season = Season( 2020, 2021 ) # or
119
- season = Season( 202021 ) # or
120
- season = Season( 20202021 )
121
-
122
- # -or-
123
- season = Season( "2020" ) # or
124
- season = Season( 2020 )
125
- ```
126
-
127
-
128
-
129
- ### Bonus: Using Ranges with Seasons
130
-
131
- Yes, you can use the Season class for ruby's built-in ranges.
132
- Example:
133
-
134
- ``` ruby
135
- seasons = Season( '2010/11' )..Season( '2019/20' )
136
- seasons.to_a
137
- # => [2010/11, 2011/12, 2012/13, 2013/14, 2014/15,
138
- # 2015/16, 2016/17, 2017/18, 2018/19, 2019/20]
139
-
140
- seasons = Season( '2010' )..Season( '2019' )
141
- seasons.to_a
142
- # => [2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019]
143
- ```
144
-
145
- The "magic" is possible thanks to `Season#succ / next`
146
- and `Season#prev`.
147
-
148
- ``` ruby
149
- Season( '2019/20' ).succ # or
150
- Season( '2019/20' ).next #=> 2020/21
151
-
152
- Season( '2019/20' ).succ.succ # or
153
- Season( '2019/20' ).next.next #=> 2021/22
154
-
155
- # -or-
156
-
157
- Season( '2019' ).succ #=> 2020
158
- Season( '2019' ).next #=> 2020
159
- ```
160
-
161
-
162
- That's all for now.
163
-
164
-
165
-
166
- ## Installation
167
-
168
- Use
169
-
170
- gem install season-formats
171
-
172
- or add the gem to your Gemfile
173
-
174
- gem 'season-formats'
175
-
176
-
177
-
178
- ## License
179
-
180
- The `season-formats` scripts are dedicated to the public domain.
181
- Use it as you please with no restrictions whatsoever.
182
-
183
-
184
- ## Questions? Comments?
185
-
186
- Send them along to the
187
- [Open Sports & Friends Forum/Mailing List](http://groups.google.com/group/opensport).
188
- Thanks!
1
+ # season-formats - read / parse and print seasons (using an academic or calendar year)
2
+
3
+
4
+ * home :: [github.com/sportdb/sport.db](https://github.com/sportdb/sport.db)
5
+ * bugs :: [github.com/sportdb/sport.db/issues](https://github.com/sportdb/sport.db/issues)
6
+ * gem :: [rubygems.org/gems/season-formats](https://rubygems.org/gems/season-formats)
7
+ * rdoc :: [rubydoc.info/gems/season-formats](http://rubydoc.info/gems/season-formats)
8
+
9
+
10
+
11
+ ## Usage
12
+
13
+
14
+ The idea is to follow the `Date` class and make `Season`
15
+ into a top-level free-standing class. Let's say you have
16
+ the season (using an academic year):
17
+
18
+ ```
19
+ 2020/21 # or
20
+ 2020/1 # or
21
+ 2020/2021 # or
22
+ 2020-21
23
+ ...
24
+ ```
25
+
26
+
27
+ Using
28
+
29
+ ``` ruby
30
+ require "season/formats"
31
+
32
+ season = Season.parse( "2020/21" ) # or
33
+ season = Season.parse( "2020/1" ) # or
34
+ season = Season.parse( "2020/2021" ) # or
35
+ season = Season.parse( "2020-21" ) # or
36
+
37
+ season.start_year #=> 2020
38
+ season.end_year #=> 2021
39
+
40
+ season.academic? # or
41
+ season.academic_year? #=> true
42
+
43
+ season.to_s #=> "2020/21"
44
+ season.to_path #=> "2020-21"
45
+ ```
46
+
47
+ you can parse the season into its components, that is, the
48
+ start year (`start_year`) and end year (`end year`).
49
+
50
+ Using the `academic?` / `academic_year?`
51
+ or `calendar?` / `calendar_year?` / `year?` helpers
52
+ lets you check if the season uses an academic year (e.g. 2020/2021)
53
+ or a calendar year (e.g. 2020).
54
+
55
+
56
+ ``` ruby
57
+ season = Season.parse( "2020" )
58
+
59
+ season.start_year #=> 2020
60
+ season.end_year #=> 2020
61
+
62
+ season.calendar? # or
63
+ season.calendar_year? # or
64
+ season.year? #=> true
65
+
66
+ season.to_s #=> "2020"
67
+ season.to_path #=> "2020"
68
+ ```
69
+
70
+ Using `to_s` gets you back a canonical / normalized name
71
+ (e.g. 2020/21 or 2020). For use in file names / paths
72
+ use `to_path` (2020-21 or 2020).
73
+
74
+
75
+
76
+
77
+ Like `Date` you can initialize `Season` with a "to-the-metal"
78
+ year or years as integer numbers e.g.:
79
+
80
+ ``` ruby
81
+ season = Season.new( 2020, 2021 )
82
+
83
+ season.start_year #=> 2020
84
+ season.end_year #=> 2021
85
+
86
+ season.academic? # or
87
+ season.academic_year? #=> true
88
+
89
+ season.to_s #=> "2020/21"
90
+ season.to_path #=> "2020-21"
91
+
92
+ # -or-
93
+
94
+ season = Season.new( 2020 )
95
+
96
+ season.start_year #=> 2020
97
+ season.end_year #=> 2020
98
+
99
+ season.calendar? # or
100
+ season.calendar_year? # or
101
+ season.year? #=> true
102
+
103
+ season.to_s #=> "2020"
104
+ season.to_path #=> "2020"
105
+ ```
106
+
107
+
108
+ If you want to support / allow both string and integers in your
109
+ arguments, use the `Kernel#Season` method, that is,
110
+ a shortcut for `Season.convert`. Example:
111
+
112
+ ``` ruby
113
+ season = Season( "2020/21" ) # or
114
+ season = Season( "2020/1" ) # or
115
+ season = Season( "2020/2021" ) # or
116
+ season = Season( "2020-21" ) # or
117
+ season = Season( 2020, 2021 ) # or
118
+ season = Season( 202021 ) # or
119
+ season = Season( 20202021 )
120
+
121
+ # -or-
122
+ season = Season( "2020" ) # or
123
+ season = Season( 2020 )
124
+ ```
125
+
126
+
127
+
128
+ ### Bonus: Using Ranges with Seasons
129
+
130
+ Yes, you can use the Season class for ruby's built-in ranges.
131
+ Example:
132
+
133
+ ``` ruby
134
+ seasons = Season( '2010/11' )..Season( '2019/20' )
135
+ seasons.to_a
136
+ # => [2010/11, 2011/12, 2012/13, 2013/14, 2014/15,
137
+ # 2015/16, 2016/17, 2017/18, 2018/19, 2019/20]
138
+
139
+ seasons = Season( '2010' )..Season( '2019' )
140
+ seasons.to_a
141
+ # => [2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019]
142
+ ```
143
+
144
+ The "magic" is possible thanks to `Season#succ / next`
145
+ and `Season#prev`.
146
+
147
+ ``` ruby
148
+ Season( '2019/20' ).succ # or
149
+ Season( '2019/20' ).next #=> 2020/21
150
+
151
+ Season( '2019/20' ).succ.succ # or
152
+ Season( '2019/20' ).next.next #=> 2021/22
153
+
154
+ # -or-
155
+
156
+ Season( '2019' ).succ # or
157
+ Season( '2019' ).next #=> 2020
158
+ ```
159
+
160
+
161
+ That's all for now.
162
+
163
+
164
+
165
+ ## Installation
166
+
167
+ Use
168
+
169
+ gem install season-formats
170
+
171
+ or add the gem to your Gemfile
172
+
173
+ gem 'season-formats'
174
+
175
+
176
+
177
+ ## License
178
+
179
+ The `season-formats` scripts are dedicated to the public domain.
180
+ Use it as you please with no restrictions whatsoever.
181
+
182
+
183
+
184
+ ## Questions? Comments?
185
+
186
+ Yes, you can. More than welcome.
187
+ See [Help & Support »](https://github.com/openfootball/help)
@@ -1,7 +1,7 @@
1
- # note: allow require 'season/formats' too
2
- # (in addition to require 'season-formats')
3
-
4
- require_relative '../season-formats'
5
-
6
-
7
-
1
+ # note: allow require 'season/formats' too
2
+ # (in addition to require 'season-formats')
3
+
4
+ require_relative '../season-formats'
5
+
6
+
7
+
@@ -1,209 +1,209 @@
1
-
2
- ### note: make Season like Date a "top-level" / "generic" class
3
-
4
-
5
- class Season
6
- ##
7
- ## todo: add (optional) start_date and end_date - why? why not?
8
-
9
- ## todo/todo/todo/check/check/check !!!
10
- ## todo: add a kernel Seaons e.g. Season('2011/12')
11
- ## forward to Season.convert( *args ) - why? why not?
12
-
13
- ## todo: add unicode - too - why? why not? see wikipedia pages, for example
14
-
15
- YYYY_YYYY_RE = %r{^ ## e.g. 2011-2012 or 2011/2012
16
- (\d{4})
17
- [/-]
18
- (\d{4})
19
- $
20
- }x
21
- YYYY_YY_RE = %r{^ ## e.g. 2011-12 or 2011/12
22
- (\d{4})
23
- [/-]
24
- (\d{2})
25
- $
26
- }x
27
- YYYY_Y_RE = %r{^ ## e.g. 2011-2 or 2011/2
28
- (\d{4})
29
- [/-]
30
- (\d{1})
31
- $
32
- }x
33
- YYYY_RE = %r{^ ## e.g. 2011
34
- (\d{4})
35
- $
36
- }x
37
-
38
-
39
- def self.parse( str )
40
- new( *_parse( str ))
41
- end
42
-
43
- def self._parse( str ) ## "internal" parse helper
44
- if str =~ YYYY_YYYY_RE ## e.g. 2011/2012
45
- [$1.to_i, $2.to_i]
46
- elsif str =~ YYYY_YY_RE ## e.g. 2011/12
47
- fst = $1.to_i
48
- snd = $2.to_i
49
- snd_exp = '%02d' % [(fst+1) % 100] ## double check: e.g 00 == 00, 01==01 etc.
50
- raise ArgumentError, "[Season.parse] invalid year in season >>#{str}<<; expected #{snd_exp} but got #{$2}" if snd_exp != $2
51
- [fst, fst+1]
52
- elsif str =~ YYYY_Y_RE ## e.g. 2011/2
53
- fst = $1.to_i
54
- snd = $2.to_i
55
- snd_exp = '%d' % [(fst+1) % 10] ## double check: e.g 0 == 0, 1==1 etc.
56
- raise ArgumentError, "[Season.parse] invalid year in season >>#{str}<<; expected #{snd_exp} but got #{$2}" if snd_exp != $2
57
- [fst, fst+1]
58
- elsif str =~ YYYY_RE ## e.g. 2011
59
- [$1.to_i]
60
- else
61
- raise ArgumentError, "[Season.parse] unkown season format >>#{str}<<; sorry cannot parse"
62
- end
63
- end
64
-
65
-
66
- def self.convert( *args ) ## note: used by Kernel method Season()
67
- if args.size == 1 && args[0].is_a?( Season )
68
- args[0] # pass through / along as is 1:1
69
- elsif args.size == 1 && args[0].is_a?( String )
70
- parse( args[0] )
71
- elsif args.size == 1 && args[0].is_a?( Integer ) && args[0] > 9999
72
- ## note: allow convenience "hack" such as:
73
- # 202021 or 2020_21 => '2020/21' or
74
- # 2020_1 or 2020_1 => '2020/21' or
75
- # 20202021 or 2020_2021 => '2020/21'
76
- str = args[0].to_s
77
- parse( "#{str[0..3]}/#{str[4..-1]}" )
78
- else ## assume all integer args e.g. 2020 or 2020, 2021 and such
79
- new( *args ) ## try conversion with new
80
- end
81
- end
82
-
83
-
84
- attr_reader :start_year,
85
- :end_year
86
-
87
- def initialize( *args ) ## change args to years - why? why not?
88
- if args.size == 1 && args[0].is_a?( Integer )
89
- @start_year = args[0]
90
- @end_year = args[0]
91
- elsif args.size == 2 && args[0].is_a?( Integer ) &&
92
- args[1].is_a?( Integer )
93
- @start_year = args[0]
94
- @end_year = args[1]
95
- end_year_exp = @start_year+1
96
- raise ArgumentError, "[Season] invalid year in season >>#{to_s}<<; expected #{end_year_exp} but got #{@end_year}" if end_year_exp != @end_year
97
- else
98
- pp args
99
- raise ArgumentError, "[Season] expected season start year (integer) with opt. end year"
100
- end
101
- end
102
-
103
-
104
-
105
- ## single-year season e.g. 2011 if start_year is end_year - todo - find a better name?
106
- def calendar_year?() @start_year == @end_year; end
107
- alias_method :calendar?, :calendar_year?
108
- alias_method :year?, :calendar_year?
109
-
110
- def academic_year?() !calenar_year?; end
111
- alias_method :academic?, :academic_year?
112
-
113
-
114
-
115
- def prev
116
- if year?
117
- Season.new( @start_year-1 )
118
- else
119
- Season.new( @start_year-1, @end_year-1 )
120
- end
121
- end
122
-
123
- def next
124
- if year?
125
- Season.new( @start_year+1 )
126
- else
127
- Season.new( @start_year+1, @end_year+1 )
128
- end
129
- end
130
- alias_method :succ, :next ## add support for ranges
131
-
132
-
133
- include Comparable
134
- def <=>(other)
135
- ## todo/fix/fix: check if other is_a?( Season )!!!
136
- ## what to return if other type/class ??
137
- ## note: check special edge case - year season and other e.g.
138
- ## 2010 <=> 2010/2011
139
-
140
- res = @start_year <=> other.start_year
141
- res = @end_year <=> other.end_year if res == 0
142
- res
143
- end
144
-
145
-
146
- def to_formatted_s( format=:default, sep: '/' )
147
- if year?
148
- '%d' % @start_year
149
- else
150
- case format
151
- when :default, :short, :s ## e.g. 1999/00 or 2019/20
152
- "%d#{sep}%02d" % [@start_year, @end_year % 100]
153
- when :long, :l ## e.g. 1999/2000 or 2019/2020
154
- "%d#{sep}%d" % [@start_year, @end_year]
155
- else
156
- raise ArgumentError, "[Season.to_s] unsupported format >#{format}<"
157
- end
158
- end
159
- end
160
- alias_method :to_s, :to_formatted_s
161
-
162
- def key() to_s( :short ); end
163
- alias_method :to_key, :key
164
- alias_method :name, :key
165
- alias_method :title, :key
166
-
167
- alias_method :inspect, :key ## note: add inspect debug support change debug output to string!!
168
-
169
-
170
-
171
- def to_path( format=:default )
172
- case format
173
- when :default, :short, :s ## e.g. 1999-00 or 2019-20
174
- to_s( :short, sep: '-' )
175
- when :long, :l ## e.g. 1999-2000 or 2019-2000
176
- to_s( :long, sep: '-' )
177
- when :archive, :decade, :d ## e.g. 1990s/1999-00 or 2010s/2019-20
178
- "%3d0s/%s" % [@start_year / 10, to_s( :short, sep: '-' )]
179
- when :century, :c ## e.g. 1900s/1990-00 or 2000s/2019-20
180
- "%2d00s/%s" % [@start_year / 100, to_s( :short, sep: '-' )]
181
- else
182
- raise ArgumentError, "[Season.to_path] unsupported format >#{format}<"
183
- end
184
- end # method to_path
185
- alias_method :directory, :to_path ## keep "legacy" directory alias - why? why not?
186
- alias_method :path, :to_path
187
-
188
-
189
-
190
- #########################################
191
- ## more convenience helper - move to sportdb or such - remove - why - why not???
192
- def start_date ## generate "generic / syntetic start date" - keep helper - why? why not?
193
- if year?
194
- Date.new( start_year, 1, 1 )
195
- else
196
- Date.new( start_year 1, 7 )
197
- end
198
- end
199
-
200
-
201
- end # class Season
202
-
203
-
204
-
205
- ### note: add a convenience "shortcut" season kernel method conversion method
206
- ## use like Season( '2012/3' ) or such
207
- module Kernel
208
- def Season( *args ) Season.convert( *args ); end
1
+
2
+ ### note: make Season like Date a "top-level" / "generic" class
3
+
4
+
5
+ class Season
6
+ ##
7
+ ## todo: add (optional) start_date and end_date - why? why not?
8
+
9
+ ## todo/todo/todo/check/check/check !!!
10
+ ## todo: add a kernel Seaons e.g. Season('2011/12')
11
+ ## forward to Season.convert( *args ) - why? why not?
12
+
13
+ ## todo: add unicode - too - why? why not? see wikipedia pages, for example
14
+
15
+ YYYY_YYYY_RE = %r{^ ## e.g. 2011-2012 or 2011/2012
16
+ (\d{4})
17
+ [/-]
18
+ (\d{4})
19
+ $
20
+ }x
21
+ YYYY_YY_RE = %r{^ ## e.g. 2011-12 or 2011/12
22
+ (\d{4})
23
+ [/-]
24
+ (\d{2})
25
+ $
26
+ }x
27
+ YYYY_Y_RE = %r{^ ## e.g. 2011-2 or 2011/2
28
+ (\d{4})
29
+ [/-]
30
+ (\d{1})
31
+ $
32
+ }x
33
+ YYYY_RE = %r{^ ## e.g. 2011
34
+ (\d{4})
35
+ $
36
+ }x
37
+
38
+
39
+ def self.parse( str )
40
+ new( *_parse( str ))
41
+ end
42
+
43
+ def self._parse( str ) ## "internal" parse helper
44
+ if str =~ YYYY_YYYY_RE ## e.g. 2011/2012
45
+ [$1.to_i, $2.to_i]
46
+ elsif str =~ YYYY_YY_RE ## e.g. 2011/12
47
+ fst = $1.to_i
48
+ snd = $2.to_i
49
+ snd_exp = '%02d' % [(fst+1) % 100] ## double check: e.g 00 == 00, 01==01 etc.
50
+ raise ArgumentError, "[Season.parse] invalid year in season >>#{str}<<; expected #{snd_exp} but got #{$2}" if snd_exp != $2
51
+ [fst, fst+1]
52
+ elsif str =~ YYYY_Y_RE ## e.g. 2011/2
53
+ fst = $1.to_i
54
+ snd = $2.to_i
55
+ snd_exp = '%d' % [(fst+1) % 10] ## double check: e.g 0 == 0, 1==1 etc.
56
+ raise ArgumentError, "[Season.parse] invalid year in season >>#{str}<<; expected #{snd_exp} but got #{$2}" if snd_exp != $2
57
+ [fst, fst+1]
58
+ elsif str =~ YYYY_RE ## e.g. 2011
59
+ [$1.to_i]
60
+ else
61
+ raise ArgumentError, "[Season.parse] unkown season format >>#{str}<<; sorry cannot parse"
62
+ end
63
+ end
64
+
65
+
66
+ def self.convert( *args ) ## note: used by Kernel method Season()
67
+ if args.size == 1 && args[0].is_a?( Season )
68
+ args[0] # pass through / along as is 1:1
69
+ elsif args.size == 1 && args[0].is_a?( String )
70
+ parse( args[0] )
71
+ elsif args.size == 1 && args[0].is_a?( Integer ) && args[0] > 9999
72
+ ## note: allow convenience "hack" such as:
73
+ # 202021 or 2020_21 => '2020/21' or
74
+ # 2020_1 or 2020_1 => '2020/21' or
75
+ # 20202021 or 2020_2021 => '2020/21'
76
+ str = args[0].to_s
77
+ parse( "#{str[0..3]}/#{str[4..-1]}" )
78
+ else ## assume all integer args e.g. 2020 or 2020, 2021 and such
79
+ new( *args ) ## try conversion with new
80
+ end
81
+ end
82
+
83
+
84
+ attr_reader :start_year,
85
+ :end_year
86
+
87
+ def initialize( *args ) ## change args to years - why? why not?
88
+ if args.size == 1 && args[0].is_a?( Integer )
89
+ @start_year = args[0]
90
+ @end_year = args[0]
91
+ elsif args.size == 2 && args[0].is_a?( Integer ) &&
92
+ args[1].is_a?( Integer )
93
+ @start_year = args[0]
94
+ @end_year = args[1]
95
+ end_year_exp = @start_year+1
96
+ raise ArgumentError, "[Season] invalid year in season >>#{to_s}<<; expected #{end_year_exp} but got #{@end_year}" if end_year_exp != @end_year
97
+ else
98
+ pp args
99
+ raise ArgumentError, "[Season] expected season start year (integer) with opt. end year"
100
+ end
101
+ end
102
+
103
+
104
+
105
+ ## single-year season e.g. 2011 if start_year is end_year - todo - find a better name?
106
+ def calendar_year?() @start_year == @end_year; end
107
+ alias_method :calendar?, :calendar_year?
108
+ alias_method :year?, :calendar_year?
109
+
110
+ def academic_year?() !calendar_year?; end
111
+ alias_method :academic?, :academic_year?
112
+
113
+
114
+
115
+ def prev
116
+ if year?
117
+ Season.new( @start_year-1 )
118
+ else
119
+ Season.new( @start_year-1, @end_year-1 )
120
+ end
121
+ end
122
+
123
+ def next
124
+ if year?
125
+ Season.new( @start_year+1 )
126
+ else
127
+ Season.new( @start_year+1, @end_year+1 )
128
+ end
129
+ end
130
+ alias_method :succ, :next ## add support for ranges
131
+
132
+
133
+ include Comparable
134
+ def <=>(other)
135
+ ## todo/fix/fix: check if other is_a?( Season )!!!
136
+ ## what to return if other type/class ??
137
+ ## note: check special edge case - year season and other e.g.
138
+ ## 2010 <=> 2010/2011
139
+
140
+ res = @start_year <=> other.start_year
141
+ res = @end_year <=> other.end_year if res == 0
142
+ res
143
+ end
144
+
145
+
146
+ def to_formatted_s( format=:default, sep: '/' )
147
+ if year?
148
+ '%d' % @start_year
149
+ else
150
+ case format
151
+ when :default, :short, :s ## e.g. 1999/00 or 2019/20
152
+ "%d#{sep}%02d" % [@start_year, @end_year % 100]
153
+ when :long, :l ## e.g. 1999/2000 or 2019/2020
154
+ "%d#{sep}%d" % [@start_year, @end_year]
155
+ else
156
+ raise ArgumentError, "[Season.to_s] unsupported format >#{format}<"
157
+ end
158
+ end
159
+ end
160
+ alias_method :to_s, :to_formatted_s
161
+
162
+ def key() to_s( :short ); end
163
+ alias_method :to_key, :key
164
+ alias_method :name, :key
165
+ alias_method :title, :key
166
+
167
+ alias_method :inspect, :key ## note: add inspect debug support change debug output to string!!
168
+
169
+
170
+
171
+ def to_path( format=:default )
172
+ case format
173
+ when :default, :short, :s ## e.g. 1999-00 or 2019-20
174
+ to_s( :short, sep: '-' )
175
+ when :long, :l ## e.g. 1999-2000 or 2019-2000
176
+ to_s( :long, sep: '-' )
177
+ when :archive, :decade, :d ## e.g. 1990s/1999-00 or 2010s/2019-20
178
+ "%3d0s/%s" % [@start_year / 10, to_s( :short, sep: '-' )]
179
+ when :century, :c ## e.g. 1900s/1990-00 or 2000s/2019-20
180
+ "%2d00s/%s" % [@start_year / 100, to_s( :short, sep: '-' )]
181
+ else
182
+ raise ArgumentError, "[Season.to_path] unsupported format >#{format}<"
183
+ end
184
+ end # method to_path
185
+ alias_method :directory, :to_path ## keep "legacy" directory alias - why? why not?
186
+ alias_method :path, :to_path
187
+
188
+
189
+
190
+ #########################################
191
+ ## more convenience helper - move to sportdb or such - remove - why - why not???
192
+ def start_date ## generate "generic / syntetic start date" - keep helper - why? why not?
193
+ if year?
194
+ Date.new( start_year, 1, 1 )
195
+ else
196
+ Date.new( start_year 1, 7 )
197
+ end
198
+ end
199
+
200
+
201
+ end # class Season
202
+
203
+
204
+
205
+ ### note: add a convenience "shortcut" season kernel method conversion method
206
+ ## use like Season( '2012/3' ) or such
207
+ module Kernel
208
+ def Season( *args ) Season.convert( *args ); end
209
209
  end
@@ -0,0 +1,47 @@
1
+ ####
2
+ # add more experimental functionality to season class
3
+ # e.g. parse season ranges e.g. 2020..2024
4
+ # parse list of seasons incl. ranges e.g. 2020/21 2021/22..2023/24
5
+
6
+ class Season
7
+
8
+
9
+ def self.parse_range( str )
10
+ range = nil
11
+
12
+ fst,snd = str.split( '..' )
13
+ # pp [fst,snd]
14
+ fst = parse( fst )
15
+ snd = parse( snd )
16
+ if fst < snd && fst.year? == snd.year?
17
+ range = fst..snd
18
+ else
19
+ raise ArgumentError, "parse error - invalid season range >#{str}<, (1) two seasons required, (2) first < second, (3) same (year/academic) type"
20
+ end
21
+ range
22
+ end
23
+
24
+ # check - find a better name - why? why not?
25
+ ## e.g Season.parse_list or parse_lst
26
+ # or parse_multi(ple)?
27
+ def self.parse_line( str )
28
+ ## helper to parse seasons string/column
29
+ ## note: ALWAYS returns an array of seaons (even if only one)
30
+ result = []
31
+ seasons = str.split( /[ ]+/ )
32
+
33
+ seasons.each do |season_str|
34
+ ## note - add support for ranges e.g. 2001/02..2010/11
35
+ if season_str.index( '..' )
36
+ ## note - "unfold" range into array (use to_a)
37
+ result += parse_range( season_str ).to_a
38
+ else
39
+ result << parse( season_str )
40
+ end
41
+ end
42
+
43
+ result
44
+ end
45
+
46
+
47
+ end # class Season
@@ -1,19 +1,19 @@
1
-
2
- module SeasonFormats
3
- MAJOR = 0 ## todo: namespace inside version or something - why? why not??
4
- MINOR = 0
5
- PATCH = 1
6
- VERSION = [MAJOR,MINOR,PATCH].join('.')
7
-
8
- def self.version
9
- VERSION
10
- end
11
-
12
- def self.banner
13
- "season-formats/#{VERSION} on Ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}]"
14
- end
15
-
16
- def self.root
17
- File.expand_path( File.dirname(File.dirname(File.dirname(__FILE__))) )
18
- end
19
- end # module SeasonFormats
1
+
2
+ module SeasonFormats
3
+ MAJOR = 0 ## todo: namespace inside version or something - why? why not??
4
+ MINOR = 1
5
+ PATCH = 0
6
+ VERSION = [MAJOR,MINOR,PATCH].join('.')
7
+
8
+ def self.version
9
+ VERSION
10
+ end
11
+
12
+ def self.banner
13
+ "season-formats/#{VERSION} on Ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}] in (#{root})"
14
+ end
15
+
16
+ def self.root
17
+ File.expand_path( File.dirname(File.dirname(File.dirname(__FILE__))) )
18
+ end
19
+ end # module SeasonFormats
@@ -1,15 +1,15 @@
1
- require 'pp'
2
- require 'date'
3
- require 'time'
4
-
5
-
6
-
7
- ## our own code
8
- require 'season-formats/version' ## let version go first
9
- require 'season-formats/season'
10
-
11
-
12
-
13
-
14
-
15
- puts SeasonFormats.banner # say hello
1
+ require 'pp'
2
+ require 'date'
3
+ require 'time'
4
+
5
+
6
+
7
+ ## our own code
8
+ require_relative 'season-formats/version' ## let version go first
9
+ require_relative 'season-formats/season'
10
+ require_relative 'season-formats/season_more'
11
+
12
+
13
+
14
+
15
+ puts SeasonFormats.banner # say hello
data/lib/season.rb CHANGED
@@ -1,4 +1,4 @@
1
- # note: allow require simple 'season' too
2
- # (in addition to require 'season-formats')
3
-
4
- require_relative 'season-formats'
1
+ # note: allow require simple 'season' too
2
+ # (in addition to require 'season-formats')
3
+
4
+ require_relative 'season-formats'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: season-formats
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gerald Bauer
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-11-22 00:00:00.000000000 Z
11
+ date: 2025-05-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rdoc
@@ -36,17 +36,17 @@ dependencies:
36
36
  requirements:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
- version: '3.22'
39
+ version: '4.2'
40
40
  type: :development
41
41
  prerelease: false
42
42
  version_requirements: !ruby/object:Gem::Requirement
43
43
  requirements:
44
44
  - - "~>"
45
45
  - !ruby/object:Gem::Version
46
- version: '3.22'
46
+ version: '4.2'
47
47
  description: season-formats - read / parse and print seasons (using an academic or
48
48
  calendar year
49
- email: opensport@googlegroups.com
49
+ email: gerald.bauer@gmail.com
50
50
  executables: []
51
51
  extensions: []
52
52
  extra_rdoc_files:
@@ -57,19 +57,17 @@ files:
57
57
  - CHANGELOG.md
58
58
  - Manifest.txt
59
59
  - README.md
60
- - Rakefile
61
60
  - lib/season-formats.rb
62
61
  - lib/season-formats/season.rb
62
+ - lib/season-formats/season_more.rb
63
63
  - lib/season-formats/version.rb
64
64
  - lib/season.rb
65
65
  - lib/season/formats.rb
66
- - test/helper.rb
67
- - test/test_season.rb
68
66
  homepage: https://github.com/sportdb/sport.db
69
67
  licenses:
70
68
  - Public Domain
71
69
  metadata: {}
72
- post_install_message:
70
+ post_install_message:
73
71
  rdoc_options:
74
72
  - "--main"
75
73
  - README.md
@@ -79,16 +77,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
79
77
  requirements:
80
78
  - - ">="
81
79
  - !ruby/object:Gem::Version
82
- version: 2.2.2
80
+ version: 3.1.0
83
81
  required_rubygems_version: !ruby/object:Gem::Requirement
84
82
  requirements:
85
83
  - - ">="
86
84
  - !ruby/object:Gem::Version
87
85
  version: '0'
88
86
  requirements: []
89
- rubyforge_project:
90
- rubygems_version: 2.5.2
91
- signing_key:
87
+ rubygems_version: 3.5.22
88
+ signing_key:
92
89
  specification_version: 4
93
90
  summary: season-formats - read / parse and print seasons (using an academic or calendar
94
91
  year
data/Rakefile DELETED
@@ -1,27 +0,0 @@
1
- require 'hoe'
2
- require './lib/season-formats/version.rb'
3
-
4
- Hoe.spec 'season-formats' do
5
-
6
- self.version = SeasonFormats::VERSION
7
-
8
- self.summary = "season-formats - read / parse and print seasons (using an academic or calendar year"
9
- self.description = summary
10
-
11
- self.urls = { home: 'https://github.com/sportdb/sport.db' }
12
-
13
- self.author = 'Gerald Bauer'
14
- self.email = 'opensport@googlegroups.com'
15
-
16
- # switch extension to .markdown for gihub formatting
17
- self.readme_file = 'README.md'
18
- self.history_file = 'CHANGELOG.md'
19
-
20
- self.licenses = ['Public Domain']
21
-
22
- self.extra_deps = []
23
-
24
- self.spec_extras = {
25
- required_ruby_version: '>= 2.2.2'
26
- }
27
- end
data/test/helper.rb DELETED
@@ -1,8 +0,0 @@
1
- ## minitest setup
2
- require 'minitest/autorun'
3
-
4
-
5
- ## our own code
6
- require 'season/formats' ## or require 'season-formats'
7
-
8
-
data/test/test_season.rb DELETED
@@ -1,141 +0,0 @@
1
- ###
2
- # to run use
3
- # ruby -I ./lib -I ./test test/test_season.rb
4
-
5
-
6
- require 'helper'
7
-
8
- class TestSeason < MiniTest::Test
9
-
10
-
11
- def test_to_path
12
- assert_equal '2010-11', Season( '2010-11' ).to_path
13
- assert_equal '2010-11', Season( '2010-2011' ).to_path
14
- assert_equal '2010-11', Season( '2010/11' ).to_path
15
- assert_equal '2010-11', Season( '2010/1' ).to_path
16
- assert_equal '2010-11', Season( '2010/2011' ).to_path
17
- assert_equal '2010', Season( '2010' ).to_path
18
-
19
- assert_equal '2010-11', Season( 2010, 2011 ).to_path
20
- assert_equal '2010-11', Season( 2010_2011 ).to_path
21
- assert_equal '2010-11', Season( 20102011 ).to_path
22
- assert_equal '2010-11', Season( 201011 ).to_path
23
- assert_equal '2010-11', Season( 20101 ).to_path
24
- assert_equal '2010', Season( 2010 ).to_path
25
-
26
- assert_equal '2010s/2010-11', Season( '2010-11' ).to_path( :decade )
27
- assert_equal '2010s/2010-11', Season( '2010-2011' ).to_path( :decade )
28
- assert_equal '2010s/2010', Season( '2010' ).to_path( :decade )
29
-
30
- assert_equal '1999-00', Season( '1999-00' ).to_path
31
- assert_equal '1999-00', Season( '1999-2000' ).to_path
32
- assert_equal '1990s/1999-00', Season( '1999-00' ).to_path( :decade )
33
- assert_equal '1990s/1999-00', Season( '1999-2000' ).to_path( :decade )
34
-
35
- assert_equal '2000s/2010-11', Season( '2010-11' ).to_path( :century )
36
- assert_equal '2000s/2010-11', Season( '2010-2011' ).to_path( :century )
37
- assert_equal '2000s/2010', Season( '2010' ).to_path( :century )
38
-
39
- assert_equal '1900s/1999-00', Season( '1999-00' ).to_path( :century )
40
- assert_equal '1900s/1999-00', Season( '1999-2000' ).to_path( :century )
41
- end # method test_to_path
42
-
43
-
44
- def test_key
45
- assert_equal '2010/11', Season( '2010-11' ).key
46
- assert_equal '2010/11', Season( '2010-2011' ).key
47
- assert_equal '2010/11', Season( '2010/11' ).key
48
- assert_equal '2010/11', Season( '2010/1' ).key
49
- assert_equal '2010/11', Season( '2010/2011' ).key
50
- assert_equal '2010', Season( '2010' ).key
51
-
52
- assert_equal '1999/00', Season( '1999-00' ).key
53
- assert_equal '1999/00', Season( '1999-2000' ).key
54
- end # method test_key
55
-
56
-
57
- def test_years
58
- [Season( '1999-00' ),
59
- Season( '1999/00' ),
60
- Season( '1999/2000' ),
61
- Season( 1999, 2000 ),
62
- Season( 1999_00 ), ## allow "hacky" shortcuts - why? why not?
63
- Season( 1999_2000 ),
64
- ].each do |season|
65
- assert_equal 1999, season.start_year
66
- assert_equal 2000, season.end_year
67
- end
68
-
69
- [Season( '2010/1' ),
70
- Season( '2010/11' ),
71
- Season( 201011 ), ## allow "hacky" shortcuts - why? why not?
72
- Season( 20102011 ),
73
- ].each do |season|
74
- assert_equal 2010, season.start_year
75
- assert_equal 2011, season.end_year
76
- end
77
-
78
- [Season( '1999' ),
79
- Season( 1999 ),
80
- ].each do |season|
81
- assert_equal 1999, season.start_year
82
- assert_equal 1999, season.end_year
83
- end
84
-
85
- [Season( '2010' ),
86
- Season( 2010 ),
87
- ].each do |season|
88
- assert_equal 2010, season.start_year
89
- assert_equal 2010, season.end_year
90
- end
91
- end
92
-
93
-
94
- def test_prev
95
- assert_equal '2009/10', Season( '2010-11' ).prev.key
96
- assert_equal '2009/10', Season( '2010-2011' ).prev.key
97
- assert_equal '2009', Season( '2010' ).prev.key
98
-
99
- assert_equal '1998/99', Season( '1999-00' ).prev.key
100
- assert_equal '1998/99', Season( '1999-2000' ).prev.key
101
- end
102
-
103
- def test_next
104
- assert_equal '2009/10', Season( '2008-09' ).next.key
105
- assert_equal '2009/10', Season( '2008-2009' ).next.key
106
- assert_equal '2009', Season( '2008' ).next.key
107
-
108
- assert_equal '1998/99', Season( '1997-98' ).next.key
109
- assert_equal '1998/99', Season( '1997-1998' ).next.key
110
- end
111
-
112
-
113
- def test_range
114
- s2010 = Season( '2010' )..Season( '2019' )
115
- pp s2010.to_a
116
- # => [2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019]
117
-
118
- s2010 = Season( '2010-11')..Season( '2019-20')
119
- pp s2010.to_a
120
- # => [2010/11, 2011/12, 2012/13, 2013/14, 2014/15,
121
- # 2015/16, 2016/17, 2017/18, 2018/19, 2019/20]
122
-
123
- puts s2010 === Season( '2015-16' ) # true
124
- puts s2010 === Season( '2015' ) # !!!! false - why? if using >= <=
125
- puts s2010 === Season( '1999-00' ) # false
126
- puts s2010 === Season( '2020-21' ) # false
127
-
128
- puts
129
- puts s2010.include? Season( '2015-16' ) # true
130
- puts s2010.include? Season( '2015' ) # !!! false
131
- puts s2010.include? Season( '1999-00' ) # false
132
-
133
- assert_equal true, Season( '2010-11' ) < Season( '2015' )
134
- assert_equal true, Season( '2015' ) < Season( '2019-20' )
135
-
136
- assert_equal false, Season( '2015' ) == Season( '2015-16' )
137
- assert_equal true, Season( '2015' ) < Season( '2015-16' )
138
- assert_equal true, Season( '2015' ) == Season( '2015' )
139
- end
140
-
141
- end # class TestSeason