eventual 0.5.2 → 0.5.3
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/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
|