eventual 0.4.9

Sign up to get free protection for your applications and to get access to all the features.
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
+