flexyear 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in flexyear.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Dan Melnick & Yan Pritzker
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,36 @@
1
+ # Flexyear
2
+
3
+ Flexible years! Parse decades, ranges, and etc into low & high values.
4
+
5
+ Examples:
6
+
7
+ FlexYear.new("1980s").year_low = 1980
8
+ FlexYear.new("1980s").year_high == 1989
9
+
10
+ FlexYear.new("mid-80s").year_low == 1983
11
+ FlexYear.new("mid-80s").year_high == 1986
12
+
13
+ It's pretty flexible in the kinds of things it takes. For more examples, see the spec.
14
+
15
+ ## Installation
16
+
17
+ Add this line to your application's Gemfile:
18
+
19
+ gem 'flexyear'
20
+
21
+ And then execute:
22
+
23
+ $ bundle
24
+
25
+ Or install it yourself as:
26
+
27
+ $ gem install flexyear
28
+
29
+
30
+ ## Contributing
31
+
32
+ 1. Fork it
33
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
34
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
35
+ 4. Push to the branch (`git push origin my-new-feature`)
36
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/flexyear.gemspec ADDED
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'flexyear/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "flexyear"
8
+ spec.version = Flexyear::VERSION
9
+ spec.authors = ["Dan Melnick & Yan Pritzker"]
10
+ spec.email = ["pair+dm+yp@reverb.com"]
11
+ spec.description = %q{Parse common year range formats like '1973-75' or natural language ranges like 'mid 80s'}
12
+ spec.summary = %q{Natural language year range parser}
13
+ spec.homepage = "http://github.com/reverbdev/flexyear"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ end
@@ -0,0 +1,3 @@
1
+ module Flexyear
2
+ VERSION = "0.0.1"
3
+ end
data/lib/flexyear.rb ADDED
@@ -0,0 +1,104 @@
1
+ require 'flexyear/version'
2
+ require 'date'
3
+
4
+ # Represents a flexible year entry:
5
+ #
6
+ # * 1979 - a specific year
7
+ # * 1970s and 70s - decades
8
+ # * mid-70s, early-70s, late-70s - subdecades, dashes optional
9
+ # * 1972-1975 - a range
10
+ #
11
+ # All years can be in two or four digit format
12
+ class FlexYear
13
+ class InvalidYearError < ArgumentError; end
14
+
15
+ attr_reader :year_low, :year_high
16
+
17
+ CIRCA_KEYWORDS = ["circ", "ca", "c.a.", "ca.", "cca", "c.", "approx", "appx", "about", "around"]
18
+
19
+ def initialize(year_string)
20
+ @year_string = year_string.to_s
21
+
22
+ if @year_string.start_with?("early")
23
+ @low = 0
24
+ @high = 3
25
+ elsif @year_string.start_with?("mid")
26
+ @low = 3
27
+ @high = 6
28
+ elsif @year_string.start_with?("late")
29
+ @low = 6
30
+ @high = 9
31
+ elsif @year_string.end_with?("s") # decade
32
+ @low = 0
33
+ @high = 9
34
+ elsif @year_string.include?("-")
35
+ @year_string =~ /(\d+)\s*-\s*(\d+)/
36
+ if $1 && $2
37
+ @year_low = centuryize($1).to_i
38
+ @year_high = centuryize($2, @year_low).to_i
39
+ return
40
+ end
41
+ elsif CIRCA_KEYWORDS.any?{|circa_pattern| @year_string.downcase.include?(circa_pattern)}
42
+ @low = -1
43
+ @high = 1
44
+ elsif @year_string.downcase.include?('reissue')
45
+ raise InvalidYearError, 'Please enter the date of manufacture, not the reissue era.'
46
+ else # specific year
47
+ @low = 0
48
+ @high = 0
49
+ end
50
+
51
+ parse_year
52
+ end
53
+
54
+ def to_s
55
+ @year_string
56
+ end
57
+
58
+ private
59
+
60
+ def centuryize(year, base_year=nil)
61
+ base = "19" # 19th century
62
+ if base_year
63
+ base = (base_year/100).to_s
64
+ end
65
+
66
+ if year.length == 1
67
+ "#{base}0#{year}"
68
+ elsif year.length == 2
69
+ "#{base}#{year}"
70
+ else
71
+ year
72
+ end
73
+ end
74
+
75
+ def parse_year
76
+ if @year_string =~ /(\d+).*s$/
77
+ @base_year = centuryize($1).to_i
78
+ elsif @year_string =~ /^\w+\s+(\d+)/
79
+ @base_year = centuryize($1).to_i
80
+ else
81
+ @base_year = @year_string.gsub(/\D+/,'').to_i
82
+ end
83
+
84
+ if @base_year > 9999
85
+ raise InvalidYearError, "Please use a four digit year."
86
+ end
87
+
88
+ @year_low = @base_year + (@low || -1)
89
+ @year_high = @base_year + (@high || 1)
90
+ end
91
+
92
+ # Represents a flexible year entry that must be in the past.
93
+ class Historical < FlexYear
94
+ private
95
+
96
+ def parse_year
97
+ super
98
+
99
+ if @base_year > DateTime.now.year
100
+ raise InvalidYearError, "The year must be in the past. You specified #{@base_year}; Today is #{DateTime.now.year}"
101
+ end
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,187 @@
1
+ require 'flexyear'
2
+
3
+ describe FlexYear do
4
+ context "given a blank string" do
5
+ subject { FlexYear.new("") }
6
+ its(:year_low) { should eq(0) }
7
+ its(:year_high) { should eq(0) }
8
+ end
9
+
10
+ context "given nil" do
11
+ subject { FlexYear.new(nil) }
12
+ its(:year_low) { should eq(0) }
13
+ its(:year_high) { should eq(0) }
14
+ end
15
+
16
+ context "text" do
17
+ subject { FlexYear.new("something") }
18
+ its(:year_low) { should eq(0) }
19
+ its(:year_high) { should eq(0) }
20
+ end
21
+
22
+ context "given 1979 as number" do
23
+ subject { FlexYear.new(1979) }
24
+ its(:year_low) { should eq(1979) }
25
+ its(:year_high) { should eq(1979) }
26
+ end
27
+
28
+ context "given 1979" do
29
+ subject { FlexYear.new("1979") }
30
+ its(:year_low) { should eq(1979) }
31
+ its(:year_high) { should eq(1979) }
32
+ end
33
+
34
+ context "given 1970s" do
35
+ subject { FlexYear.new("1970s") }
36
+ its(:year_low) { should eq(1970) }
37
+ its(:year_high) { should eq(1979) }
38
+ end
39
+
40
+ context "given 70s" do
41
+ subject { FlexYear.new("70s") }
42
+ its(:year_low) { should eq(1970) }
43
+ its(:year_high) { should eq(1979) }
44
+ end
45
+
46
+ context "given something with negative and dots" do
47
+ subject { FlexYear.new("approx.-2006") }
48
+ its(:year_low) { should eq(2005) }
49
+ its(:year_high) { should eq(2007) }
50
+ end
51
+
52
+ ["mid 1970s", "mid 70s", "mid-70s", "mid-70's"].each do |year|
53
+ context "given #{year}" do
54
+ subject { FlexYear.new(year) }
55
+ its(:year_low) { should eq(1973) }
56
+ its(:year_high) { should eq(1976) }
57
+ its(:to_s) { should eq(year) }
58
+ end
59
+ end
60
+
61
+ ["early 1970s", "early 70s", "early-70s", "early 70's"].each do |year|
62
+ context "given #{year}" do
63
+ subject { FlexYear.new(year) }
64
+ its(:year_low) { should eq(1970) }
65
+ its(:year_high) { should eq(1973) }
66
+ end
67
+ end
68
+
69
+ ["late 1970s", "late 70s", "late -70s", "late 70 s"].each do |year|
70
+ context "given #{year}" do
71
+ subject { FlexYear.new(year) }
72
+ its(:year_low) { should eq(1976) }
73
+ its(:year_high) { should eq(1979) }
74
+ end
75
+ end
76
+
77
+ ["73-75", "1973-1975", "1973 - 1975", "1973- 1975", "1973 -1975", "1973-75"].each do |range|
78
+ context "given a range #{range}" do
79
+ subject { FlexYear.new(range) }
80
+ its(:year_low) { should eq(1973) }
81
+ its(:year_high) { should eq(1975) }
82
+ end
83
+ end
84
+
85
+ context "given a range" do
86
+ ["2003-4", "2003-04"].each do |range|
87
+ subject { FlexYear.new(range) }
88
+ its(:year_low) { should eq(2003) }
89
+ its(:year_high) { should eq(2004) }
90
+ end
91
+ end
92
+
93
+ context 'given a reissue' do
94
+ specify do
95
+ expect { FlexYear.new('65 reissue') }.to raise_error(FlexYear::InvalidYearError)
96
+ end
97
+ end
98
+
99
+ context 'given a circa' do
100
+ context 'at the end of the string' do
101
+ subject { FlexYear.new('1973 (Circa)') }
102
+ its(:year_low) { should eq(1972) }
103
+ its(:year_high) { should eq(1974) }
104
+ end
105
+
106
+ context 'at the beginning of the string' do
107
+ subject { FlexYear.new('Circa 1973') }
108
+ its(:year_low) { should eq(1972) }
109
+ its(:year_high) { should eq(1974) }
110
+ end
111
+
112
+ context 'abbreviated' do
113
+ subject { FlexYear.new('ca 1973') }
114
+ its(:year_low) { should eq(1972) }
115
+ its(:year_high) { should eq(1974) }
116
+ end
117
+
118
+ context 'with dots' do
119
+ subject { FlexYear.new('c.a. 1973') }
120
+ its(:year_low) { should eq(1972) }
121
+ its(:year_high) { should eq(1974) }
122
+ end
123
+
124
+ context 'with c.' do
125
+ subject { FlexYear.new('c. 1973') }
126
+ its(:year_low) { should eq(1972) }
127
+ its(:year_high) { should eq(1974) }
128
+ end
129
+
130
+ context 'with ca.' do
131
+ subject { FlexYear.new('ca. 1973') }
132
+ its(:year_low) { should eq(1972) }
133
+ its(:year_high) { should eq(1974) }
134
+ end
135
+
136
+ context 'with approx.' do
137
+ subject { FlexYear.new('approx. 1973') }
138
+ its(:year_low) { should eq(1972) }
139
+ its(:year_high) { should eq(1974) }
140
+ end
141
+
142
+ context 'with appxly.' do
143
+ subject { FlexYear.new('appxly 1973') }
144
+ its(:year_low) { should eq(1972) }
145
+ its(:year_high) { should eq(1974) }
146
+ end
147
+
148
+ context 'with around' do
149
+ subject { FlexYear.new('around 1973') }
150
+ its(:year_low) { should eq(1972) }
151
+ its(:year_high) { should eq(1974) }
152
+ end
153
+
154
+ context 'with about' do
155
+ subject { FlexYear.new('about 1973') }
156
+ its(:year_low) { should eq(1972) }
157
+ its(:year_high) { should eq(1974) }
158
+ end
159
+
160
+ context 'with circ' do
161
+ subject { FlexYear.new('circ. 1973') }
162
+ its(:year_low) { should eq(1972) }
163
+ its(:year_high) { should eq(1974) }
164
+ end
165
+
166
+ context 'with cca' do
167
+ subject { FlexYear.new('cca 1973') }
168
+ its(:year_low) { should eq(1972) }
169
+ its(:year_high) { should eq(1974) }
170
+ end
171
+
172
+ end
173
+
174
+ context "given 12345 (five digit year)" do
175
+ specify do
176
+ expect { FlexYear.new('12345') }.to raise_error(FlexYear::InvalidYearError)
177
+ end
178
+ end
179
+
180
+ describe FlexYear::Historical do
181
+ context "given a year past today" do
182
+ specify do
183
+ expect { FlexYear::Historical.new('3000') }.to raise_error(FlexYear::InvalidYearError)
184
+ end
185
+ end
186
+ end
187
+ end
metadata ADDED
@@ -0,0 +1,95 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: flexyear
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 1
9
+ version: 0.0.1
10
+ platform: ruby
11
+ authors:
12
+ - Dan Melnick & Yan Pritzker
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2013-06-13 00:00:00 -05:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: bundler
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ~>
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 1
29
+ - 3
30
+ version: "1.3"
31
+ type: :development
32
+ version_requirements: *id001
33
+ - !ruby/object:Gem::Dependency
34
+ name: rake
35
+ prerelease: false
36
+ requirement: &id002 !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ segments:
41
+ - 0
42
+ version: "0"
43
+ type: :development
44
+ version_requirements: *id002
45
+ description: Parse common year range formats like '1973-75' or natural language ranges like 'mid 80s'
46
+ email:
47
+ - pair+dm+yp@reverb.com
48
+ executables: []
49
+
50
+ extensions: []
51
+
52
+ extra_rdoc_files: []
53
+
54
+ files:
55
+ - .gitignore
56
+ - Gemfile
57
+ - LICENSE.txt
58
+ - README.md
59
+ - Rakefile
60
+ - flexyear.gemspec
61
+ - lib/flexyear.rb
62
+ - lib/flexyear/version.rb
63
+ - spec/flexyear_spec.rb
64
+ has_rdoc: true
65
+ homepage: http://github.com/reverbdev/flexyear
66
+ licenses:
67
+ - MIT
68
+ post_install_message:
69
+ rdoc_options: []
70
+
71
+ require_paths:
72
+ - lib
73
+ required_ruby_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ segments:
78
+ - 0
79
+ version: "0"
80
+ required_rubygems_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ segments:
85
+ - 0
86
+ version: "0"
87
+ requirements: []
88
+
89
+ rubyforge_project:
90
+ rubygems_version: 1.3.6
91
+ signing_key:
92
+ specification_version: 3
93
+ summary: Natural language year range parser
94
+ test_files:
95
+ - spec/flexyear_spec.rb