eventual 0.5.3 → 0.5.4

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -84,6 +84,7 @@ Ejemplos de formatos reconocidos:
84
84
  * 21 de marzo
85
85
  * 21 marzo
86
86
  * domingo 21 de marzo
87
+ * domingo, 21 de marzo
87
88
  * 1, 2 y 3 de marzo
88
89
  * 1, 2 y 3 marzo
89
90
  * lunes 1, martes 2 y miercoles 3 de marzo
@@ -101,6 +102,7 @@ Ejemplos de formatos reconocidos:
101
102
  * los lunes y martes del 1 al 22 de marzo del '10
102
103
  * los lunes y los martes del 1 al 22 de marzo del '10
103
104
  * lunes y martes de diciembre a las 15
105
+ * lunes y martes, de diciembre a las 15
104
106
  * lunes y martes de diciembre a las 15:30 hrs.
105
107
  * lunes y martes de diciembre a las 15:00 y 16:00 horas
106
108
  * lunes y martes de diciembre a las 3 am
@@ -111,6 +113,7 @@ Ejemplos de formatos reconocidos:
111
113
  Formatos a reconocer
112
114
 
113
115
  * todo el año
116
+ * lunes y martes de diciembre, 3:15 p.m.
114
117
 
115
118
  == INSTALACIÓN:
116
119
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.5.3
1
+ 0.5.4
@@ -33,7 +33,11 @@ grammar EsDates
33
33
 
34
34
  ##########
35
35
  rule times
36
- space 'a' space ('las' / 'la') (time_12 / time_24) ((space 'y' / ',') (time_12 / time_24))* <Eventual::Times>
36
+ time_range / time_list
37
+ end
38
+
39
+ rule time_list
40
+ space 'a' space ('las' / 'la') (time_12 / time_24) ((space 'y' / ',') (time_12 / time_24))* <Eventual::TimeList>
37
41
  end
38
42
 
39
43
  rule time_24
@@ -41,7 +45,11 @@ grammar EsDates
41
45
  end
42
46
 
43
47
  rule time_12
44
- space ('0' [0-9] / '1' [0-2] / [0-9]) (':' [0-5] [0-9])? space? period:(('a'/'p') '.'? space? 'm' '.'? space?) <Eventual::Time12>
48
+ space ('0' [0-9] / '1' [0-2] / [0-9]) (':' [0-5] [0-9])? space? period:(('a'/'p') '.'? space? 'm' '.'? ) <Eventual::Time12>
49
+ end
50
+
51
+ rule time_range
52
+ space 'de' space ('las' / 'la') first:(time_12 / time_24) space 'a' space ('las' / 'la') last:(time_12 / time_24) <Eventual::TimeRange>
45
53
  end
46
54
 
47
55
  ##########
@@ -58,7 +66,7 @@ grammar EsDates
58
66
  end
59
67
 
60
68
  rule weekday_constrain
61
- wdays_node:weekday space <Eventual::WeekdayConstrain>
69
+ wdays_node:weekday ','? space <Eventual::WeekdayConstrain>
62
70
  end
63
71
 
64
72
  rule weekday_list
data/lib/eventual/es.rb CHANGED
@@ -1 +1,2 @@
1
1
  Treetop.load "#{ File.dirname __FILE__ }/es/event_parser"
2
+
@@ -6,12 +6,12 @@ module Eventual
6
6
  WdayListR = /\b(?:#{ WdaysR.join('|') })/.freeze
7
7
 
8
8
  class WdayMatchError < StandardError #:nodoc:
9
- def initialize value, wday_index
10
- @value, @wday_index = value, wday_index
9
+ def initialize value
10
+ @value
11
11
  end
12
12
 
13
13
  def to_s
14
- "El #{@value.day} de #{MonthNames[@value.month]} del #{@value.year} cae en #{Weekdays[@value.wday]} no #{Weekdays[@wday_index]}"
14
+ "El #{@value.day} de #{MonthNames[@value.month]} del #{@value.year} cae en #{Weekdays[@value.wday]}"
15
15
  end
16
16
  end
17
17
 
@@ -48,19 +48,13 @@ module Eventual
48
48
  attr_accessor :times
49
49
 
50
50
  # Returns last Date or DateTime of the encompassed period
51
- def last
52
- to_a.last
53
- end
51
+ def last; to_a.last end
54
52
 
55
53
  # Returns last Date or DateTime of the encompassed period
56
- def first
57
- to_a.first
58
- end
54
+ def first; to_a.first end
59
55
 
60
56
  # Returns an array with all the encompassed Dates or DateTimes
61
- def to_a
62
- map
63
- end
57
+ def to_a; map end
64
58
 
65
59
  # Returns true if the weekday (as number) correspons to any allowed weekday
66
60
  def date_within_weekdays? date
@@ -78,15 +72,9 @@ module Eventual
78
72
  result = false
79
73
  walk { |elements| break result = true if elements.include? date }
80
74
 
81
- unless date.class == Date or times.nil? or times.empty?
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
- }
88
- end
89
- result
75
+ return result if !result or date.class == Date or times.nil?
76
+
77
+ times.include? date
90
78
  end
91
79
 
92
80
  private
@@ -96,7 +84,7 @@ module Eventual
96
84
 
97
85
  walk = lambda do |elements|
98
86
  break unless elements
99
- weekdays = elements.first.value if elements.first.class == WeekdayConstrain
87
+ weekdays = elements.shift.value if WeekdayConstrain === elements.first
100
88
 
101
89
  elements.reverse.map do |element|
102
90
  case element
@@ -105,7 +93,6 @@ module Eventual
105
93
  element.year = year
106
94
  element.month = month
107
95
  element.times = @times
108
-
109
96
  yield element
110
97
  when Year
111
98
  year = element.value
@@ -113,29 +100,37 @@ module Eventual
113
100
  when MonthName
114
101
  month = element.value
115
102
  next nil
116
- when WeekdayConstrain
117
- next nil
118
- when Times
119
- @times = element.map
103
+ when TimeList, TimeRange
104
+ @times = element
120
105
  next nil
121
- else
106
+ else
122
107
  walk.call element.elements
123
108
  end
124
109
  end.reverse
125
110
  end
126
111
  walk.call(elements).flatten.compact
127
112
  end
113
+
114
+ def make year, month, day
115
+ return Date.civil(year, month, day) unless times
116
+ times.make year, month, day
117
+ end
128
118
  end
129
119
 
130
120
  class Day < Node #:nodoc:
121
+ def value
122
+ Date.civil year, month, text_value.to_i
123
+ end
124
+
131
125
  def map &block
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)]
133
- raise WdayMatchError.new(dates.first, weekdays.first) unless date_within_weekdays? dates.first
134
- dates.map(&block)
126
+ dates = make(year, month, text_value.to_i)
127
+ dates = [dates] unless Array === dates
128
+ raise WdayMatchError.new(dates.first) unless date_within_weekdays? dates.first
129
+ dates.map &block
135
130
  end
136
131
 
137
132
  def include? date
138
- map{ |e| e.strftime("%Y-%m-%d") }.include? date.strftime("%Y-%m-%d")
133
+ map { |element| [*element].map{ |e| e.strftime("%Y-%m-%d") } }.flatten.include? date.strftime("%Y-%m-%d")
139
134
  end
140
135
  end
141
136
 
@@ -152,33 +147,22 @@ module Eventual
152
147
  alias node_map map
153
148
  private :node_map
154
149
 
155
- def map
156
- array = []
157
- range.each do |date|
150
+ def map &block
151
+ range.map do |date|
158
152
  next unless date_within_weekdays? date
159
- next array.push(block_given? ? yield(date) : date) unless times
160
-
161
- times.each do |time|
162
- new_date = DateTime.civil date.year, date.month, date.day, time.hour, time.minute
163
- array.push block_given? ? yield(new_date) : new_date
164
- end
153
+ dates = times ? make(date.year, date.month, date.day) : [date]
154
+ dates.map &block
165
155
  end
166
- array
167
156
  end
168
157
  end
169
158
 
170
159
  class MonthPeriod < Period #:nodoc:
171
160
  def first
172
- return Date.civil(year, month_name.value) unless times and !times.empty?
173
- time = times.first
174
- return DateTime.civil(year, month_name.value, 1, time.hour, time.minute)
161
+ Date.civil year, month_name.value
175
162
  end
176
-
163
+
177
164
  def last
178
- date = (first >> 1) - 1
179
- return date unless times and !times.empty?
180
- time = times.last
181
- DateTime.civil(date.year, date.month, date.day, time.hour, time.minute)
165
+ Date.civil year, month_name.value, -1
182
166
  end
183
167
  end
184
168
 
@@ -192,32 +176,59 @@ module Eventual
192
176
  end
193
177
  end
194
178
 
195
- class Times < Treetop::Runtime::SyntaxNode #:nodoc:
179
+ class TimeList < Treetop::Runtime::SyntaxNode #:nodoc:
196
180
  def map
197
181
  walk_times = lambda do |elements|
198
182
  break unless elements
199
- elements.map { |e| Time === e ? e.value : walk_times.call(e.elements) }
183
+ elements.map do |element|
184
+ next walk_times.call(element.elements) unless Time === element
185
+ block_given? ? yield(element) : element
186
+ end
200
187
  end
201
- walk_times.call(elements).flatten.compact.sort_by{ |t| '%02d%02d' % [t.hour, t.minute] }
188
+ walk_times.call(elements).flatten.compact
189
+ end
190
+
191
+ def make year, month, day
192
+ map { |time| DateTime.civil year, month, day, time.hour, time.minute }.sort
193
+ end
194
+
195
+ def include? date
196
+ map { |time| time.to_i }.include? date.strftime("%H%M").to_i
202
197
  end
203
198
  end
204
-
199
+
205
200
  class Time < Treetop::Runtime::SyntaxNode #:nodoc:
206
- attr_accessor :hour, :minute
207
201
  def value
208
- @hour, @minute = text_value.scan(/\d+/).map(&:to_i)
209
- @minute ||= 0
210
- self
202
+ @value ||= text_value.scan(/\d+/).map(&:to_i)
211
203
  end
212
204
 
213
-
205
+ def hour; value.first end
206
+ def minute; value[1] || 0 end
207
+
208
+ def to_i
209
+ ("%02d%02d" % [hour, minute]).to_i
210
+ end
214
211
  end
215
212
 
216
213
  class Time12 < Time #:nodoc:
217
- def value
218
- super
219
- @hour += 12 if period.text_value.gsub(/[^a-z]/, '') == 'pm'
220
- self
214
+ def pm?
215
+ @pm ||= true if period.text_value.include? 'pm'
216
+ end
217
+
218
+ def hour
219
+ pm? ? super + 12 : super
220
+ end
221
+ end
222
+
223
+ class TimeRange < Treetop::Runtime::SyntaxNode #:nodoc:
224
+ def make year, month, day
225
+ first_time = DateTime.civil year, month, day, first.hour, first.minute
226
+ last_time = DateTime.civil year, month, day, last.hour, last.minute
227
+ (first_time..last_time)
228
+ end
229
+
230
+ def include? date
231
+ (first.to_i..last.to_i).include? date.strftime("%H%M").to_i
221
232
  end
222
233
  end
223
234
  end
data/lib/eventual.rb CHANGED
@@ -13,7 +13,7 @@ module Eventual
13
13
  #
14
14
  # Options:
15
15
  # +:lang+:
16
- # Defaults to 'Es', the language to be used for parsing, currently only spanish is supported, hang on.
16
+ # Defaults to 'Es', the language to be used for parsing, currently only spanish is supported, please contribute.
17
17
  # +:default_year+:
18
18
  # The default year to be used in case year is not specified in the text, defaults to current year
19
19
  # +:default_event_span+:
@@ -9,7 +9,7 @@ describe Eventual, 'Es' do
9
9
  describe 'proxy' do
10
10
  it "should raise NotImplementedError if using not implemented language" do
11
11
  lambda { Eventual.parse 'marzo', :lang => 'WP' }.should raise_error(NotImplementedError)
12
- end
12
+ end
13
13
  end
14
14
 
15
15
  shared_examples_for 'correctly parses' do
@@ -137,6 +137,17 @@ describe Eventual, 'Es' do
137
137
  lambda { Eventual.parse("lunes 21 de marzo").map }.should raise_error(Eventual::WdayMatchError)
138
138
  end
139
139
  end
140
+
141
+ describe 'date with wday and comma' do
142
+ describe "parsing 'domingo, 21 de marzo'" do
143
+ before { @result = Eventual.parse("domingo, 21 de marzo") }
144
+ it_should_behave_like 'correctly parses'
145
+ end
146
+
147
+ it "should raise WdayMatchError if weekday doesn't correspond to date" do
148
+ lambda { Eventual.parse("lunes 21 de marzo").map }.should raise_error(Eventual::WdayMatchError)
149
+ end
150
+ end
140
151
  end
141
152
 
142
153
  describe 'day list' do
@@ -236,6 +247,14 @@ describe Eventual, 'Es' do
236
247
  end
237
248
  it_should_behave_like 'correctly parses'
238
249
  end
250
+
251
+ describe "lunes y martes, del 1 de octubre al 2 de diciembre del 2008" do
252
+ before do
253
+ @result = Eventual.parse "lunes y martes, del 1 de octubre al 2 de diciembre del 2008"
254
+ @dates = (Date.parse('2008-10-1')..DateTime.parse('2008-12-2')).reject{ |day| not [1,2].include?(day.wday) }
255
+ end
256
+ it_should_behave_like 'correctly parses'
257
+ end
239
258
 
240
259
  describe 'with weekday constrain' do
241
260
  describe "wdays for 'lunes y martes del 1 al 22 de marzo del '10" do
@@ -337,6 +356,7 @@ describe Eventual, 'Es' do
337
356
  @result = Eventual.parse('1 de enero del 2010 a las 15:00')
338
357
  @dates = [DateTime.civil 2010, 1, 1, 15]
339
358
  end
359
+
340
360
  it_should_behave_like 'correctly parses'
341
361
  it_should_behave_like 'outputs DateTime'
342
362
  end
@@ -390,6 +410,24 @@ describe Eventual, 'Es' do
390
410
  end
391
411
  end
392
412
 
413
+ describe 'three times for month range' do
414
+ before do
415
+ @result = Eventual.parse('lunes y martes de diciembre a las 16:00, 17:00 y 15:00 horas')
416
+ @dates = (
417
+ (DateTime.parse('2010-12-1T15:00')..DateTime.parse('2010-12-31T15:00')).map +
418
+ (DateTime.parse('2010-12-1T16:00')..DateTime.parse('2010-12-31T16:00')).map +
419
+ (DateTime.parse('2010-12-1T17:00')..DateTime.parse('2010-12-31T17:00')).map
420
+ ).reject{ |day| not [1,2].include?(day.wday) }
421
+ end
422
+
423
+ it_should_behave_like 'correctly parses'
424
+ it_should_behave_like 'outputs DateTime'
425
+
426
+ it "should not include other time" do
427
+ @result.should_not include(DateTime.parse('2010-12-06T14:00'))
428
+ end
429
+ end
430
+
393
431
  describe 'range with time as 12 hours am' do
394
432
  before do
395
433
  @result = Eventual.parse('lunes y martes de diciembre a las 3 am')
@@ -423,14 +461,6 @@ describe Eventual, 'Es' do
423
461
  end
424
462
  it_should_behave_like 'correctly parses'
425
463
  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
464
  end
435
465
 
436
466
  describe 'event defined timespan' do
@@ -440,21 +470,28 @@ describe Eventual, 'Es' do
440
470
  end
441
471
  it_should_behave_like 'correctly parses'
442
472
  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))
473
+ end
474
+ end
475
+
476
+ describe "with time range" do
477
+ describe 'single day with time range' do
478
+ before do
479
+ @result = Eventual.parse('1 de enero del 2010 de las 15:00 a las 16:00')
480
+ @ranges = [(DateTime.civil 2010, 1, 1, 15)..(DateTime.civil 2010, 1, 1, 16)]
446
481
  end
447
482
 
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
483
+ it { @result.should_not be_nil }
484
+ it { @result.to_a.size.should == @ranges.map.size }
485
+ it { @result.should map_dates *@ranges }
486
+ it { @ranges.each{ |range| range.each{ |date| @result.should include(date) } } }
487
+ # it { @result.should_not include(@dates.first - 1) }
488
+ # it { @result.should_not include(@dates.last + 1) }
489
+ # it { @dates.select{ |d| @result.include? d }.map{ |d| d.to_s }.should == @dates.map{ |r| r.to_s } }
451
490
 
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
491
  end
456
492
  end
457
493
 
494
+
458
495
  describe 'Marshal dump' do
459
496
  describe "month without year parsing 'marzo'" do
460
497
  before do
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 5
8
- - 3
9
- version: 0.5.3
8
+ - 4
9
+ version: 0.5.4
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-30 00:00:00 -05:00
17
+ date: 2010-09-20 00:00:00 -05:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency