eventual 0.5.3 → 0.5.4

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