eventual 0.4.9 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/eventual.rb CHANGED
@@ -1,193 +1,7 @@
1
+ require 'rubygems'
2
+ require 'treetop'
1
3
  require 'date'
2
- require 'iconv'
3
- require 'strscan'
4
4
 
5
- module Eventual
6
- class WdayMatchError < StandardError; end
7
-
8
-
9
- VERSION = '0.4.9'
10
- extend self
11
-
12
- WDAY_LIST = %w(domingo lunes martes miércoles jueves viernes sábado).freeze
13
- MESES = %w(enero febrero marzo abril mayo junio julio agosto septiembre octubre noviembre diciembre).unshift(nil).freeze
14
- DIAS_DE_LA_SEMANA = WDAY_LIST.map{ |d| d.match(/s$/) ? d : "#{d}s?" }
15
-
16
- def rango_de a, b = nil
17
- a = a.join('|') if Array === a
18
- b ||= a
19
- /(?:de |del )?(?:#{ a }) (?:a|al) (?:#{ b })/
20
- end
21
-
22
- def lista_de elementos
23
- elementos = elementos.join('|') if Array === elementos
24
- /(?:#{ elementos }) # Primer elemento -requerido-
25
- (?: # Cualquier número de
26
- (?-x:, | y ) # concatenador
27
- (?:#{ elementos }) # y elemento.
28
- )*/ix
29
- end
30
-
31
- def plural_opcional elementos
32
- elementos.map{ |d| d.match(/s$/) ? d : "#{d}s?" }
33
- end
34
-
35
- year = /(?-x:del |de )?(\d{4})/i
36
- horarios = /a las (#{ lista_de '\d{1,2}:\d{2}' })(?: horas| hrs)?/i
37
-
38
-
39
- DAY_LIST = /
40
- (#{ lista_de %r"(?:(?:#{ DIAS_DE_LA_SEMANA.join('|') }) )?\d{1,2}" })\s
41
- de\s(#{ MESES.compact.join('|') }) # Mes
42
- (?:\s#{ year })? # Año opcional
43
- (\s#{ horarios })? # Hora opcional
44
- /ixo
45
-
46
- DAY_PERIOD = /
47
- (?:
48
- (
49
- (?:#{ rango_de DIAS_DE_LA_SEMANA })\s
50
- |
51
- (?:#{ lista_de DIAS_DE_LA_SEMANA })\s
52
- )
53
- (?-x:de |del )
54
- )?
55
- (?-x:(?:de |del )?(?:(#{ DIAS_DE_LA_SEMANA.join('|') }) )?(\d{1,2})(?: de (#{ MESES.compact.join('|') })(?: #{ year })?)?)
56
- (?-x: (?:a|al) (?:(#{ DIAS_DE_LA_SEMANA.join('|') }) )?(\d{1,2}) de (#{ MESES.compact.join('|') })(?: #{ year })?)
57
- (?:\s#{ horarios })?
58
- /ixo
59
-
60
- WHOLE_MONTH = /
61
- ( # Dias de la semana opcionales
62
- (?-x:los |todos los )?
63
- (?:
64
- (?:#{ rango_de DIAS_DE_LA_SEMANA })
65
- |
66
- (?:#{ lista_de DIAS_DE_LA_SEMANA })
67
- )\s
68
- (?-x:de|durante|durante todo)\s
69
- )?
70
- (?:
71
- (?:#{ rango_de %r"(#{ MESES.compact.join('|') })(?:\s#{ year })?" })
72
- |
73
- (#{ lista_de MESES.compact })(?:\s#{ year })?
74
- )
75
- (?:\s#{ horarios })? # Hora opcional
76
- /ixo
77
-
78
- def event_parse string, opts = {}, &block
79
- parser = opts.delete(:parser) || (self == Eventual ? DateTime : self)
80
- use_trailing = opts.delete(:use_trailing)
81
- string = string.gsub('miercoles', 'miércoles').gsub('sabado', 'sábado').gsub(/'/, '').gsub(/(\s)+/, '\1')
82
- results = []
83
- scanner = StringScanner.new string
84
-
85
- map_months = lambda{ |months| months.scan(/#{ MESES.compact.join('|') }/).map{ |m| MESES.index(m.downcase) } }
86
- make_range = lambda{ |first, last, min, max| first > last ? (first..max).map + (min..last).map : (first..last).map }
87
-
88
- extract_wdays = lambda do |wdays|
89
- wdays_array = wdays ? wdays.scan( /#{ WDAY_LIST.join('|') }/ ).map{ |d| WDAY_LIST.index d.downcase } : []
90
- next wdays_array unless rango_de(DIAS_DE_LA_SEMANA) === wdays
91
- make_range[wdays_array.first, wdays_array.last, 0, 6]
92
- end
93
-
94
- until scanner.eos?
95
- case match = scanner.scan(/.*?(?:#{ DAY_LIST }|#{ DAY_PERIOD }|#{ WHOLE_MONTH })/m)
96
-
97
- when DAY_PERIOD
98
- wdays, first_wday, first_day, first_month, first_year, last_wday, last_day, last_month, last_year, times = $1, $2, $3, $4, $5, $6, $7, $8, $9, $10
99
-
100
- wdays_array = extract_wdays[wdays]
101
- last_year ||= string.match(/\d{4}/) ? $& : Date.today.year
102
- first_year ||= last_year
103
- first_month ||= last_month
104
- last_month = MESES.index last_month.downcase
105
- first_month = MESES.index first_month.downcase
106
-
107
- make_days = lambda do |hour, minute|
108
- first = make_day parser, first_year, first_month, first_day, hour, minute
109
- last = make_day parser, last_year, last_month, last_day, hour, minute
110
-
111
- [first, last].zip([first_wday, last_wday]).each do |day, wday|
112
- raise WdayMatchError.new("El día #{ day } cae en #{ DIAS_DE_LA_SEMANA[day.wday] }, no en #{ wday.downcase }") unless day.wday == WDAY_LIST.index(wday.downcase) if wday
113
- end
114
-
115
- next (first..last).map if wdays_array.empty?
116
- (first..last).select{ |day| wdays_array.include? day.wday }
117
- end
118
-
119
- when DAY_LIST
120
- daynums, month, year, times = $1, MESES.index($2.downcase), $3, $4
121
-
122
- year ||= string.match(/\d{4}/) ? $& : Date.today.year
123
- make_days = lambda do |hour, minute|
124
- daynums.scan(/(?:(#{ DIAS_DE_LA_SEMANA.join('|') }) )?(\d{1,2})/).collect do |wday, daynum|
125
- day = make_day(parser, year, month, daynum, hour, minute)
126
- raise WdayMatchError.new("El día #{ day } cae en #{ DIAS_DE_LA_SEMANA[day.wday] }, no en #{ wday.downcase }") unless day.wday == WDAY_LIST.index(wday.downcase) if wday
127
- day
128
- end
129
- end
130
-
131
- when WHOLE_MONTH
132
- wdays, month_range_start, starting_year, month_range_end, ending_year, months, year, times = $1, $2, $3, $4, $5, $6, $7, $8
133
- wdays_array = extract_wdays[wdays]
134
-
135
- month_array =
136
- if month_range_start
137
- ending_year ||= Date.today.year
138
- first = Date.civil( (starting_year || ending_year).to_i, MESES.index(month_range_start.downcase) )
139
- last = Date.civil ending_year.to_i, MESES.index(month_range_end.downcase)
140
- (first..last)
141
- else
142
- year ||= Date.today.year
143
- months.scan(/#{ MESES.compact.join('|') }/).map do |m|
144
- Date.civil year.to_i, MESES.index(m.downcase)
145
- end
146
- end
147
-
148
- make_days = lambda do |hour, minute|
149
- months = month_array.map do |date|
150
- first = make_day(parser, date.year, date.month, 1, hour, minute)
151
- last = (first >> 1) - 1
152
- next (first..last).map if wdays_array.empty?
153
- (first..last).select{ |day| wdays_array.include? day.wday }
154
- end.flatten
155
- end
156
-
157
- else
158
- break
159
- end
160
-
161
- extra = scanner.scan(/.*?(?=#{ DAY_LIST }|#{ DAY_PERIOD }|\z)/m).to_s.chomp
162
- extra.gsub!(/^(,|\n|\.)/, '')
163
-
164
- days =
165
- if times
166
- times.scan( /(\d{2}):(\d{2})/ ).map{ |hour, minute| make_days.call hour, minute }.flatten
167
- else
168
- make_days.call nil, nil
169
- end
170
-
171
- days.each { |day| day.instance_variable_set('@extra', extra) }
172
- results += days
173
- end
174
-
175
- raise ArgumentError.new( 'El formato de las fechas parece ser incorrecto' ) if results.empty?
176
- results.uniq!
177
- results.sort!
178
-
179
- use_trailing ? results.map!{ |day| yield day, day.instance_variable_get('@extra') } : results.map!{ |day| yield day } if block_given?
180
- results
181
- end
182
-
183
- protected
184
- def make_day *args
185
- maker = args.shift
186
- if maker == Date
187
- maker.civil *args.compact.collect{ |a| a.to_i }[0...4]
188
- else
189
- maker.civil *args.compact.collect{ |a| a.to_i }
190
- end
191
- end
192
- end
5
+ require "#{ File.dirname __FILE__ }/eventual/syntax_nodes"
193
6
 
7
+ autoload :EsDatesParser, 'eventual/es'
@@ -1,222 +1,435 @@
1
- require File.expand_path( File.dirname(__FILE__) + '/spec_helper' )
1
+ require "#{File.dirname __FILE__}/spec_helper"
2
+ require 'eventual'
2
3
 
3
- describe 'event parsing' do
4
+ describe Eventual, 'Es' do
5
+ before do
6
+ @parser = EsDatesParser.new
7
+ Date.stub!(:today).and_return Date.civil(2010)
8
+ end
4
9
 
5
- describe 'lista de número dia' do
6
- it "should event_parse one day" do
7
- Eventual.event_parse( '1 de enero del 2009' ).should map_times( '2009-1-1' )
8
- end
9
-
10
- it "should event_parse several days" do
11
- Eventual.event_parse( '1, 2 y 3 de enero' ).should map_times( "2009-1-1", "2009-1-2", "2009-1-3" )
12
- end
13
-
14
- it "should match several days with year" do
15
- Eventual.event_parse( '1, 2 y 3 de enero del 2010' ).should map_times( "2010-1-1", "2010-1-2", "2010-1-3" )
16
- end
17
-
18
- it "should event_parse one day with one time" do
19
- Eventual.event_parse( '1 de enero del 2009 a las 16:00 horas' ).should map_times( '2009-1-1T16:00' )
20
- end
21
-
22
- it "should parse one day with wday" do
23
- Eventual.event_parse( 'viernes 1 de enero del 2010' ).should map_times( '2010-1-1' )
10
+ shared_examples_for 'correctly parses' do
11
+ it { @result.should_not be_nil }
12
+ it { @result.to_a.size.should == @dates.map.size }
13
+ it { @result.should map_dates *@dates }
14
+ it { @dates.map{ |date| @result.should include(date) } }
15
+ it { @result.should_not include(@dates.first - 1) }
16
+ it { @result.should_not include(@dates.last + 1) }
17
+ it { @dates.select{ |d| @result.include? d }.map{ |d| d.to_s }.should == @dates.map{ |r| r.to_s } }
18
+ end
19
+
20
+ describe 'month' do
21
+ describe "month without year parsing 'marzo'" do
22
+ before do
23
+ @result = @parser.parse 'marzo'
24
+ @dates = (Date.parse('2010-3-1')..Date.parse('2010-3-31')).map
25
+ end
26
+ it_should_behave_like 'correctly parses'
24
27
  end
25
-
26
- it "should parse list with wday" do
27
- Eventual.event_parse( 'viernes 1, sábado 2, domingo 3 y lunes 4 de enero del 2010' ).should map_times( '2010-1-1', '2010-1-2', '2010-1-3', '2010-1-4' )
28
+
29
+ describe 'month with year' do
30
+ describe "parsing 'marzo de 2009'" do
31
+ before do
32
+ @result = @parser.parse "marzo de 2009"
33
+ @dates = (Date.parse('2009-3-1')..Date.parse('2009-3-31')).map
34
+ end
35
+ it_should_behave_like 'correctly parses'
36
+ end
37
+
38
+ describe "parsing 'marzo del 2009'" do
39
+ before do
40
+ @result = @parser.parse "marzo del 2009"
41
+ @dates = (Date.parse('2009-3-1')..Date.parse('2009-3-31')).map
42
+ end
43
+ it_should_behave_like 'correctly parses'
44
+ end
45
+
46
+ describe "parsing 'marzo 2009'" do
47
+ before do
48
+ @result = @parser.parse "marzo 2009"
49
+ @dates = (Date.parse('2009-3-1')..Date.parse('2009-3-31')).map
50
+ end
51
+ it_should_behave_like 'correctly parses'
52
+ end
53
+
54
+ describe "parsing 'marzo, 2009'" do
55
+ before do
56
+ @result = @parser.parse "marzo, 2009"
57
+ @dates = (Date.parse('2009-3-1')..Date.parse('2009-3-31')).map
58
+ end
59
+ it_should_behave_like 'correctly parses'
60
+ end
61
+
62
+ describe "parsing 'marzo '09'" do
63
+ before do
64
+ @result = @parser.parse "marzo '09"
65
+ @dates = (Date.parse('2009-3-1')..Date.parse('2009-3-31')).map
66
+ end
67
+ it_should_behave_like 'correctly parses'
68
+ end
28
69
  end
29
-
30
- it "should blow if wday doesn't correspond" do
31
- lambda{ Eventual.event_parse('sábado 1 de enero del 2010') }.should raise_error(Eventual::WdayMatchError)
70
+
71
+ describe 'month with wdays' do
72
+ before do
73
+ @dates = (Date.parse('2010-3-1')..Date.parse('2010-3-31')).reject{ |day| not [1,2].include?(day.wday) }
74
+ end
75
+
76
+ describe "parsing 'lunes y martes marzo del 2010'" do
77
+ before { @result = @parser.parse "lunes y martes marzo del 2010" }
78
+ it_should_behave_like 'correctly parses'
79
+ end
80
+
81
+ describe "parsing 'lunes y martes de marzo del 2010'" do
82
+ before { @result = @parser.parse "lunes y martes de marzo del 2010" }
83
+ it_should_behave_like 'correctly parses'
84
+ end
85
+
86
+ describe "parsing 'lunes y martes durante marzo del 2010'" do
87
+ before { @result = @parser.parse "lunes y martes durante marzo del 2010" }
88
+ it_should_behave_like 'correctly parses'
89
+ end
90
+
91
+ describe "parsing 'lunes y martes durante todo marzo del 2010'" do
92
+ before { @result = @parser.parse "lunes y martes durante todo marzo del 2010" }
93
+ it_should_behave_like 'correctly parses'
94
+ end
95
+
96
+ describe "parsing 'lunes y martes, marzo del 2010'" do
97
+ before { @result = @parser.parse "lunes y martes, marzo del 2010" }
98
+ it_should_behave_like 'correctly parses'
99
+ end
32
100
  end
101
+
33
102
  end
34
103
 
35
- describe 'lista de rango de número de día' do
36
- it "should event_parse a period" do
37
- Eventual.event_parse( 'del 1 al 3 de enero' ).should map_times( '2009-1-1', '2009-1-2', '2009-1-3' )
38
- end
39
-
40
- it "should event_parse a period with year" do
41
- Eventual.event_parse( 'del 1 al 3 de enero 2010' ).should map_times( '2010-1-1', '2010-1-2', '2010-1-3' )
104
+ describe 'day numbers' do
105
+ describe 'single date' do
106
+ before do
107
+ @dates = [Date.civil 2010, 3, 21]
108
+ end
109
+
110
+ describe "should single day number for '21 de marzo'" do
111
+ before { @result = @parser.parse("21 de marzo") }
112
+ it_should_behave_like 'correctly parses'
113
+ end
114
+
115
+ describe "parsing '21 marzo'" do
116
+ before { @result = @parser.parse("21 marzo") }
117
+ it_should_behave_like 'correctly parses'
118
+ end
119
+
120
+ # describe "parsing 'marzo 21'" do
121
+ # before { @result = @parser.parse("21 marzo") }
122
+ # it_should_behave_like 'correctly parses'
123
+ # end
124
+
125
+ describe 'date with wday' do
126
+ describe "parsing 'domingo 21 de marzo'" do
127
+ before { @result = @parser.parse("domingo 21 de marzo") }
128
+ it_should_behave_like 'correctly parses'
129
+ end
130
+
131
+ it "should raise WdayMatchError if weekday doesn't correspond to date" do
132
+ lambda { @parser.parse("lunes 21 de marzo").map }.should raise_error(Eventual::WdayMatchError)
133
+ end
134
+ end
42
135
  end
43
-
44
- it "should event_parse a period with time" do
45
- Eventual.event_parse( 'miércoles del 1 al 3 de junio' ).should map_times( '2009-6-3' )
136
+
137
+ describe 'day list' do
138
+ before do
139
+ @dates = (1..3).map{ |i| Date.civil( 2010, 3, i) }
140
+ end
141
+
142
+ describe "day list for '1, 2 y 3 de marzo'" do
143
+ before { @result = @parser.parse("1, 2 y 3 marzo") }
144
+ it_should_behave_like 'correctly parses'
145
+ end
146
+
147
+ describe "day list for '1, 2 y 3 marzo'" do
148
+ before { @result = @parser.parse("1, 2 y 3 de marzo") }
149
+ it_should_behave_like 'correctly parses'
150
+ end
151
+
152
+ describe "day list with weekday 'lunes 1, martes 2 y miercoles 3 de marzo'" do
153
+ before { @result = @parser.parse("lunes 1, martes 2 y miercoles 3 de marzo") }
154
+ it_should_behave_like 'correctly parses'
155
+ end
156
+
157
+ it "should raise WdayMatchError if weekday doesn't correspond to date" do
158
+ lambda { @parser.parse("lunes 2, martes 2 y jueves 3 de marzo").map }.should raise_error(Eventual::WdayMatchError)
159
+ end
46
160
  end
47
-
48
- it "should event_parse a period with time" do
49
- Eventual.event_parse( 'miércoles del 1 al 3 de junio a las 16:00 horas' ).should map_times( '2009-6-3T16:00' )
161
+ end
162
+
163
+ describe 'day range' do
164
+ describe 'period in same month' do
165
+ before do
166
+ @dates = (1..3).map{ |i| Date.civil( 2010, 3, i) }
167
+ end
168
+
169
+ describe "day list for '1 al 3 de marzo" do
170
+ before { @result = @parser.parse("1 al 3 de marzo del '10") }
171
+ it_should_behave_like 'correctly parses'
172
+ end
173
+
174
+ describe "day list for '1 al 3, marzo" do
175
+ before { @result = @parser.parse("1 al 3, marzo del '10") }
176
+ it_should_behave_like 'correctly parses'
177
+ end
178
+
179
+ describe "day list for 'del 1 al 3 de marzo" do
180
+ before { @result = @parser.parse("del 1 al 3 de marzo del '10") }
181
+ it_should_behave_like 'correctly parses'
182
+ end
183
+
184
+ describe "day list for 'del 1 al 3, marzo" do
185
+ before { @result = @parser.parse("del 1 al 3, marzo del '10") }
186
+ it_should_behave_like 'correctly parses'
187
+ end
50
188
  end
51
-
52
- it "should event_parse one day with several times" do
53
- Eventual.event_parse( '1 de enero del 2009 a las 16:00 y 17:00' ).should map_times( '2009-1-1T16:00', '2009-1-1T:17:00' )
189
+
190
+ describe "spanning diferent months '24 de febrero al 3 de marzo del 2010" do
191
+ before do
192
+ @result = @parser.parse "24 de febrero al 3 de marzo del 2010"
193
+ @dates = (Date.parse('2010-2-24')..Date.parse('2010-3-3'))
194
+ end
195
+ it_should_behave_like 'correctly parses'
54
196
  end
55
-
56
- it "should event_parse period spanning more than one month" do
57
- Eventual.event_parse( 'del 29 de enero al 3 de febrero' ).should map_times( '2009-1-29', '2009-1-30', '2009-1-31', '2009-2-1', '2009-2-2', '2009-2-3' )
197
+
198
+ describe "spanning diferent years '24 de diciembre del 2009 al 3 de enero del 2010" do
199
+ before do
200
+ @result = @parser.parse("24 de diciembre del 2009 al 3 de enero del 2010")
201
+ @dates = (Date.parse('2009-12-24')..Date.parse('2010-1-3'))
202
+ end
203
+ it_should_behave_like 'correctly parses'
58
204
  end
59
205
 
60
- it "should parse period spanning across year" do
61
- Eventual.event_parse( 'del 28 de diciembre del 2009 al 2 de enero del 2010').should map_times( '2009-12-28', '2009-12-29', '2009-12-30', '2009-12-31', '2010-1-1', '2010-1-2')
62
- end
63
-
64
- it "should parse range with wday" do
65
- Eventual.event_parse( 'viernes 1 al domingo 3 de enero del 2010' ).should map_times( '2010-1-1', '2010-1-2', '2010-1-3' )
66
- end
67
-
68
- it "should blow if wday doesn't correspond" do
69
- lambda{ Eventual.event_parse('viernes 2 a domingo 4 de enero del 2010') }.should raise_error(Eventual::WdayMatchError)
70
- end
206
+ describe 'period spanning two dates' do
207
+ before do
208
+ @dates = (Date.parse('2008-10-1')..DateTime.parse('2008-12-2'))
209
+ end
210
+
211
+ describe "1 de octubre a 2 de diciembre del 2008" do
212
+ before { @result = @parser.parse "1 de octubre a 2 de diciembre del 2008" }
213
+ it_should_behave_like 'correctly parses'
214
+ end
71
215
 
72
- describe 'restringido por dia de la semana' do
73
- it "should parse all tuesdays and thursdays of the year" do
74
- e = Eventual.event_parse( 'martes y jueves del 1 de enero al 31 de diciembre del 2008')
75
- r = ( DateTime.parse('2008-1-1')..DateTime.parse('2008-12-31') ).reject{ |day| not [2,4].include?(day.wday) }
76
- e.should map_times( *r )
216
+ describe "1 de octubre al 2 de diciembre del 2008" do
217
+ before { @result = @parser.parse "1 de octubre al 2 de diciembre del 2008" }
218
+ it_should_behave_like 'correctly parses'
77
219
  end
78
220
 
79
- it "should parse all tuesdays and thursdays of the year with time" do
80
- e = Eventual.event_parse( 'martes y jueves del 1 de enero al 31 de diciembre del 2008 a las 16:00')
81
- r = ( DateTime.parse('2008-1-1T16:00')..DateTime.parse('2008-12-31T16:00') ).reject{ |day| not [2,4].include?(day.wday) }
82
- e.should map_times( *r )
221
+ describe "del miercoles 1 de octubre al martes 2 de diciembre del 2008" do
222
+ before { @result = @parser.parse "del miercoles 1 de octubre al martes 2 de diciembre del 2008" }
223
+ it_should_behave_like 'correctly parses'
83
224
  end
225
+ end
84
226
 
85
- it "should parse all saturdays and sundays of the year with time" do
86
- e = Eventual.event_parse( 'sábado y domingo del 1 de enero al 31 de diciembre del 2008 a las 16:00')
87
- r = ( DateTime.parse('2008-1-1T16:00')..DateTime.parse('2008-12-31T16:00') ).reject{ |day| not [0,6].include?(day.wday) }
88
- e.should map_times( *r )
227
+ describe "lunes y martes del 1 de octubre al 2 de diciembre del 2008" do
228
+ before do
229
+ @result = @parser.parse "lunes y martes del 1 de octubre al 2 de diciembre del 2008"
230
+ @dates = (Date.parse('2008-10-1')..DateTime.parse('2008-12-2')).reject{ |day| not [1,2].include?(day.wday) }
231
+ end
232
+ it_should_behave_like 'correctly parses'
233
+ end
234
+
235
+ describe 'with weekday constrain' do
236
+ describe "wdays for 'lunes y martes del 1 al 22 de marzo del '10" do
237
+ before do
238
+ @result = @parser.parse "lunes y martes del 1 al 22 de marzo del '10"
239
+ @dates = (Date.parse('2010-3-1')..Date.parse('2010-3-22')).reject{ |day| not [1,2].include?(day.wday) }
240
+ end
241
+ it_should_behave_like 'correctly parses'
89
242
  end
90
243
 
91
- it "should parse all pluralized saturdays and sundays of the year with time" do
92
- e = Eventual.event_parse( 'sábados y domingos del 1 de enero al 31 de diciembre del 2008 a las 16:00')
93
- r = ( DateTime.parse('2008-1-1T16:00')..DateTime.parse('2008-12-31T16:00') ).reject{ |day| not [0,6].include?(day.wday) }
94
- e.should map_times( *r )
244
+ describe "wdays for 'fines de semana del 1 al 22 de marzo del '10" do
245
+ before do
246
+ @result = @parser.parse "fines de semana del 1 al 22 de marzo del '10"
247
+ @dates = (Date.parse('2010-3-1')..Date.parse('2010-3-22')).map.reject{ |day| not [6,0].include?(day.wday) }
248
+ end
249
+ it_should_behave_like 'correctly parses'
95
250
  end
96
251
 
97
- it "should parse week day period" do
98
- e = Eventual.event_parse( 'lunes a viernes del 1 de enero al 31 de diciembre del 2008 a las 16:00')
99
- r = ( DateTime.parse('2008-1-1T16:00')..DateTime.parse('2008-12-31T16:00') ).reject{ |day| not (1..5).map.include?(day.wday) }
100
- e.should map_times( *r )
252
+ describe "wdays for 'entre semana del 1 al 22 de marzo del '10" do
253
+ before do
254
+ @result = @parser.parse("entre semana del 1 al 22 de marzo del '10")
255
+ @dates = (Date.parse('2010-3-1')..Date.parse('2010-3-22')).map.reject{ |day| not (1..5).map.include?(day.wday) }
256
+ end
257
+ it_should_behave_like 'correctly parses'
101
258
  end
259
+
260
+ describe 'sugar for wday constrain' do
261
+ before do
262
+ @dates = (Date.parse('2010-3-1')..Date.parse('2010-3-22')).reject{ |day| not [1,2].include?(day.wday) }
263
+ end
264
+
265
+ describe "wdays for 'lunes y martes del 1 al 22 de marzo del '10" do
266
+ before { @result = @parser.parse("lunes y martes del 1 al 22 de marzo del '10") }
267
+ it_should_behave_like 'correctly parses'
268
+ end
102
269
 
103
- it "should parse week day period across week" do
104
- e = Eventual.event_parse( 'viernes a lunes del 1 de enero al 31 de diciembre del 2008 a las 16:00')
105
- r = ( DateTime.parse('2008-1-1T16:00')..DateTime.parse('2008-12-31T16:00') ).reject{ |day| not [5,6,0,1].map.include?(day.wday) }
106
- e.should map_times( *r )
270
+ describe "wdays for 'todos los lunes y martes del 1 al 22 de marzo del '10" do
271
+ before { @result = @parser.parse("todos los lunes y martes del 1 al 22 de marzo del '10") }
272
+ it_should_behave_like 'correctly parses'
273
+ end
274
+
275
+ describe "wdays for 'los lunes y martes del 1 al 22 de marzo del '10" do
276
+ before { @result = @parser.parse("los lunes y martes del 1 al 22 de marzo del '10") }
277
+ it_should_behave_like 'correctly parses'
278
+ end
279
+
280
+ describe "wdays for 'los lunes y los martes del 1 al 22 de marzo del '10" do
281
+ before { @result = @parser.parse("los lunes y los martes del 1 al 22 de marzo del '10") }
282
+ it_should_behave_like 'correctly parses'
283
+ end
107
284
  end
108
285
  end
109
286
  end
110
-
111
- describe 'Meses completos' do
112
- it "should parse a single month" do
113
- ['diciembre del 2008', 'durante diciembre del 2008', 'durante todo diciembre del 2008'].each do |e|
114
- Eventual.event_parse(e).should map_times( *(DateTime.parse('2008-12-1T00:00')..DateTime.parse('2008-12-31T00:00')).map )
287
+
288
+ describe 'month range' do
289
+ describe 'octubre a diciembre del 2008' do
290
+ before do
291
+ @result = @parser.parse('octubre a diciembre del 2008')
292
+ @dates = (Date.parse('2008-10-1')..DateTime.parse('2008-12-31')).map
115
293
  end
294
+ it_should_behave_like 'correctly parses'
116
295
  end
117
-
118
- it "should parse two full months" do
119
- ['noviembre y diciembre del 2008', 'durante noviembre y diciembre del 2008', 'durante todo noviembre y diciembre del 2008'].each do |e|
120
- Eventual.event_parse(e).should map_times( *(DateTime.parse('2008-11-1T00:00')..DateTime.parse('2008-12-31T00:00')).map )
296
+
297
+
298
+ describe 'lunes y martes de octubre del 2007 a diciembre del 2008' do
299
+ before do
300
+ @result = @parser.parse('lunes y martes de octubre del 2007 a diciembre del 2008')
301
+ @dates = (Date.parse('2007-10-1')..DateTime.parse('2008-12-31')).reject{ |day| not [1,2].include?(day.wday) }
121
302
  end
303
+ it_should_behave_like 'correctly parses'
122
304
  end
123
-
124
- it "should parse severals full months" do
125
- ['octubre, noviembre y diciembre del 2008', 'durante octubre, noviembre y diciembre del 2008', 'durante todo octubre, noviembre y diciembre del 2008'].each do |e|
126
- Eventual.event_parse(e).should map_times( *(DateTime.parse('2008-10-1T00:00')..DateTime.parse('2008-12-31T00:00')).map )
127
- end
305
+ end
306
+
307
+ describe 'compound dates giving year at the end' do
308
+ before do
309
+ @result = @parser.parse "1 de enero y lunes y martes del 1 de octubre al 2 de diciembre del 2008"
310
+ @dates = [Date.parse('2008-1-1')] + (Date.parse('2008-10-1')..Date.parse('2008-12-2')).reject{ |day| not [1,2].include?(day.wday) }
128
311
  end
312
+ it_should_behave_like 'correctly parses'
313
+ end
129
314
 
130
- it "should parse a full month with time" do
131
- Eventual.event_parse('diciembre del 2008 a las 16:00 horas').should map_times( *(DateTime.parse('2008-12-1T16:00')..DateTime.parse('2008-12-31T16:00')).map )
315
+ describe 'compound dates in different lines' do
316
+ before do
317
+ @result = @parser.parse "1 de enero\nlunes y martes del 1 de octubre al 2 de diciembre del 2008"
318
+ @dates = [Date.parse('2008-1-1')] + (Date.parse('2008-10-1')..Date.parse('2008-12-2')).reject{ |day| not [1,2].include?(day.wday) }
132
319
  end
320
+ it_should_behave_like 'correctly parses'
321
+ end
133
322
 
134
- it "should parse a full month with time with days" do
135
- Eventual.event_parse('domingos de diciembre del 2008').should map_times( *(DateTime.parse('2008-12-1T00:00')..DateTime.parse('2008-12-31T00:00')).reject{ |day| not [0].include?(day.wday) } )
323
+ describe 'with time constrain' do
324
+ shared_examples_for 'outputs DateTime' do
325
+ it "should all be DateTime" do
326
+ @result.map{ |d| d.should be_a(DateTime) }
327
+ end
136
328
  end
137
329
 
138
- it "should parse a full month with time with days and sugar" do
139
- ['todos los domingos de diciembre del 2008', 'los domingos durante todo diciembre del 2008'].each do |e|
140
- Eventual.event_parse(e).should map_times( *(DateTime.parse('2008-12-1T00:00')..DateTime.parse('2008-12-31T00:00')).reject{ |day| not [0].include?(day.wday) } )
330
+ describe 'single day with time' do
331
+ before do
332
+ @result = @parser.parse('1 de enero del 2010 a las 15:00')
333
+ @dates = [DateTime.civil 2010, 1, 1, 15]
141
334
  end
335
+ it_should_behave_like 'correctly parses'
336
+ it_should_behave_like 'outputs DateTime'
142
337
  end
143
338
 
144
- it "should parse a full month with time with days" do
145
- ['sábados y domingos de diciembre del 2008', 'todos los sábados y domingos de diciembre del 2008', 'sábados y domingos durante todo diciembre del 2008'].each do |e|
146
- Eventual.event_parse(e).should map_times( *(DateTime.parse('2008-12-1T00:00')..DateTime.parse('2008-12-31T00:00')).reject{ |day| not [0, 6].include?(day.wday) } )
339
+ describe 'single time with no sugar for month range' do
340
+ before do
341
+ @result = @parser.parse('lunes y martes de diciembre del 2010 a las 15:00')
342
+ @dates = (DateTime.parse('2010-12-1T15:00')..DateTime.parse('2010-12-31T15:00')).reject{ |day| not [1,2].include?(day.wday) }
147
343
  end
344
+ it_should_behave_like 'correctly parses'
345
+ it_should_behave_like 'outputs DateTime'
148
346
  end
149
347
 
150
- it "should parse a full month with time with days" do
151
- ['todos los sábados a lunes de diciembre del 2008', 'sábado a lunes de diciembre del 2008', 'sábados a lunes durante todo diciembre del 2008'].each do |e|
152
- Eventual.event_parse(e).should map_times( *(DateTime.parse('2008-12-1T00:00')..DateTime.parse('2008-12-31T00:00')).reject{ |day| not [0, 1, 6].include?(day.wday) } )
348
+ describe 'single time with sugar 1 for month range' do
349
+ before do
350
+ @result = @parser.parse('lunes y martes de diciembre a las 15:00 hrs.')
351
+ @dates = (DateTime.parse('2010-12-1T15:00')..DateTime.parse('2010-12-31T15:00')).reject{ |day| not [1,2].include?(day.wday) }
153
352
  end
353
+ it_should_behave_like 'correctly parses'
354
+ it_should_behave_like 'outputs DateTime'
154
355
  end
155
356
 
156
- it "should parse without year" do
157
- Eventual.event_parse('sábados de diciembre').should map_times( *(DateTime.parse("#{ y = Date.today.year }-12-1T00:00")..DateTime.parse("#{ y }-12-31T00:00")).reject{ |day| not [6].include?(day.wday) } )
357
+ describe 'single time with sugar 2 for month range' do
358
+ before do
359
+ @result = @parser.parse('lunes y martes de diciembre a las 15:00hrs')
360
+ @dates = (DateTime.parse('2010-12-1T15:00')..DateTime.parse('2010-12-31T15:00')).reject{ |day| not [1,2].include?(day.wday) }
361
+ end
362
+ it_should_behave_like 'correctly parses'
363
+ it_should_behave_like 'outputs DateTime'
158
364
  end
159
365
 
160
- it "should parse month range" do
161
- Eventual.event_parse('octubre a diciembre del 2008').should map_times( *(DateTime.parse('2008-10-1T00:00')..DateTime.parse('2008-12-31T00:00')).map )
366
+ describe 'single time with sugar 3 for month range' do
367
+ before do
368
+ @result = @parser.parse('lunes y martes de diciembre a las 15 horas')
369
+ @dates = (DateTime.parse('2010-12-1T15:00')..DateTime.parse('2010-12-31T15:00')).reject{ |day| not [1,2].include?(day.wday) }
370
+ end
371
+ it_should_behave_like 'correctly parses'
372
+ it_should_behave_like 'outputs DateTime'
162
373
  end
163
374
 
164
- it "should parse month range" do
165
- Eventual.event_parse('diciembre del 2008 a enero del 2009').should map_times( *(DateTime.parse('2008-12-1T00:00')..DateTime.parse('2009-1-31T00:00')).map )
166
- end
167
- end
168
-
169
- it "should event_parse a period with block" do
170
- Eventual.event_parse( 'del 5 al 7 de junio 2009' ){ |d| Eventual::WDAY_LIST[ d.wday ] }.should == ['viernes', 'sábado', 'domingo']
171
- end
172
-
173
- it "should parse several expressions" do
174
- Eventual.event_parse( '1 de enero y 2 de febrero del 2008' ).should map_times( '2008-1-1', '2008-2-2' )
175
- end
176
-
177
- it "should event_parse period spanning more than one month" do
178
- Eventual.event_parse( '1 de enero, del 29 de enero al 3 de febrero y 2 de febrero del 2008' ).should map_times( '2008-1-1', '2008-1-29', '2008-1-30', '2008-1-31', '2008-2-1', '2008-2-2', '2008-2-3' )
179
- end
180
-
181
- it "should event_parse a several dates separated by \\n" do |d, extra|
182
- Eventual.event_parse( "1 de enero del 2009\n2 de enero del 2009" ) do |d|
183
- d.to_s
184
- end.should == ["2009-01-01T00:00:00+00:00", "2009-01-02T00:00:00+00:00"]
185
- end
186
-
187
- describe 'With extra data' do
188
- it "should event_parse one day with one time" do
189
- Eventual.event_parse( "1 de enero del 2009 a las 16:00 horas\nSede:Áreas verdes\nCupo: limitado", :use_trailing => true ) do |day, extra|
190
- day.to_s.should == "2009-01-01T16:00:00+00:00"
191
- extra.should == "Sede:Áreas verdes\nCupo: limitado"
375
+ describe 'two times for month range' do
376
+ before do
377
+ @result = @parser.parse('lunes y martes de diciembre a las 16:00 y 15:00 horas')
378
+ @dates = ((DateTime.parse('2010-12-1T15:00')..DateTime.parse('2010-12-31T15:00')).map + (DateTime.parse('2010-12-1T16:00')..DateTime.parse('2010-12-31T16:00')).map).reject{ |day| not [1,2].include?(day.wday) }
379
+ end
380
+ it_should_behave_like 'correctly parses'
381
+ it_should_behave_like 'outputs DateTime'
382
+
383
+ it "should not include other time" do
384
+ @result.should_not include(DateTime.parse('2010-12-06T14:00'))
192
385
  end
193
386
  end
194
-
195
- it "should event_parse a period with block" do
196
- Eventual.event_parse( "del 5 al 7 de junio 2009\nSede:El tercer lugar\nCupo: limitado", :use_trailing => true ) do |d, extra|
197
- extra.should == "Sede:El tercer lugar\nCupo: limitado"
198
- Eventual::WDAY_LIST[ d.wday ]
199
- end.should == ['viernes', 'sábado', 'domingo']
387
+
388
+ describe 'range with time as 12 hours am' do
389
+ before do
390
+ @result = @parser.parse('lunes y martes de diciembre a las 3 am')
391
+ @dates = ((DateTime.parse('2010-12-1T03:00')..DateTime.parse('2010-12-31T03:00')).map).reject{ |day| not [1,2].include?(day.wday) }
392
+ end
393
+ it_should_behave_like 'correctly parses'
394
+ it_should_behave_like 'outputs DateTime'
395
+
396
+ it "should not include other time" do
397
+ @result.should_not include(DateTime.parse('2010-12-06T14:00'))
398
+ end
200
399
  end
201
400
 
202
- it "should event_parse a several dates" do
203
- Eventual.event_parse( "1 de enero del 2009\nSede:El tercer lugar\nCupo: limitado\n2 de enero del 2009\nSede:El tercer lugar\nCupo: limitado", :use_trailing => true ) do |d, extra|
204
- extra.should == "Sede:El tercer lugar\nCupo: limitado"
205
- d.to_s
206
- end.should == ["2009-01-01T00:00:00+00:00", "2009-01-02T00:00:00+00:00"]
401
+ describe 'range with time as 12 hours pm' do
402
+ before do
403
+ @result = @parser.parse('lunes y martes de diciembre a las 3:00 pm')
404
+ @dates = ((DateTime.parse('2010-12-1T15:00')..DateTime.parse('2010-12-31T15:00')).map).reject{ |day| not [1,2].include?(day.wday) }
405
+ end
406
+ it_should_behave_like 'correctly parses'
407
+ it_should_behave_like 'outputs DateTime'
408
+
409
+ it "should not include other time" do
410
+ @result.should_not include(DateTime.parse('2010-12-06T14:00'))
411
+ end
207
412
  end
413
+ end
208
414
 
209
- it "should event_parse a several dates" do
210
- Eventual.event_parse( "1 de enero del 2009\nSede 1\n\n2 de enero del 2009\nSede 2", :use_trailing => true ) do |d, extra|
211
- [d.to_s, extra]
212
- end.should == [["2009-01-01T00:00:00+00:00", "Sede 1"], ["2009-01-02T00:00:00+00:00", "Sede 2"]]
415
+ describe 'Marshal dump' do
416
+ describe "month without year parsing 'marzo'" do
417
+ before do
418
+ @result = Marshal.load Marshal.dump(@parser.parse('marzo')).gsub('NaturalDates::', 'NaturalDates::Eventual::Es::')
419
+ @dates = (Date.parse('2010-3-1')..Date.parse('2010-3-31')).map
420
+ end
421
+ it_should_behave_like 'correctly parses'
213
422
  end
214
423
  end
215
424
 
216
- describe 'Case sensitivity' do
217
- it "should ignore case" do
218
- Eventual.event_parse( 'DeL 1 al 3 de ENeRO' ).should map_times( '2009-1-1', '2009-1-2', '2009-1-3' )
425
+ describe 'Default year' do
426
+ describe "month without year parsing 'marzo'" do
427
+ before do
428
+ @result = @parser.parse('marzo')
429
+ @result.year = 2007
430
+ @dates = (Date.parse('2007-3-1')..Date.parse('2007-3-31')).map
431
+ end
432
+ it_should_behave_like 'correctly parses'
219
433
  end
220
434
  end
221
435
  end
222
-