eventual 0.4.9
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +6 -0
- data/Manifest.txt +11 -0
- data/README.rdoc +105 -0
- data/Rakefile +18 -0
- data/eventual.gemspec +33 -0
- data/lib/eventual/date.rb +1 -0
- data/lib/eventual/date_time.rb +1 -0
- data/lib/eventual.rb +193 -0
- data/spec/date_time_spec.rb +15 -0
- data/spec/es_eventual_spec.rb +222 -0
- data/spec/spec_helper.rb +33 -0
- metadata +78 -0
data/History.txt
ADDED
data/Manifest.txt
ADDED
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
|
+
|
data/spec/spec_helper.rb
ADDED
@@ -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
|
+
|