eventual 0.5.2 → 0.5.3
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +6 -2
- data/VERSION +1 -1
- data/lib/eventual/syntax_nodes.rb +30 -30
- data/lib/eventual.rb +11 -8
- data/spec/es_eventual_spec.rb +44 -0
- metadata +3 -3
data/README.rdoc
CHANGED
@@ -64,7 +64,7 @@ Ejemplos:
|
|
64
64
|
=> false
|
65
65
|
|
66
66
|
# Pero se puede cambiar
|
67
|
-
dates
|
67
|
+
dates = Eventual.parse( 'del 5 al 7 de junio del 2007 a las 16:00', :default_event_span => 120)
|
68
68
|
dates.include? DateTime.civil(2007, 6, 6, 17, 00)
|
69
69
|
=> true
|
70
70
|
|
@@ -114,7 +114,11 @@ Formatos a reconocer
|
|
114
114
|
|
115
115
|
== INSTALACIÓN:
|
116
116
|
|
117
|
-
[sudo] gem install eventual
|
117
|
+
[sudo] gem install eventual
|
118
|
+
|
119
|
+
== Documentation
|
120
|
+
|
121
|
+
http://rdoc.info/projects/maca/eventual
|
118
122
|
|
119
123
|
== LICENCIA:
|
120
124
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.5.
|
1
|
+
0.5.3
|
@@ -4,8 +4,8 @@ module Eventual
|
|
4
4
|
ShortMonthNames = %w(ene feb mar abr may jun jul ago sept oct nov dic).freeze
|
5
5
|
WdaysR = [/d/, /l/, /ma/, /mi/, /j/, /v/, /s/].freeze
|
6
6
|
WdayListR = /\b(?:#{ WdaysR.join('|') })/.freeze
|
7
|
-
|
8
|
-
class WdayMatchError < StandardError
|
7
|
+
|
8
|
+
class WdayMatchError < StandardError #:nodoc:
|
9
9
|
def initialize value, wday_index
|
10
10
|
@value, @wday_index = value, wday_index
|
11
11
|
end
|
@@ -14,8 +14,8 @@ module Eventual
|
|
14
14
|
"El #{@value.day} de #{MonthNames[@value.month]} del #{@value.year} cae en #{Weekdays[@value.wday]} no #{Weekdays[@wday_index]}"
|
15
15
|
end
|
16
16
|
end
|
17
|
-
|
18
|
-
class Year < Treetop::Runtime::SyntaxNode
|
17
|
+
|
18
|
+
class Year < Treetop::Runtime::SyntaxNode #:nodoc:
|
19
19
|
def value
|
20
20
|
match = text_value.match(/(')?(\d{2,4})/)
|
21
21
|
value = match[2].to_i
|
@@ -23,8 +23,8 @@ module Eventual
|
|
23
23
|
value
|
24
24
|
end
|
25
25
|
end
|
26
|
-
|
27
|
-
class WeekdayConstrain < Treetop::Runtime::SyntaxNode
|
26
|
+
|
27
|
+
class WeekdayConstrain < Treetop::Runtime::SyntaxNode #:nodoc:
|
28
28
|
def value
|
29
29
|
text = wdays_node.text_value.sub('semana', '')
|
30
30
|
days = text.scan(WdayListR).map{ |d| WdaysR.index /#{d}/ }
|
@@ -33,8 +33,8 @@ module Eventual
|
|
33
33
|
days.uniq
|
34
34
|
end
|
35
35
|
end
|
36
|
-
|
37
|
-
class MonthName < Treetop::Runtime::SyntaxNode
|
36
|
+
|
37
|
+
class MonthName < Treetop::Runtime::SyntaxNode #:nodoc:
|
38
38
|
def value
|
39
39
|
ShortMonthNames.index(text_value.downcase.match(/#{ ShortMonthNames.join('|') }/).to_s) + 1
|
40
40
|
end
|
@@ -65,7 +65,7 @@ module Eventual
|
|
65
65
|
# Returns true if the weekday (as number) correspons to any allowed weekday
|
66
66
|
def date_within_weekdays? date
|
67
67
|
return true unless weekdays
|
68
|
-
weekdays.include?
|
68
|
+
weekdays.include? date.wday
|
69
69
|
end
|
70
70
|
|
71
71
|
# Invokes block once for each Date or DateTime. Creates a new array containing the values returned by the block.
|
@@ -79,13 +79,12 @@ module Eventual
|
|
79
79
|
walk { |elements| break result = true if elements.include? date }
|
80
80
|
|
81
81
|
unless date.class == Date or times.nil? or times.empty?
|
82
|
-
@time_span
|
83
|
-
|
84
|
-
|
85
|
-
time
|
86
|
-
break true if time >=
|
82
|
+
@time_span ||= 60
|
83
|
+
return false unless times.inject(nil){ |memo, time|
|
84
|
+
check_against = ::Time.local date.year, date.month, date.day, time.hour, time.minute
|
85
|
+
time = ::Time.local date.year, date.month, date.day, date.hour, date.min
|
86
|
+
break true if time >= check_against && time < check_against + 60 * @time_span
|
87
87
|
}
|
88
|
-
return false unless within_time
|
89
88
|
end
|
90
89
|
result
|
91
90
|
end
|
@@ -128,8 +127,7 @@ module Eventual
|
|
128
127
|
end
|
129
128
|
end
|
130
129
|
|
131
|
-
|
132
|
-
class Day < Node
|
130
|
+
class Day < Node #:nodoc:
|
133
131
|
def map &block
|
134
132
|
dates = times ? times.map{ |time| DateTime.civil year, month, text_value.to_i, time.hour, time.minute } : [Date.civil(year, month, text_value.to_i)]
|
135
133
|
raise WdayMatchError.new(dates.first, weekdays.first) unless date_within_weekdays? dates.first
|
@@ -137,11 +135,11 @@ module Eventual
|
|
137
135
|
end
|
138
136
|
|
139
137
|
def include? date
|
140
|
-
|
138
|
+
map{ |e| e.strftime("%Y-%m-%d") }.include? date.strftime("%Y-%m-%d")
|
141
139
|
end
|
142
140
|
end
|
143
|
-
|
144
|
-
class Period < Node
|
141
|
+
|
142
|
+
class Period < Node #:nodoc:
|
145
143
|
def range
|
146
144
|
(first..last)
|
147
145
|
end
|
@@ -168,8 +166,8 @@ module Eventual
|
|
168
166
|
array
|
169
167
|
end
|
170
168
|
end
|
171
|
-
|
172
|
-
class MonthPeriod < Period
|
169
|
+
|
170
|
+
class MonthPeriod < Period #:nodoc:
|
173
171
|
def first
|
174
172
|
return Date.civil(year, month_name.value) unless times and !times.empty?
|
175
173
|
time = times.first
|
@@ -183,8 +181,8 @@ module Eventual
|
|
183
181
|
DateTime.civil(date.year, date.month, date.day, time.hour, time.minute)
|
184
182
|
end
|
185
183
|
end
|
186
|
-
|
187
|
-
class DatePeriod < Period
|
184
|
+
|
185
|
+
class DatePeriod < Period #:nodoc:
|
188
186
|
def first
|
189
187
|
node_map.first
|
190
188
|
end
|
@@ -193,8 +191,8 @@ module Eventual
|
|
193
191
|
node_map.last
|
194
192
|
end
|
195
193
|
end
|
196
|
-
|
197
|
-
class Times < Treetop::Runtime::SyntaxNode
|
194
|
+
|
195
|
+
class Times < Treetop::Runtime::SyntaxNode #:nodoc:
|
198
196
|
def map
|
199
197
|
walk_times = lambda do |elements|
|
200
198
|
break unless elements
|
@@ -203,17 +201,19 @@ module Eventual
|
|
203
201
|
walk_times.call(elements).flatten.compact.sort_by{ |t| '%02d%02d' % [t.hour, t.minute] }
|
204
202
|
end
|
205
203
|
end
|
206
|
-
|
207
|
-
class Time < Treetop::Runtime::SyntaxNode
|
204
|
+
|
205
|
+
class Time < Treetop::Runtime::SyntaxNode #:nodoc:
|
208
206
|
attr_accessor :hour, :minute
|
209
207
|
def value
|
210
208
|
@hour, @minute = text_value.scan(/\d+/).map(&:to_i)
|
211
209
|
@minute ||= 0
|
212
210
|
self
|
213
211
|
end
|
212
|
+
|
213
|
+
|
214
214
|
end
|
215
|
-
|
216
|
-
class Time12 < Time
|
215
|
+
|
216
|
+
class Time12 < Time #:nodoc:
|
217
217
|
def value
|
218
218
|
super
|
219
219
|
@hour += 12 if period.text_value.gsub(/[^a-z]/, '') == 'pm'
|
data/lib/eventual.rb
CHANGED
@@ -10,14 +10,15 @@ module Eventual
|
|
10
10
|
# Parses dates specified in natural language and returns an Eventual::Node object
|
11
11
|
# Eventual.parse( 'del 5 al 7 de junio del 2009' ).map
|
12
12
|
# => [#<DateTime: 4909975/2,0,2299161>, #<DateTime: 4909977/2,0,2299161>, #<DateTime: 4909979/2,0,2299161
|
13
|
-
# Options:
|
14
|
-
# +:lang+:
|
15
|
-
# Defaults to 'Es', the language to be used for parsing, currently only spanish is supported, hang on.
|
16
|
-
# +:default_year+:
|
17
|
-
# The default year to be used in case year is not specified in the text, defaults to current year
|
18
|
-
# +:default_event_span+:
|
19
|
-
# The duration in minutes an event has, defaults to 60
|
20
13
|
#
|
14
|
+
# Options:
|
15
|
+
# +:lang+:
|
16
|
+
# Defaults to 'Es', the language to be used for parsing, currently only spanish is supported, hang on.
|
17
|
+
# +:default_year+:
|
18
|
+
# The default year to be used in case year is not specified in the text, defaults to current year
|
19
|
+
# +:default_event_span+:
|
20
|
+
# The duration in minutes an event has, defaults to 60
|
21
|
+
#
|
21
22
|
def self.parse text, opts = {}
|
22
23
|
lang = opts.delete(:lang) || 'Es'
|
23
24
|
year = opts.delete(:default_year)
|
@@ -26,7 +27,9 @@ module Eventual
|
|
26
27
|
raise ArgumentError, "Expected option `:default_year` to be an integer" if year && !(Integer === year)
|
27
28
|
raise ArgumentError, "Expected option `:default_event_span` to be an integer" if span && !(Integer === span)
|
28
29
|
|
29
|
-
|
30
|
+
parser = const_get("#{ lang.to_s[0..1].capitalize }DatesParser") rescue raise( NotImplementedError.new("Parsing has not yet been implemented for the language '#{lang}'"))
|
31
|
+
node = parser.new.parse(text)
|
32
|
+
|
30
33
|
node.year = year if year
|
31
34
|
node.time_span = span if span
|
32
35
|
node
|
data/spec/es_eventual_spec.rb
CHANGED
@@ -5,6 +5,12 @@ describe Eventual, 'Es' do
|
|
5
5
|
before do
|
6
6
|
Date.stub!(:today).and_return Date.civil(2010)
|
7
7
|
end
|
8
|
+
|
9
|
+
describe 'proxy' do
|
10
|
+
it "should raise NotImplementedError if using not implemented language" do
|
11
|
+
lambda { Eventual.parse 'marzo', :lang => 'WP' }.should raise_error(NotImplementedError)
|
12
|
+
end
|
13
|
+
end
|
8
14
|
|
9
15
|
shared_examples_for 'correctly parses' do
|
10
16
|
it { @result.should_not be_nil }
|
@@ -409,6 +415,44 @@ describe Eventual, 'Es' do
|
|
409
415
|
@result.should_not include(DateTime.parse('2010-12-06T14:00'))
|
410
416
|
end
|
411
417
|
end
|
418
|
+
|
419
|
+
describe 'event default timespan' do
|
420
|
+
before do
|
421
|
+
@result = Eventual.parse('1 de diciembre del 2010 a las 15:00')
|
422
|
+
@dates = [DateTime.parse('2010-12-1T15:00')]
|
423
|
+
end
|
424
|
+
it_should_behave_like 'correctly parses'
|
425
|
+
it_should_behave_like 'outputs DateTime'
|
426
|
+
|
427
|
+
it "should include time encompassed in 60 minutes from start" do
|
428
|
+
@result.should include(DateTime.civil(2010, 12, 1, 15, 30))
|
429
|
+
end
|
430
|
+
|
431
|
+
it "should not include time past 60 minutes from start" do
|
432
|
+
@result.should_not include(DateTime.civil(2010, 12, 1, 16, 00))
|
433
|
+
end
|
434
|
+
end
|
435
|
+
|
436
|
+
describe 'event defined timespan' do
|
437
|
+
before do
|
438
|
+
@result = Eventual.parse('1 de diciembre del 2010 a las 15:00', :default_event_span => 120)
|
439
|
+
@dates = [DateTime.parse('2010-12-1T15:00')]
|
440
|
+
end
|
441
|
+
it_should_behave_like 'correctly parses'
|
442
|
+
it_should_behave_like 'outputs DateTime'
|
443
|
+
|
444
|
+
it "should include time encompassed in 60 minutes from start" do
|
445
|
+
@result.should include(DateTime.civil(2010, 12, 1, 15, 30))
|
446
|
+
end
|
447
|
+
|
448
|
+
it "should not include time past 60 minutes from start" do
|
449
|
+
@result.should include(DateTime.civil(2010, 12, 1, 16, 00))
|
450
|
+
end
|
451
|
+
|
452
|
+
it "should not include time past 60 minutes from start" do
|
453
|
+
@result.should_not include(DateTime.civil(2010, 12, 1, 17, 00))
|
454
|
+
end
|
455
|
+
end
|
412
456
|
end
|
413
457
|
|
414
458
|
describe 'Marshal dump' do
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 5
|
8
|
-
-
|
9
|
-
version: 0.5.
|
8
|
+
- 3
|
9
|
+
version: 0.5.3
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Macario Ortega
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-07-
|
17
|
+
date: 2010-07-30 00:00:00 -05:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|