timeliness 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.
- data/CHANGELOG.rdoc +0 -0
- data/LICENSE +20 -0
- data/README.rdoc +242 -0
- data/Rakefile +64 -0
- data/lib/timeliness.rb +35 -0
- data/lib/timeliness/format_set.rb +95 -0
- data/lib/timeliness/formats.rb +221 -0
- data/lib/timeliness/helpers.rb +49 -0
- data/lib/timeliness/parser.rb +94 -0
- data/lib/timeliness/version.rb +3 -0
- data/spec/spec_helper.rb +36 -0
- data/spec/timeliness/format_set_spec.rb +106 -0
- data/spec/timeliness/formats_spec.rb +93 -0
- data/spec/timeliness/parser_spec.rb +354 -0
- data/timeliness.gemspec +29 -0
- metadata +82 -0
data/CHANGELOG.rdoc
ADDED
File without changes
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010 Adam Meehan
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,242 @@
|
|
1
|
+
= Timeliness
|
2
|
+
|
3
|
+
* Source: http://github.com/adzap/timeliness
|
4
|
+
* Bugs: http://github.com/adzap/timeliness/issues
|
5
|
+
|
6
|
+
== Description
|
7
|
+
|
8
|
+
Date/time parser for Ruby with the following features:
|
9
|
+
|
10
|
+
* Extensible with custom formats and tokens.
|
11
|
+
* It's pretty fast. Up to 60% faster than Time/Date parse method.
|
12
|
+
* Control the parser strictness.
|
13
|
+
* Control behaviour of ambiguous date formats (US vs European e.g. mm/dd/yy, dd/mm/yy).
|
14
|
+
* I18n support (for months).
|
15
|
+
* Fewer WTFs than Time/Date parse method.
|
16
|
+
* Has no dependencies.
|
17
|
+
|
18
|
+
Extracted from the validates_timeliness gem, it has been rewritten cleaner and much faster. It's most suitable for when
|
19
|
+
you need to control the parsing behaviour. It's faster than the Time/Date class parse methods, so it has general appeal.
|
20
|
+
|
21
|
+
|
22
|
+
== Usage
|
23
|
+
|
24
|
+
The simplest example is just a straight forward string parse:
|
25
|
+
|
26
|
+
Timeliness.parse('2010-09-08 12:13:14') #=> Wed Sep 08 12:13:14 1000 2010
|
27
|
+
Timeliness.parse('2010-09-08') #=> Wed Sep 08 00:00:00 1000 2010
|
28
|
+
Timeliness.parse('12:13:14') #=> Sat Jan 01 12:13:14 1100 2000
|
29
|
+
|
30
|
+
Notice a time only string will return with a date value. The date value can be configured globally with
|
31
|
+
this setting:
|
32
|
+
|
33
|
+
Timeliness.date_for_time_type = [2010, 1, 1]
|
34
|
+
|
35
|
+
or specified with :now option:
|
36
|
+
|
37
|
+
Timeliness.parse('12:13:14', :now => Time.mktime(2010,9,8)) #=> Wed Sep 08 12:13:14 1000 2010
|
38
|
+
|
39
|
+
You can also provide a type which will tell the parser that you are only interested in the values for that type.
|
40
|
+
|
41
|
+
Timeliness.parse('2010-09-08 12:13:14', :date) #=> Wed Sep 08 00:00:00 1000 2010
|
42
|
+
Timeliness.parse('2010-09-08 12:13:14', :time) #=> Sat Jan 01 12:13:14 1100 2000
|
43
|
+
Timeliness.parse('2010-09-08 12:13:14', :datetime) #=> Wed Sep 08 12:13:14 1000 2010 i.e. the whole string is used
|
44
|
+
|
45
|
+
Now let's get strict. Pass the :strict option with true and things get finicky
|
46
|
+
|
47
|
+
Timeliness.parse('2010-09-08 12:13:14', :date, :strict => true) #=> nil
|
48
|
+
Timeliness.parse('2010-09-08 12:13:14', :time, :strict => true) #=> nil
|
49
|
+
Timeliness.parse('2010-09-08 12:13:14', :datetime, :strict => true) #=> Wed Sep 08 12:13:14 1000 2010 i.e. the whole string is used
|
50
|
+
|
51
|
+
The strict option without a type is ignored.
|
52
|
+
|
53
|
+
To control what zone the time object is returned in, you have two options. Firstly you can set the default zone. Below
|
54
|
+
is the list of options with their effective time creation method call
|
55
|
+
|
56
|
+
Timeliness.default_timezone = :local # Time.local(...)
|
57
|
+
Timeliness.default_timezone = :utc # Time.utc(...)
|
58
|
+
Timeliness.default_timezone = :current # Time.zone.local(...)
|
59
|
+
Timeliness.default_timezone = 'Melbourne' # Time.use_zone('Melbourne') { Time.zone.local(...) }
|
60
|
+
|
61
|
+
The last two options require that you have ActiveSupport timezone extension loaded.
|
62
|
+
|
63
|
+
You can also use the :zone option to control it for a single parse call:
|
64
|
+
|
65
|
+
Timeliness.parse('2010-09-08 12:13:14', :zone => :utc) #=> Wed Sep 08 12:13:14 UTC 2010
|
66
|
+
Timeliness.parse('2010-09-08 12:13:14', :zone => :local) #=> Wed Sep 08 12:13:14 1000 2010
|
67
|
+
Timeliness.parse('2010-09-08 12:13:14', :zone => :current) #=> Wed Sep 08 12:13:14 1000 2010, with Time.zone = 'Melbourne'
|
68
|
+
Timeliness.parse('2010-09-08 12:13:14', :zone => 'Melbourne') #=> Wed Sep 08 12:13:14 1000 2010
|
69
|
+
|
70
|
+
Remember, you must have ActiveSupport timezone extension loaded to use the last two examples.
|
71
|
+
|
72
|
+
To get super finicky, you can restrict the parsing to a single format with the :format option
|
73
|
+
|
74
|
+
Timeliness.parse('2010-09-08 12:13:14', :format => 'yyyy-mm-dd hh:nn:ss') #=> Wed Sep 08 12:13:14 UTC 2010
|
75
|
+
Timeliness.parse('08/09/2010 12:13:14', :format => 'yyyy-mm-dd hh:nn:ss') #=> nil
|
76
|
+
|
77
|
+
If you would like to get the raw array of values before the time object is created, you can with
|
78
|
+
|
79
|
+
Timeliness._parse('2010-09-08 12:13:14') # => [2010, 9, 8, 12, 13, 14, nil]
|
80
|
+
|
81
|
+
The last nil is for the empty value of microseconds.
|
82
|
+
|
83
|
+
|
84
|
+
== Formats
|
85
|
+
|
86
|
+
The gem has default formats included which can be easily added to using the format syntax. Also formats can be easily
|
87
|
+
removed so that they are no longer considered valid.
|
88
|
+
|
89
|
+
Below are the default formats. If you think they are easy to read then you will be happy to know that is exactly the same
|
90
|
+
format syntax you can use to define your own. No complex regular expressions are needed.
|
91
|
+
|
92
|
+
|
93
|
+
=== Datetime formats
|
94
|
+
|
95
|
+
m/d/yy h:nn:ss OR d/m/yy hh:nn:ss
|
96
|
+
m/d/yy h:nn OR d/m/yy h:nn
|
97
|
+
m/d/yy h:nn_ampm OR d/m/yy h:nn_ampm
|
98
|
+
yyyy-mm-dd hh:nn:ss
|
99
|
+
yyyy-mm-dd h:nn
|
100
|
+
ddd mmm d hh:nn:ss zo yyyy # Ruby time string
|
101
|
+
yyyy-mm-ddThh:nn:ssZ # ISO 8601 without zone offset
|
102
|
+
yyyy-mm-ddThh:nn:sszo # ISO 8601 with zone offset
|
103
|
+
|
104
|
+
NOTE: To use non-US date formats see US/Euro Formats section
|
105
|
+
|
106
|
+
|
107
|
+
=== Date formats
|
108
|
+
|
109
|
+
yyyy/mm/dd
|
110
|
+
yyyy-mm-dd
|
111
|
+
yyyy.mm.dd
|
112
|
+
m/d/yy OR d/m/yy
|
113
|
+
m\d\yy OR d\m\yy
|
114
|
+
d-m-yy
|
115
|
+
dd-mm-yyyy
|
116
|
+
d.m.yy
|
117
|
+
d mmm yy
|
118
|
+
|
119
|
+
NOTE: To use non-US date formats see US/Euro Formats section
|
120
|
+
|
121
|
+
|
122
|
+
=== Time formats
|
123
|
+
|
124
|
+
hh:nn:ss
|
125
|
+
hh-nn-ss
|
126
|
+
h:nn
|
127
|
+
h.nn
|
128
|
+
h nn
|
129
|
+
h-nn
|
130
|
+
h:nn_ampm
|
131
|
+
h.nn_ampm
|
132
|
+
h nn_ampm
|
133
|
+
h-nn_ampm
|
134
|
+
h_ampm
|
135
|
+
|
136
|
+
NOTE: Any time format without a meridian token (the 'ampm' token) is considered in 24 hour time.
|
137
|
+
|
138
|
+
|
139
|
+
=== Format Tokens
|
140
|
+
|
141
|
+
Here is what each format token means:
|
142
|
+
|
143
|
+
Format tokens:
|
144
|
+
y = year
|
145
|
+
m = month
|
146
|
+
d = day
|
147
|
+
h = hour
|
148
|
+
n = minute
|
149
|
+
s = second
|
150
|
+
u = micro-seconds
|
151
|
+
ampm = meridian (am or pm) with or without dots (e.g. am, a.m, or a.m.)
|
152
|
+
_ = optional space
|
153
|
+
tz = Timezone abbreviation (e.g. UTC, GMT, PST, EST)
|
154
|
+
zo = Timezone offset (e.g. +10:00, -08:00, +1000)
|
155
|
+
|
156
|
+
Repeating tokens:
|
157
|
+
x = 1 or 2 digits for unit (e.g. 'h' means an hour can be '9' or '09')
|
158
|
+
xx = 2 digits exactly for unit (e.g. 'hh' means an hour can only be '09')
|
159
|
+
|
160
|
+
Special Cases:
|
161
|
+
yy = 2 or 4 digit year
|
162
|
+
yyyy = exactly 4 digit year
|
163
|
+
mmm = month long name (e.g. 'Jul' or 'July')
|
164
|
+
ddd = Day name of 3 to 9 letters (e.g. Wed or Wednesday)
|
165
|
+
u = microseconds matches 1 to 3 digits
|
166
|
+
|
167
|
+
All other characters are considered literal. For the technically minded, these formats are compiled into a single regular expression
|
168
|
+
|
169
|
+
To see all defined formats look at the {parser source code}[http://github.com/adzap/timeliness/tree/master/lib/timeliness/parser.rb].
|
170
|
+
|
171
|
+
|
172
|
+
== Settings
|
173
|
+
|
174
|
+
=== US/Euro Formats
|
175
|
+
|
176
|
+
The perennial problem for non-US developers or applications not primarily for the
|
177
|
+
US, is the US date format of m/d/yy. This is ambiguous with the European format
|
178
|
+
of d/m/yy. By default the gem uses the US formats as this is the Ruby default
|
179
|
+
when it does date interpretation.
|
180
|
+
|
181
|
+
To switch to using the European (or Rest of The World) formats use this setting
|
182
|
+
|
183
|
+
Timeliness.use_euro_formats
|
184
|
+
|
185
|
+
Now '01/02/2000' will be parsed as 1st February 2000, instead of 2nd January 2000.
|
186
|
+
|
187
|
+
You can switch back to US formats with
|
188
|
+
|
189
|
+
Timeliness.use_us_formats
|
190
|
+
|
191
|
+
|
192
|
+
=== Customising Formats
|
193
|
+
|
194
|
+
Sometimes you may not want certain formats to be valid. You can remove formats for each type and
|
195
|
+
the parser will then not consider that a valid format. To remove a format
|
196
|
+
|
197
|
+
Timeliness.remove_formats(:date, 'm\d\yy')
|
198
|
+
|
199
|
+
Adding new formats is also simple
|
200
|
+
|
201
|
+
Timeliness.add_formats(:time, "d o'clock")
|
202
|
+
|
203
|
+
Now "10 o'clock" will be a valid value.
|
204
|
+
|
205
|
+
You can embed regular expressions in the format but no guarantees that it will
|
206
|
+
remain intact. If you avoid the use of any token characters, and regexp dots or
|
207
|
+
backslashes as special characters in the regexp, it may work as expected.
|
208
|
+
For special characters use POSIX character classes for safety. See the ISO 8601
|
209
|
+
datetime for an example of an embedded regular expression.
|
210
|
+
|
211
|
+
Because formats are evaluated in order, adding a format which may be ambiguous
|
212
|
+
with an existing format, will mean your format is ignored. If you need to make
|
213
|
+
your new format higher precedence than an existing format, you can include the
|
214
|
+
before option like so
|
215
|
+
|
216
|
+
Timeliness.add_formats(:time, 'ss:nn:hh', :before => 'hh:nn:ss')
|
217
|
+
|
218
|
+
Now a time of '59:30:23' will be interpreted as 11:30:59 pm. This option saves
|
219
|
+
you adding a new one and deleting an old one to get it to work.
|
220
|
+
|
221
|
+
|
222
|
+
=== Ambiguous Year
|
223
|
+
|
224
|
+
When dealing with 2 digit year values, by default a year is interpreted as being
|
225
|
+
in the last century when at or above 30. You can customize this however
|
226
|
+
|
227
|
+
Timeliness.ambiguous_year_threshold = 20
|
228
|
+
|
229
|
+
Now you get:
|
230
|
+
|
231
|
+
year of 19 is considered 2019
|
232
|
+
year of 20 is considered 1920
|
233
|
+
|
234
|
+
|
235
|
+
== Credits
|
236
|
+
|
237
|
+
* Adam Meehan (adam.meehan@gmail.com, http://github.com/adzap)
|
238
|
+
|
239
|
+
|
240
|
+
== License
|
241
|
+
|
242
|
+
Copyright (c) 2010 Adam Meehan, released under the MIT license
|
data/Rakefile
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake/rdoctask'
|
3
|
+
require 'rake/gempackagetask'
|
4
|
+
require 'rubygems/specification'
|
5
|
+
require 'rspec/core/rake_task'
|
6
|
+
require 'lib/timeliness/version'
|
7
|
+
|
8
|
+
GEM_NAME = "timeliness"
|
9
|
+
GEM_VERSION = Timeliness::VERSION
|
10
|
+
|
11
|
+
spec = Gem::Specification.new do |s|
|
12
|
+
s.name = GEM_NAME
|
13
|
+
s.version = GEM_VERSION
|
14
|
+
s.platform = Gem::Platform::RUBY
|
15
|
+
s.rubyforge_project = "timeliness"
|
16
|
+
s.has_rdoc = true
|
17
|
+
s.extra_rdoc_files = ["README.rdoc", "CHANGELOG.rdoc"]
|
18
|
+
s.summary = %q{Control time (parsing), quickly.}
|
19
|
+
s.description = %q{Fast date/time parser with customisable formats and I18n support.}
|
20
|
+
s.author = "Adam Meehan"
|
21
|
+
s.email = "adam.meehan@gmail.com"
|
22
|
+
s.homepage = "http://github.com/adzap/timeliness"
|
23
|
+
s.require_path = 'lib'
|
24
|
+
s.files = %w(timeliness.gemspec LICENSE CHANGELOG.rdoc README.rdoc Rakefile) + Dir.glob("{lib,spec}/**/*")
|
25
|
+
end
|
26
|
+
|
27
|
+
desc 'Default: run specs.'
|
28
|
+
task :default => :spec
|
29
|
+
|
30
|
+
desc "Run specs"
|
31
|
+
RSpec::Core::RakeTask.new do |t|
|
32
|
+
t.pattern = "./spec/**/*_spec.rb" # don't need this, it's default.
|
33
|
+
end
|
34
|
+
|
35
|
+
desc "Generate code coverage"
|
36
|
+
RSpec::Core::RakeTask.new(:coverage) do |t|
|
37
|
+
t.rcov = true
|
38
|
+
t.rcov_opts = ['--exclude', 'spec']
|
39
|
+
end
|
40
|
+
|
41
|
+
desc 'Generate documentation for plugin.'
|
42
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
43
|
+
rdoc.rdoc_dir = 'rdoc'
|
44
|
+
rdoc.title = 'Timeliness'
|
45
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
46
|
+
rdoc.rdoc_files.include('README')
|
47
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
48
|
+
end
|
49
|
+
|
50
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
51
|
+
pkg.gem_spec = spec
|
52
|
+
end
|
53
|
+
|
54
|
+
desc "Install the gem locally"
|
55
|
+
task :install => [:package] do
|
56
|
+
sh %{gem install pkg/#{GEM_NAME}-#{GEM_VERSION}}
|
57
|
+
end
|
58
|
+
|
59
|
+
desc "Create a gemspec file"
|
60
|
+
task :make_spec do
|
61
|
+
File.open("#{GEM_NAME}.gemspec", "w") do |file|
|
62
|
+
file.puts spec.to_ruby
|
63
|
+
end
|
64
|
+
end
|
data/lib/timeliness.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'date'
|
2
|
+
require 'forwardable'
|
3
|
+
|
4
|
+
require 'timeliness/helpers'
|
5
|
+
require 'timeliness/formats'
|
6
|
+
require 'timeliness/format_set'
|
7
|
+
require 'timeliness/parser'
|
8
|
+
require 'timeliness/version'
|
9
|
+
|
10
|
+
module Timeliness
|
11
|
+
class << self
|
12
|
+
extend Forwardable
|
13
|
+
def_delegators Parser, :parse, :_parse
|
14
|
+
def_delegators Formats, :add_formats, :remove_formats, :use_us_formats, :use_euro_formats
|
15
|
+
attr_accessor :default_timezone, :date_for_time_type, :ambiguous_year_threshold
|
16
|
+
end
|
17
|
+
|
18
|
+
# Default timezone (:local or :utc)
|
19
|
+
@default_timezone = :local
|
20
|
+
|
21
|
+
# Set the default date part for a time type values.
|
22
|
+
@date_for_time_type = [ 2000, 1, 1 ]
|
23
|
+
|
24
|
+
# Set the threshold value for a two digit year to be considered last century
|
25
|
+
#
|
26
|
+
# Default: 30
|
27
|
+
#
|
28
|
+
# Example:
|
29
|
+
# year = '29' is considered 2029
|
30
|
+
# year = '30' is considered 1930
|
31
|
+
#
|
32
|
+
@ambiguous_year_threshold = 30
|
33
|
+
end
|
34
|
+
|
35
|
+
Timeliness::Formats.compile_formats
|
@@ -0,0 +1,95 @@
|
|
1
|
+
module Timeliness
|
2
|
+
class FormatSet
|
3
|
+
include Helpers
|
4
|
+
|
5
|
+
attr_reader :formats, :regexp
|
6
|
+
|
7
|
+
class << self
|
8
|
+
|
9
|
+
def compile(formats)
|
10
|
+
set = new(formats)
|
11
|
+
set.compile!
|
12
|
+
set
|
13
|
+
end
|
14
|
+
|
15
|
+
def compile_format(string_format)
|
16
|
+
format = string_format.dup
|
17
|
+
format.gsub!(/([\.\\])/, '\\\\\1') # escapes dots and backslashes
|
18
|
+
found_tokens, token_order, value_token_count = [], [], 0
|
19
|
+
|
20
|
+
# Substitute tokens with numbered placeholder
|
21
|
+
Formats.sorted_token_keys.each do |token|
|
22
|
+
regexp_str, arg_key = *Formats.format_tokens[token]
|
23
|
+
if format.gsub!(/#{token}/, "%<#{found_tokens.size}>")
|
24
|
+
if arg_key
|
25
|
+
regexp_str = "(#{regexp_str})"
|
26
|
+
value_token_count += 1
|
27
|
+
end
|
28
|
+
found_tokens << [regexp_str, arg_key]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Replace placeholders with token regexps
|
33
|
+
format.scan(/%<(\d)>/).each {|token_index|
|
34
|
+
token_index = token_index.first
|
35
|
+
regexp_str, arg_key = found_tokens[token_index.to_i]
|
36
|
+
format.gsub!("%<#{token_index}>", regexp_str)
|
37
|
+
token_order << arg_key
|
38
|
+
}
|
39
|
+
|
40
|
+
define_format_method(string_format, token_order.compact)
|
41
|
+
return format, value_token_count
|
42
|
+
rescue
|
43
|
+
raise "The following format regular expression failed to compile: #{format}\n from format #{string_format}."
|
44
|
+
end
|
45
|
+
|
46
|
+
# Compiles a format method which maps the regexp capture groups to method
|
47
|
+
# arguments based on order captured. A time array is built using the argument
|
48
|
+
# values placed in the position defined by the component.
|
49
|
+
#
|
50
|
+
def define_format_method(name, components)
|
51
|
+
values = [nil] * 7
|
52
|
+
components.each do |component|
|
53
|
+
position, code = *Formats.format_components[component]
|
54
|
+
values[position] = code || "#{component}.to_i" if position
|
55
|
+
end
|
56
|
+
class_eval <<-DEF
|
57
|
+
define_method(:"format_#{name}") do |#{components.join(',')}|
|
58
|
+
[#{values.map {|i| i || 'nil' }.join(',')}]
|
59
|
+
end
|
60
|
+
DEF
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
def initialize(formats)
|
66
|
+
@formats = formats
|
67
|
+
end
|
68
|
+
|
69
|
+
def compile!
|
70
|
+
regexp_string = ''
|
71
|
+
@format_regexps = {}
|
72
|
+
@match_indexes = {}
|
73
|
+
@formats.inject(0) { |index, format|
|
74
|
+
format_regexp, token_count = self.class.compile_format(format)
|
75
|
+
@format_regexps[format] = Regexp.new("^(#{format_regexp})$")
|
76
|
+
@match_indexes[index] = format
|
77
|
+
regexp_string = "#{regexp_string}(#{format_regexp})|"
|
78
|
+
index + token_count + 1 # add one for wrapper capture
|
79
|
+
}
|
80
|
+
@regexp = Regexp.new("^(?:#{regexp_string.chop})$")
|
81
|
+
end
|
82
|
+
|
83
|
+
def match(string, format=nil)
|
84
|
+
match_regexp = format ? @format_regexps[format] : @regexp
|
85
|
+
if match_data = match_regexp.match(string)
|
86
|
+
index = match_data.captures.index(string)
|
87
|
+
start = index + 1
|
88
|
+
values = match_data.captures[start..(start+7)].compact
|
89
|
+
format ||= @match_indexes[index]
|
90
|
+
send(:"format_#{format}", *values)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
end
|