quando 0.0.2 → 0.0.8

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
  SHA256:
3
- metadata.gz: 8e5750a6507d6b1f1a1abdaba34591014a1288d24720b6ff2d24299ce2fdb5e0
4
- data.tar.gz: efc1b8ae6a9c67e55f6d941b5efbf112e869a5584060ed051f8959a0474d76fb
3
+ metadata.gz: dc9ef7c527d685d3da9942e1d53aff6017c012a7a25fc3e1fd47f667c2f94167
4
+ data.tar.gz: a1794e5af7f816d5b8edeb36bd8a762073f48afbcbc353a304d68bfd9c2a48e3
5
5
  SHA512:
6
- metadata.gz: 59173a1541b71b270872725d7b2a83a30218a6cc5d30b32265389f6443d19e00a86bb3fdad51fe4ef65333ffce05288e16f34c9cfdd71dad6f4a4ab1aa1dd5c2
7
- data.tar.gz: f9bb328ad18cec91a28119b3595a785d50774c94bcf3bc5bdfa41fd1fbce97d58d14e5c804d71c9102f59352edd0638d6533f3fc54acbff26b7ea60a8ac215d3
6
+ metadata.gz: 55afbcc5d55fd62967ed3dfbbcbccf4e23933cf44f98ae9249ff47f631c7c4a62c1dea93f6961da81d62035547d516849bd1527ca98bf060eff1a659b2a61e7a
7
+ data.tar.gz: d6e38f8106e168aeb5ce8b6c9e8f14108c00eff87fdba43dcf0edc75c2c1d330f248e777b461ff7378fdaa5b894a2181883013337764662b422b91ed15c2962b
data/.gitignore CHANGED
@@ -1,5 +1,7 @@
1
1
  .DS_Store
2
- pkg
3
- .idea/
4
- docker/*
2
+ .idea
3
+ .gem
4
+ bundle
5
5
  docker-compose.yml
6
+ pkg
7
+ up
data/.rspec CHANGED
@@ -1,2 +1,3 @@
1
1
  --format documentation
2
2
  --color
3
+ --require spec_helper
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- quando (0.0.2)
4
+ quando (0.0.8)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -12,7 +12,7 @@ GEM
12
12
  pry (0.11.3)
13
13
  coderay (~> 1.1.0)
14
14
  method_source (~> 0.9.0)
15
- rake (10.5.0)
15
+ rake (11.3.0)
16
16
  rspec (3.6.0)
17
17
  rspec-core (~> 3.6.0)
18
18
  rspec-expectations (~> 3.6.0)
@@ -31,11 +31,11 @@ PLATFORMS
31
31
  ruby
32
32
 
33
33
  DEPENDENCIES
34
- bundler (~> 1.15)
34
+ bundler (>= 1.15)
35
35
  pry
36
36
  quando!
37
- rake (~> 10.0)
38
- rspec (~> 3.0)
37
+ rake (~> 11)
38
+ rspec (>= 3.0)
39
39
 
40
40
  BUNDLED WITH
41
- 1.16.5
41
+ 1.17.2
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2018-2019 Sergey Konotopov
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 all
13
+ 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 THE
21
+ SOFTWARE.
data/README.md CHANGED
@@ -4,47 +4,207 @@
4
4
  [![Build Status](https://semaphoreci.com/api/v1/kinkou/quando/branches/master/shields_badge.svg)](https://semaphoreci.com/kinkou/quando)
5
5
  [![Maintainability](https://api.codeclimate.com/v1/badges/b0653fc45ec54c23e05c/maintainability)](https://codeclimate.com/github/kinkou/quando/maintainability)
6
6
 
7
- Quando is a configurable date parser. Show it what's what and parse any (Gregorian calendar) date. Quando can be configured on:
7
+ Quando is a configurable date parser which picks up where ```Date.strptime``` stops. It was made to work with non-standard, multi-language dates (that is, dates recorded by humans in languages other than English) but can be used for almost any date format.
8
+
9
+ A typical use case for Quando is dealing with input like:
10
+
11
+ ```text
12
+ "01 января 2019 г."
13
+ "1-ЯНВ-19"
14
+ "01.01.19"
15
+ "1/Jan/2019"
16
+ "yanvar'19"
17
+ "ЯНВ"
18
+ ```
19
+
20
+ This is a real-life example of how people would routinely write January 1, 2019 in Russia, but since many countries have their own words for month names, it might be a common problem.
21
+
22
+ ## How it works
23
+
24
+ ```bash
25
+ gem install quando
26
+ ```
27
+
28
+ and then
8
29
 
9
- #### Application-level:
10
30
  ```ruby
31
+ require 'quando'
32
+
11
33
  Quando.configure do |c|
12
- c.dlm = /[ ,-]/
34
+ # Define regular expressions to identify possible month names:
35
+ c.jan = /january|jan|yanvar|январь|января|янв/i # simplified for readability
36
+ # c.feb = …
37
+
38
+ # …more configuration…
39
+
40
+ # Then combine them into regexps that will match the date formats you accept:
41
+ c.formats = [
42
+ /#{c.day} #{c.month_txt} #{c.year} г\./i, # matches "01 января 2019 г."
43
+ /#{c.day}\.#{c.month_num}\.#{c.year2}/i, # matches "01.01.19"
44
+ /#{c.month_txt}'#{c.year2}/i, # matches "январь'19"
45
+ /#{c.month_txt}/i, # matches "ЯНВ"
46
+ ]
47
+ end
48
+
49
+ Quando.parse("01 января 2019 г.") #=> #<Date: 2019-01-01>
50
+ Quando.parse("01.01.19") #=> #<Date: 2019-01-01>
51
+ Quando.parse("январь'19") #=> #<Date: 2019-01-01>
52
+ Quando.parse("ЯНВ") #=> #<Date: 2019-01-01> (given that current year is 2019)
53
+ ```
54
+
55
+ ## Quando in detail
56
+
57
+ ### Configuration object
58
+
59
+ Configuration properties can be set by submitting a block to the ```Quando.configure``` method, as seen in the example above, or by calling the setter methods on the configuration object directly:
60
+
61
+ ```ruby
62
+ Quando.config.jun = /qershor|mehefin/ # Albanian and Welsh month names
63
+ Quando.config.jul = /korrik|gorffennaf/ # will make you cry
64
+ ```
65
+
66
+ ### Regular expressions
67
+
68
+ If you need to use grouping, remember that non-capturing groups ```(?:abc)``` provide better performance.
69
+
70
+ If, for some reason, you need to use named groups ```(?<name>abc)```, avoid names ```day```, ```month``` and ```year```. Quando uses them internally, so conflicts are possible.
71
+
72
+ ### Textual month matchers
73
+
74
+ To let Quando recognize months in your language you need to define corresponding regular expressions for all months:
75
+
76
+ ```ruby
77
+ Quando.configure do |c|
78
+ # In Finland, your matchers might look like this:
79
+ c.jan = /jan(?:uary)? | tammikuu(?:ta)? /xi
80
+ c.feb = /feb(?:ruary)? | helmikuu(?:ta)? /xi
81
+ c.mar = /mar(?:ch)? | maaliskuu(?:ta)?/xi
82
+ c.apr = /apr(?:il)? | huhtikuu(?:ta)? /xi
83
+ c.may = /may | toukokuu(?:ta)? /xi
84
+ c.jun = /june? | kesäkuu(?:ta)? /xi
85
+ c.jul = /july? | heinäkuu(?:ta)? /xi
86
+ c.aug = /aug(?:ust)? | elokuu(?:ta)? /xi
87
+ c.sep = /sep(?:tember)? | syyskuu(?:ta)? /xi
88
+ c.oct = /oct(?:ober)? | lokakuu(?:ta)? /xi
89
+ c.nov = /nov(?:ember)? | marraskuu(?:ta)?/xi
90
+ c.dec = /dec(?:ember)? | joulukuu(?:ta)? /xi
91
+
92
+ # …more configuration…
93
+ end
94
+ ```
95
+
96
+ ### Numerical matchers
97
+
98
+ Quando comes with defaults that will probably work in most situations:
99
+
100
+ ```Quando.config.day``` matches numbers from 1 to 31, both zero-padded and unpadded;
101
+
102
+ ```Quando.config.month_num``` matches numbers from 1 to 12, both zero-padded and unpadded;
13
103
 
14
- c.jan = /janeiro/i
15
- c.feb = /fevereiro/i
16
- c.mar = /março/i
17
- c.apr = /abril/i
18
- # …
19
- c.unimonth!
104
+ ```Quando.config.year``` matches any 4-digit sequence;
105
+ ```Quando.config.year2``` matches any 2-digit sequence.
20
106
 
107
+ If you need to adjust these matchers make sure that they produce named captures ```day```, ```month``` and ```year```, respectively:
108
+
109
+ ```ruby
110
+ Quando.config.day = /(?<day> …)/
111
+ Quando.config.month_num = /(?<month> …)/
112
+ Quando.config.year = /(?<year> …)/
113
+ ```
114
+
115
+ ### Delimiter matcher
116
+
117
+ By default, ```Quando.config.dlm``` will greedily match spaces, dashes, dots and slashes.
118
+
119
+ ### Format matchers
120
+
121
+ With format matchers you describe the concrete date formats that Quando will recognize. Within them you can include the date part matchers you defined previously.
122
+
123
+ ```Quando.config.day```, ```Quando.config.month_num```, ```Quando.config.month_txt```, ```Quando.config.year```, ```Quando.config.year2``` can be used.
124
+
125
+ ```Quando.config.month_txt``` is a regexp that automatically combines all textual month matchers, and will thus match any month.
126
+
127
+ ```ruby
128
+ Quando.configure do |c|
129
+ # …some initial configuration…
130
+
21
131
  c.formats = [
22
- /#{c.day} #{c.dlm} #{c.month_txt} #{c.dlm} #{c.year}/xi,
23
- /#{c.year} #{c.dlm} #{c.month_txt} #{c.dlm} #{c.day}/xi,
132
+ /^ #{c.day} #{c.dlm} #{c.month_txt} #{c.dlm} #{c.year} $/xi,
133
+ # compiles into something like
134
+ # /^ (?<day> …) [ -.\/]+ (?<month> jan|feb|…) [ -.\/]+ (?<year> …) $/xi
135
+ # and returns ~ #<MatchData "14 Apr 1965" day:"14" month:"Apr" year:"1965">
136
+ # on successful match
24
137
  ]
25
138
  end
139
+ ```
140
+
141
+ ### How dates are parsed
142
+
143
+ Quando matches regular expressions from ```Quando.config.formats```, *in the specified order*, against the input. If there is a match, the resulting ```MatchData``` object is analyzed.
144
+
145
+ If there is a named capture ```:day``` or ```:month```, either is used in the result, given that they are within correct range. If the format matcher did not define such named group, ```1``` is used:
146
+
147
+ ```ruby
148
+ Quando.config.formats = [
149
+ /#{Quando.config.month_num}\.#{Quando.config.year}/
150
+ ]
26
151
 
27
- Quando.parse('14-abril-1965') #=> #<Date: 1965-04-14>
28
- Quando.parse('1965, abril 14') #=> #<Date: 1965-04-14>
152
+ Quando.parse('04.2019') #=> #<Date: 2019-04-01>
29
153
  ```
30
154
 
31
- #### Instance-level:
32
- It will not affect your application-level configuration.
155
+ If there is a named capture ```:year```, it is used in the result. If the format matcher did not define such named group, current UTC year is used. If the captured value is less than ```100``` (which is the case for years written as 2-digit numbers), Quando will use the ```Quando.config.century``` setting (defaults to ```21```), effectively converting, for example, ```18``` to ```2018```. Be mindful of this behaviour, adjusting ```Quando.config.century``` accordingly:
156
+
157
+ ```ruby
158
+ Quando.config.formats = [Quando.config.year]
159
+ Quando.parse('2019') #=> #<Date: 2019-01-01>
160
+
161
+ Quando.config.formats = [Quando.config.year2]
162
+ Quando.parse('65') #=> #<Date: 2065-01-01>
163
+
164
+ Quando.parse('65', century: 20) #=> #<Date: 1965-01-01>
165
+ # or
166
+ Quando.config.century = 20
167
+ Quando.parse('65') #=> #<Date: 1965-01-01>
168
+ ```
169
+
170
+ ### Defaults
171
+
172
+ Out of the box, Quando will parse a reasonable variety of day-month-year ordered numerical and English textual dates. Some examples:
173
+
174
+ ```text
175
+ 14.4.1965, 14/04/1965, …
176
+ 14-apr-1965, 14 Apr 1965, …
177
+ April 1965, apr 1965, …
178
+ 13.12.05, 13-12-05, …
179
+ April, APR, …
180
+ ```
181
+
182
+ See ```Quando.config.formats``` for details.
183
+
184
+ ### Multiple ways to configure
185
+
186
+ You can configure Quando instances independently of each other and of the class:
187
+
33
188
  ```ruby
34
189
  Quando.parse('14-abril-1965') #=> nil
35
190
 
36
191
  date_parser = Quando::Parser.new.configure do |c|
37
- # here be the options from the previous example
192
+ # …some configuration…
38
193
  end
39
194
  date_parser.parse('14-abril-1965') #=> #<Date: 1965-04-14>
40
195
 
41
196
  Quando.parse('14-abril-1965') #=> nil
42
197
  ```
43
198
 
44
- #### Or just one-time usage:
199
+ or just pass a format matcher as a parameter:
200
+
45
201
  ```ruby
46
202
  m = /(?<year>#{Quando.config.year}) (?<day>\d\d) (?<month>[A-Z]+)/i
47
203
  Quando.parse('1965 14 Apr', matcher: m) #=> #<Date: 1965-04-14>
48
204
  ```
49
205
 
50
- Enjoy.
206
+ In both cases it will not change the global configuration (but note that calling setter methods on ```Quando.config``` will).
207
+
208
+ ### Requirements
209
+
210
+ Ruby >= 1.9.3. Enjoy!
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'quando'
5
+ require 'pry'
6
+
7
+ Pry.start
@@ -7,8 +7,10 @@ require 'quando/parser'
7
7
 
8
8
  module Quando
9
9
 
10
- # @param opts [Hash]
11
10
  # @param date [String]
11
+ # @param opts [Hash]
12
+ # @option opts [Regexp, Array<Regexp>] :matcher
13
+ # @option opts [Integer] :century
12
14
  # @return [Date, nil]
13
15
  def self.parse(date, opts = {})
14
16
  return if (date = date.to_s.strip).empty?
@@ -17,7 +19,13 @@ module Quando
17
19
 
18
20
  if opts[:matcher]
19
21
  p.configure do |c|
20
- c.formats = [opts[:matcher]]
22
+ c.formats = [opts[:matcher]].flatten
23
+ end
24
+ end
25
+
26
+ if opts[:century]
27
+ p.configure do |c|
28
+ c.century = opts[:century]
21
29
  end
22
30
  end
23
31
 
@@ -4,77 +4,118 @@
4
4
  module Quando
5
5
  class Config
6
6
 
7
- AVAILABLE_OPTIONS = [
8
- :dlm, :year, :day,
9
- :jan, :feb, :mar, :apr, :may, :jun, :jul, :aug, :sep, :oct, :nov, :dec,
10
- :month_num, :month_txt,
11
- :formats
12
- ]
7
+ MONTHS = [:jan, :feb, :mar, :apr, :may, :jun, :jul, :aug, :sep, :oct, :nov, :dec]
8
+ AUTOUPDATE = [:dlm, :year, :year2, :day, *MONTHS, :month_num]
9
+ COMPOUND = [:month_txt, :formats]
10
+ OPTIONS = [*AUTOUPDATE, *COMPOUND]
11
+ CENTURY = 21
13
12
 
14
- attr_accessor *AVAILABLE_OPTIONS
13
+ private_constant :AUTOUPDATE, :COMPOUND, :OPTIONS
15
14
 
16
- MONTHS = [:jan, :feb, :mar, :apr, :may, :jun, :jul, :aug, :sep, :oct, :nov, :dec]
15
+ attr_accessor *OPTIONS
17
16
 
18
17
  def initialize
19
- @dlm = /[ -.\/\\]/
20
- @year = /(?<year>(?:\d{2})|(?:\d{4}))/i
21
- @month_num = /(?<month>(?:1[0-2])|(?:0?[1-9]))/
22
- @day = /(?<day>(?:[3][0-1])|(?:[1-2][0-9])|(?:0?[1-9]))/
23
-
24
- @jan = /(?:JANUARY)|(?:JAN\.?)/i
25
- @feb = /(?:FEBRUARY)|(?:FEB\.?)/i
26
- @mar = /(?:MARCH)|(?:MAR\.?)/i
27
- @apr = /(?:APRIL)|(?:APR\.?)/i
28
- @may = /(?:MAY\.?)/i
29
- @jun = /(?:JUNE)|(?:JUN\.?)/i
30
- @jul = /(?:JULY)|(?:JUL\.?)/i
31
- @aug = /(?:AUGUST)|(?:AUG\.?)/i
32
- @sep = /(?:SEPTEMBER)|(?:SEPT?\.?)/i
33
- @oct = /(?:OCTOBER)|(?:OCT\.?)/i
34
- @nov = /(?:NOVEMBER)|(?:NOV\.?)/i
35
- @dec = /(?:DECEMBER)|(?:DEC\.?)/i
18
+ @dlm = /[- .\/]+/
19
+ @year = /(?<year>\d{4})/
20
+ @year2 = /(?<year>\d{2})/
21
+ @month_num = /(?<month> 1[012] | 0?[1-9])/x
22
+ @day = /(?<day> 3[01] | [12]\d | 0?[1-9])/x
23
+
24
+ @jan = /JAN(?:UARY)?/i
25
+ @feb = /FEB(?:RUARY)?/i
26
+ @mar = /MAR(?:CH)?/i
27
+ @apr = /APR(?:IL)?/i
28
+ @may = /MAY/i
29
+ @jun = /JUNE?/i
30
+ @jul = /JULY?/i
31
+ @aug = /AUG(?:UST)?/i
32
+ @sep = /SEP(?:TEMBER)?/i
33
+ @oct = /OCT(?:OBER)?/i
34
+ @nov = /NOV(?:EMBER)?/i
35
+ @dec = /DEC(?:EMBER)?/i
36
+
37
+ self.century=(CENTURY)
36
38
 
37
39
  uniupdate!
38
40
  end
39
41
 
42
+ # Sets @month_txt, a compound of all month regexps that matches any month name
43
+ def unimonth!
44
+ all_months_txt_rxs = MONTHS.map { |m| instance_variable_get("@#{m}".to_sym) }.join('|')
45
+ @month_txt = Regexp.new("(?<month>#{all_months_txt_rxs})", true)
46
+ end
47
+
48
+ # Sets @formats which is an array of regexps used in succession to match and identify date parts
40
49
  def uniformats!
41
50
  @formats = [
42
- # 14.4.1965, 14/04/1965, 13-12-05
43
- /\A\s* #{@day} #{@dlm} #{@month_num} #{@dlm} #{@year} \s*\z/xi,
51
+ # Formats with a 4-digits year
52
+ # 14.4.1965, 14/04/1965, 14-4-1965, 14 04 1965,
53
+ /^\s* #{@day} #{@dlm} #{@month_num} #{@dlm} #{@year} \s*$/xi,
54
+
55
+ # 14-APRIL-1965, 14-apr-1965, 14/Apr/1965, …
56
+ /^\s* #{@day} #{@dlm} #{@month_txt} #{@dlm} #{@year} \s*$/xi,
44
57
 
45
- # 14-APRIL-1965, 14-apr-65, 13/Dec/05,
46
- /\A\s* #{@day} #{@dlm} #{@month_txt} #{@dlm} #{@year} \s*\z/xi,
58
+ # April 1965, apr.1965, …
59
+ /^\s* #{@month_txt} #{@dlm} #{@year} \s*$/xi,
47
60
 
48
- # April 1965, apr.1965, DEC-05,
49
- /\A\s* #{@month_txt} #{@dlm} #{@year} \s*\z/xi,
61
+ # Same formats with a 2-digits year
62
+ # 13.12.05, 13/12/05, 13-12-05, …
63
+ /^\s* #{@day} #{@dlm} #{@month_num} #{@dlm} #{@year2} \s*$/xi,
50
64
 
51
- # April, DECEMBER, apr., …
52
- /\A\s* #{@month_txt} \s*\z/xi,
65
+ # April, DECEMBER, sep., …
66
+ /^\s* #{@month_txt} \s*$/xi,
53
67
  ]
54
68
  end
55
69
 
56
- def unimonth!
57
- all_months_txt_rxs = MONTHS.map { |m| instance_variable_get("@#{m}".to_sym) }.join('|')
58
- @month_txt = Regexp.new("(?<month>#{all_months_txt_rxs})", true)
70
+ # @return [Integer]
71
+ def century
72
+ @century
73
+ end
74
+
75
+ # @param value [Integer]
76
+ # @return [Integer]
77
+ def century=(value)
78
+ @century = (value == 0 ? 1 : value) || CENTURY
59
79
  end
60
80
 
81
+ # A single method to update all compound matchers when a part matcher was changed
61
82
  def uniupdate!
62
83
  unimonth!
63
84
  uniformats!
64
85
  end
65
86
 
87
+ # Batch-define setters for date part matchers (listed in AUTOUPDATE) that, when set,
88
+ # automatically update the compound matchers (listed in COMPOUND)
89
+ AUTOUPDATE.each do |var|
90
+ # def jan=(regexp)
91
+ # return regexp if @jan == regexp
92
+ # @jan = regexp
93
+ # uniupdate!
94
+ # end
95
+ define_method("#{var}=".to_sym) do |regexp|
96
+ var_name = "@#{var}".to_sym
97
+ return regexp if instance_variable_get(var_name) == regexp
98
+ instance_variable_set(var_name, regexp)
99
+ uniupdate!
100
+ end
101
+ end
66
102
  end
67
103
 
104
+ # Quando's class-level configuration
68
105
  # @return [Quando::Config]
69
106
  def self.config
70
107
  @config ||= Config.new
71
108
  end
72
109
 
110
+ # @return [Quando::Config]
73
111
  def self.configure
74
112
  config unless @config
75
113
  yield(config) if block_given?
114
+ @config
76
115
  end
77
116
 
117
+ # Reset Quando's class-level configuration to defaults
118
+ # @return [Quando::Config]
78
119
  def self.reset!
79
120
  @config = Config.new
80
121
  end
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Quando
4
-
5
4
  class Parser
6
5
 
7
6
  def initialize
@@ -10,7 +9,7 @@ module Quando
10
9
 
11
10
  # @return [Quando::Parser]
12
11
  def configure
13
- yield(@config = Quando.config.dup)
12
+ yield(@config ||= Quando.config.dup)
14
13
  self
15
14
  end
16
15
 
@@ -22,11 +21,11 @@ module Quando
22
21
  # @param text_date [String]
23
22
  # @return [Date, nil]
24
23
  def parse(text_date)
25
- config.formats.each do |rx|
26
- @date_parts = text_date.match(rx)
24
+ config.formats.each do |regexp|
25
+ @date_parts = text_date.match(regexp)
27
26
  next unless @date_parts
28
27
 
29
- @current_format = rx
28
+ @current_format = regexp
30
29
  year, month, day = detect_year, detect_month, detect_day
31
30
  next unless (year && month && day)
32
31
 
@@ -40,39 +39,39 @@ module Quando
40
39
 
41
40
  # @return [Integer, nil]
42
41
  def detect_year
43
- return Time.now.year unless searched?(:year)
42
+ return Time.now.utc.year unless wanted?(:year)
44
43
  return unless found?(:year)
45
44
 
46
45
  year = @date_parts[:year].to_i
47
- year < 100 ? year + 2000 : year
46
+ year.abs < 100 ? year + century_to_hundreds : year
48
47
  end
49
48
 
50
49
  # @return [Integer, nil]
51
50
  def detect_month
52
- return 1 unless searched?(:month)
51
+ return 1 unless wanted?(:month)
53
52
  return unless found?(:month)
54
53
 
55
54
  month = @date_parts[:month]
56
55
 
57
- if config.month_num.match(month)
58
- month.to_i
59
- else
60
- month_index = Quando::Config::MONTHS.find_index do |month_name|
61
- month_name_rx = config.send(month_name)
62
- month_name_rx.match(month)
63
- end
56
+ month_index = Quando::Config::MONTHS.find_index do |month_name|
57
+ config.send(month_name) =~ month
58
+ end
64
59
 
65
- month_index + 1 if month_index
60
+ if month_index
61
+ month_index += 1
62
+ return month_index if valid_month?(month_index)
66
63
  end
64
+
65
+ month.to_i if valid_month?(month)
67
66
  end
68
67
 
69
68
  # @return [Integer, nil]
70
69
  def detect_day
71
- return 1 unless searched?(:day)
70
+ return 1 unless wanted?(:day)
72
71
  return unless found?(:day)
73
72
 
74
73
  day = @date_parts[:day].to_i
75
- day if (1..31).include?(day)
74
+ day if valid_day?(day)
76
75
  end
77
76
 
78
77
  # @param date_part [Symbol]
@@ -81,10 +80,23 @@ module Quando
81
80
  end
82
81
 
83
82
  # @param date_part [Symbol]
84
- def searched?(date_part)
85
- !!@current_format.named_captures[date_part.to_s]
83
+ def wanted?(date_part)
84
+ @current_format.names.include?(date_part.to_s)
86
85
  end
87
86
 
88
- end
87
+ # @param value [Integer]
88
+ def valid_month?(value)
89
+ (1..12).include?(value.to_i)
90
+ end
89
91
 
92
+ # @param value [Integer]
93
+ def valid_day?(value)
94
+ (1..31).include?(value.to_i)
95
+ end
96
+
97
+ def century_to_hundreds
98
+ (config.century > 0 ? config.century - 1 : config.century + 1) * 100
99
+ end
100
+
101
+ end
90
102
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Quando
4
- VERSION = '0.0.2'
4
+ VERSION = '0.0.8'
5
5
  end
@@ -11,14 +11,17 @@ Gem::Specification.new do |spec|
11
11
  spec.summary = %q{Configurable date parser}
12
12
  spec.description = %q{Parse dates in any language and format by setting your own recognition patterns}
13
13
  spec.homepage = 'https://github.com/kinkou/quando'
14
+ spec.license = 'MIT'
14
15
 
15
16
  spec.files = `git ls-files -z`.split("\x0").reject do |f|
16
17
  f.match(%r{^(test|spec|features)/})
17
18
  end
18
19
  spec.require_paths = ['lib']
19
20
 
20
- spec.add_development_dependency 'bundler', '~> 1.15'
21
- spec.add_development_dependency 'rake', '~> 10.0'
22
- spec.add_development_dependency 'rspec', '~> 3.0'
21
+ spec.required_ruby_version = '>= 1.9.3'
22
+
23
+ spec.add_development_dependency 'bundler', '>= 1.15'
24
+ spec.add_development_dependency 'rake', '~> 11'
25
+ spec.add_development_dependency 'rspec', '>= 3.0'
23
26
  spec.add_development_dependency 'pry'
24
27
  end
metadata CHANGED
@@ -1,27 +1,27 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: quando
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sergey Konotopov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-10-13 00:00:00.000000000 Z
11
+ date: 2020-07-29 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: '1.15'
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: '1.15'
27
27
  - !ruby/object:Gem::Dependency
@@ -30,26 +30,26 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '10.0'
33
+ version: '11'
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
- version: '10.0'
40
+ version: '11'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - "~>"
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
47
  version: '3.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: '3.0'
55
55
  - !ruby/object:Gem::Dependency
@@ -79,15 +79,18 @@ files:
79
79
  - ".rspec"
80
80
  - Gemfile
81
81
  - Gemfile.lock
82
+ - LICENSE.md
82
83
  - README.md
83
84
  - Rakefile
85
+ - bin/console
84
86
  - lib/quando.rb
85
87
  - lib/quando/config.rb
86
88
  - lib/quando/parser.rb
87
89
  - lib/quando/version.rb
88
90
  - quando.gemspec
89
91
  homepage: https://github.com/kinkou/quando
90
- licenses: []
92
+ licenses:
93
+ - MIT
91
94
  metadata: {}
92
95
  post_install_message:
93
96
  rdoc_options: []
@@ -97,15 +100,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
97
100
  requirements:
98
101
  - - ">="
99
102
  - !ruby/object:Gem::Version
100
- version: '0'
103
+ version: 1.9.3
101
104
  required_rubygems_version: !ruby/object:Gem::Requirement
102
105
  requirements:
103
106
  - - ">="
104
107
  - !ruby/object:Gem::Version
105
108
  version: '0'
106
109
  requirements: []
107
- rubyforge_project:
108
- rubygems_version: 2.7.6
110
+ rubygems_version: 3.0.3
109
111
  signing_key:
110
112
  specification_version: 4
111
113
  summary: Configurable date parser