quando 0.0.2 → 0.0.8

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
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