eventual 0.4.9

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/History.txt ADDED
@@ -0,0 +1,6 @@
1
+ == 0.4.9 2009-11-10
2
+
3
+ * Nuevos formatos reconocidos:
4
+
5
+
6
+
data/Manifest.txt ADDED
@@ -0,0 +1,11 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.rdoc
4
+ Rakefile
5
+ lib/eventual.rb
6
+ lib/eventual/date.rb
7
+ lib/eventual/date_time.rb
8
+ spec/date_time_spec.rb
9
+ spec/es_eventual_spec.rb
10
+ spec/spec_helper.rb
11
+ eventual.gemspec
data/README.rdoc ADDED
@@ -0,0 +1,105 @@
1
+ = eventual
2
+
3
+ * http://github.com/maca/eventual
4
+
5
+ == DESCRIPCIÓN:
6
+
7
+ Reconocimiento de fechas y periodos en lenguaje natural. Útil para crear interfaces de usuario basadas en texto.
8
+
9
+ == SINOPSIS:
10
+
11
+ El método event_parse del modulo Eventual reconoce y convierte una fecha o periodo expresado en lenguaje natural en objetos _Date_ o _DateTime_
12
+ Ejemplos:
13
+
14
+ require 'rubygems'
15
+ require 'eventual'
16
+
17
+ Eventual.event_parse( 'del 5 al 7 de junio' )
18
+ => [#<DateTime: 4909975/2,0,2299161>, #<DateTime: 4909977/2,0,2299161>, #<DateTime: 4909979/2,0,2299161>]
19
+
20
+ Eventual.event_parse( 'del 5 al 7 de junio 2009', Date )
21
+ => [#<Date: 4909975/2,0,2299161>, #<Date: 4909977/2,0,2299161>, #<Date: 4909979/2,0,2299161>]
22
+
23
+ Eventual.event_parse( 'del 5 al 7 de junio del 2009 a las 16:00 y 18:00 horas' ){ |d| d.to_s }
24
+ => ["2009-06-05T16:00:00+00:00", "2009-06-05T18:00:00+00:00", "2009-06-06T16:00:00+00:00", "2009-06-06T18:00:00+00:00", "2009-06-07T16:00:00+00:00", "2009-06-07T18:00:00+00:00"]
25
+
26
+ Eventual.event_parse( 'del 5 al 7 de junio 2009' ){ |d| Eventual::WDAY_LIST[ d.wday ] }
27
+ => ['viernes', 'sabado', 'domingo']
28
+
29
+ Ejemplos de formatos reconocidos:
30
+
31
+ * 1 de enero
32
+ * 21, 22 y 23 de enero del 2009
33
+ * 21, 22 y 23 de enero a las 20:00 horas
34
+ * 21, 22 y 23 de enero a las 20:00 y 22:00 horas
35
+ * viernes 1, sábado 2, domingo 3 y lunes 4 de enero del 2010
36
+ * martes y miércoles del 1 al 20 de junio del 2009 a las 16:00 y 18:00 horas
37
+ * sábados y domingos del 1 de enero al 31 de diciembre del 2008 a las 16:00
38
+ * sábado y domingo del 1 de enero al 31 de diciembre
39
+ * lunes a viernes del 1 de enero al 31 de diciembre del 2008 a las 16:00
40
+ * todos los sábados de diciembre del 2009
41
+ * lunes a viernes de enero a abril
42
+ * del viernes 1 al domingo 3 de enero del 2010
43
+
44
+ Se puede extender _Date_ y _DateTime_ con Eventual requiriendo 'eventual/date_time' y 'eventual/date':
45
+
46
+ require 'rubygems'
47
+ require 'eventual'
48
+ require 'eventual/date_time'
49
+ require 'eventual/date'
50
+
51
+ DateTime.event_parse( 'del 5 al 7 de junio' )
52
+ => [#<DateTime: 4909975/2,0,2299161>, #<DateTime: 4909977/2,0,2299161>, #<DateTime: 4909979/2,0,2299161>]
53
+
54
+ Date.event_parse( 'del 5 al 7 de junio 2009' )
55
+ => [#<Date: 4909975/2,0,2299161>, #<Date: 4909977/2,0,2299161>, #<Date: 4909979/2,0,2299161>]
56
+
57
+
58
+ Si se pasa un bloque se puede especificar si se desea usar el texto que sigue a la definición de fechas mediante pasando la opción _use_trailing_ => _true_:
59
+
60
+ str = "1 de enero del 2009\nSede:El tercer lugar\n2 de enero del 2009\nSede:El tercer lugar"
61
+ Eventual.event_parse( str, :use_trailing => true ) do |dia, texto_extra|
62
+ [dia.to_s, texto_extra]
63
+ end
64
+ => [["2009-01-01T00:00:00+00:00", "Sede:El tercer lugar"], ["2009-01-02T00:00:00+00:00", "Sede:El tercer lugar"]]
65
+
66
+ == TODO:
67
+
68
+ * No estoy seguro de que Iconv funcione en windows, lo arreglaré pronto
69
+
70
+ Formatos a reconocer
71
+
72
+ * todos los lunes de junio
73
+ * todo junio
74
+ * domingos de septiembre
75
+ * martes y miércoles de agosto
76
+ * todo el año
77
+
78
+ == INSTALACIÓN:
79
+
80
+ sudo gem install maca-eventual -s http://gems.github.com
81
+
82
+ == LICENCIA:
83
+
84
+ (The MIT License)
85
+
86
+ Copyright (c) 2009 Macario Ortega
87
+
88
+ Permission is hereby granted, free of charge, to any person obtaining
89
+ a copy of this software and associated documentation files (the
90
+ 'Software'), to deal in the Software without restriction, including
91
+ without limitation the rights to use, copy, modify, merge, publish,
92
+ distribute, sublicense, and/or sell copies of the Software, and to
93
+ permit persons to whom the Software is furnished to do so, subject to
94
+ the following conditions:
95
+
96
+ The above copyright notice and this permission notice shall be
97
+ included in all copies or substantial portions of the Software.
98
+
99
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
100
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
101
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
102
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
103
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
104
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
105
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,18 @@
1
+ require 'rubygems' unless ENV['NO_RUBYGEMS']
2
+ %w[rake rake/clean fileutils newgem rubigen].each { |f| require f }
3
+ require File.dirname(__FILE__) + '/lib/eventual'
4
+
5
+
6
+ $hoe = Hoe.new('eventual', Eventual::VERSION) do |p|
7
+ p.developer('Macario Ortega', 'macarui@gmail.com')
8
+ p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
9
+ p.rubyforge_name = p.name
10
+
11
+ p.clean_globs |= %w[**/.DS_Store tmp *.log]
12
+ p.rsync_args = '-av --delete --ignore-errors'
13
+ end
14
+
15
+ require 'newgem/tasks' # load /tasks/*.rake
16
+ Dir['tasks/**/*.rake'].each { |t| load t }
17
+
18
+ task :default => :spec
data/eventual.gemspec ADDED
@@ -0,0 +1,33 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{eventual}
5
+ s.version = "0.4.9"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Macario Ortega"]
9
+ s.date = %q{2009-11-10}
10
+ s.description = %q{}
11
+ s.email = ["macarui@gmail.com"]
12
+ s.extra_rdoc_files = ["History.txt", "Manifest.txt", "README.rdoc"]
13
+ s.files = ["History.txt", "Manifest.txt", "README.rdoc", "Rakefile", "lib/eventual.rb", "lib/eventual/date.rb", "lib/eventual/date_time.rb", "spec/date_time_spec.rb", "spec/es_eventual_spec.rb", "spec/spec_helper.rb", "eventual.gemspec"]
14
+ s.homepage = %q{http://github.com/maca/eventual}
15
+ s.rdoc_options = ["--main", "README.rdoc"]
16
+ s.require_paths = ["lib"]
17
+ s.rubyforge_project = %q{eventual}
18
+ s.rubygems_version = %q{1.3.5}
19
+ s.summary = %q{}
20
+
21
+ if s.respond_to? :specification_version then
22
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
23
+ s.specification_version = 3
24
+
25
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
26
+ s.add_development_dependency(%q<hoe>, [">= 1.8.0"])
27
+ else
28
+ s.add_dependency(%q<hoe>, [">= 1.8.0"])
29
+ end
30
+ else
31
+ s.add_dependency(%q<hoe>, [">= 1.8.0"])
32
+ end
33
+ end
@@ -0,0 +1 @@
1
+ Date.send :extend, Eventual
@@ -0,0 +1 @@
1
+ DateTime.send :extend, Eventual
data/lib/eventual.rb ADDED
@@ -0,0 +1,193 @@
1
+ require 'date'
2
+ require 'iconv'
3
+ require 'strscan'
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
193
+
@@ -0,0 +1,15 @@
1
+ require File.expand_path( File.dirname(__FILE__) + '/spec_helper' )
2
+ require File.dirname(__FILE__) + '/../lib/eventual/date_time'
3
+ require File.dirname(__FILE__) + '/../lib/eventual/date'
4
+
5
+
6
+ describe 'Monkeypatches' do
7
+ it 'should monkey patch DateTime' do
8
+ DateTime.event_parse( '1 de enero del 2009 a las 16:00' ).should map_times( '2009-1-1T16:00:00+00:00' )
9
+ end
10
+
11
+ it 'should monkey patch Date' do
12
+ Date.event_parse( '1 de enero del 2009 a las 16:00 horas' ).should map_dates( '2009-1-1' )
13
+ end
14
+ end
15
+
@@ -0,0 +1,222 @@
1
+ require File.expand_path( File.dirname(__FILE__) + '/spec_helper' )
2
+
3
+ describe 'event parsing' do
4
+
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' )
24
+ 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
+ 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)
32
+ end
33
+ end
34
+
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' )
42
+ 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' )
46
+ 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' )
50
+ 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' )
54
+ 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' )
58
+ end
59
+
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
71
+
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 )
77
+ end
78
+
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 )
83
+ end
84
+
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 )
89
+ end
90
+
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 )
95
+ end
96
+
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 )
101
+ end
102
+
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 )
107
+ end
108
+ end
109
+ 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 )
115
+ end
116
+ 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 )
121
+ end
122
+ 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
128
+ end
129
+
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 )
132
+ end
133
+
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) } )
136
+ end
137
+
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) } )
141
+ end
142
+ end
143
+
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) } )
147
+ end
148
+ end
149
+
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) } )
153
+ end
154
+ end
155
+
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) } )
158
+ end
159
+
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 )
162
+ end
163
+
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"
192
+ end
193
+ 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']
200
+ end
201
+
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"]
207
+ end
208
+
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"]]
213
+ end
214
+ end
215
+
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' )
219
+ end
220
+ end
221
+ end
222
+
@@ -0,0 +1,33 @@
1
+ require 'rubygems'
2
+ require 'spec'
3
+
4
+ require File.dirname(__FILE__) + '/../lib/eventual'
5
+
6
+
7
+ class MapDates
8
+ def initialize expected, klass
9
+ @expected = expected.collect do |d|
10
+ d = d.is_a?(String) ? klass.parse(d) : d
11
+ d.to_s
12
+ end.sort
13
+ end
14
+
15
+ def matches? actual
16
+ @actual = actual.collect{ |d| d.to_s }
17
+ @actual == @expected
18
+ end
19
+
20
+ def failure_message
21
+ "expected #{ @expected.inspect }, got #{ @actual.inspect }"
22
+ end
23
+
24
+ end
25
+
26
+ def map_times *times
27
+ MapDates.new times, DateTime
28
+ end
29
+
30
+ def map_dates *times
31
+ MapDates.new times, Date
32
+ end
33
+
metadata ADDED
@@ -0,0 +1,78 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: eventual
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.9
5
+ platform: ruby
6
+ authors:
7
+ - Macario Ortega
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-11-10 00:00:00 -06:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: hoe
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 1.8.0
24
+ version:
25
+ description: ""
26
+ email:
27
+ - macarui@gmail.com
28
+ executables: []
29
+
30
+ extensions: []
31
+
32
+ extra_rdoc_files:
33
+ - History.txt
34
+ - Manifest.txt
35
+ - README.rdoc
36
+ files:
37
+ - History.txt
38
+ - Manifest.txt
39
+ - README.rdoc
40
+ - Rakefile
41
+ - lib/eventual.rb
42
+ - lib/eventual/date.rb
43
+ - lib/eventual/date_time.rb
44
+ - spec/date_time_spec.rb
45
+ - spec/es_eventual_spec.rb
46
+ - spec/spec_helper.rb
47
+ - eventual.gemspec
48
+ has_rdoc: true
49
+ homepage: http://github.com/maca/eventual
50
+ licenses: []
51
+
52
+ post_install_message:
53
+ rdoc_options:
54
+ - --main
55
+ - README.rdoc
56
+ require_paths:
57
+ - lib
58
+ required_ruby_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: "0"
63
+ version:
64
+ required_rubygems_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: "0"
69
+ version:
70
+ requirements: []
71
+
72
+ rubyforge_project: eventual
73
+ rubygems_version: 1.3.5
74
+ signing_key:
75
+ specification_version: 3
76
+ summary: ""
77
+ test_files: []
78
+