maca-eventual 0.4.3 → 0.4.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +11 -3
- data/eventual.gemspec +1 -1
- data/lib/eventual.rb +55 -50
- data/spec/es_eventual_spec.rb +31 -2
- metadata +3 -2
data/README.rdoc
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
|
5
5
|
== DESCRIPCIÓN:
|
6
6
|
|
7
|
-
Reconocimiento de fechas y periodos en lenguaje natural.
|
7
|
+
Reconocimiento de fechas y periodos en lenguaje natural. Útil para crear interfaces de usuario basadas en texto.
|
8
8
|
|
9
9
|
== SINOPSIS:
|
10
10
|
|
@@ -49,9 +49,17 @@ Para activar el parche:
|
|
49
49
|
=> [#<Date: 4909975/2,0,2299161>, #<Date: 4909977/2,0,2299161>, #<Date: 4909979/2,0,2299161>]
|
50
50
|
|
51
51
|
|
52
|
-
|
52
|
+
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_:
|
53
53
|
|
54
|
-
|
54
|
+
str = "1 de enero del 2009\nSede:El tercer lugar\n2 de enero del 2009\nSede:El tercer lugar"
|
55
|
+
Eventual.event_parse( str, :use_trailing => true ) do |dia, texto_extra|
|
56
|
+
[dia.to_s, texto_extra]
|
57
|
+
end
|
58
|
+
=> [["2009-01-01T00:00:00+00:00", "Sede:El tercer lugar"], ["2009-01-02T00:00:00+00:00", "Sede:El tercer lugar"]]
|
59
|
+
|
60
|
+
== TODO:
|
61
|
+
|
62
|
+
* No estoy seguro de que Iconv funcione en windows, lo arreglaré pronto
|
55
63
|
|
56
64
|
Formatos a reconocer
|
57
65
|
|
data/eventual.gemspec
CHANGED
data/lib/eventual.rb
CHANGED
@@ -1,60 +1,63 @@
|
|
1
1
|
require 'date'
|
2
2
|
require 'iconv'
|
3
|
+
require 'strscan'
|
3
4
|
|
4
5
|
$:.unshift(File.dirname(__FILE__)) unless $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
5
6
|
|
6
7
|
|
7
8
|
module Eventual
|
8
|
-
VERSION = '0.4.
|
9
|
+
VERSION = '0.4.5'
|
9
10
|
extend self
|
10
11
|
|
11
12
|
WDAY_LIST = %w(domingo lunes martes miercoles jueves viernes sabado)
|
12
13
|
MNAMES = %w(enero febrero marzo abril mayo junio julio agosto septiembre octubre noviembre diciembre).unshift(nil)
|
13
|
-
|
14
|
-
DAY_LIST = %r{
|
15
|
-
(
|
16
|
-
(?:\d{1,2}(?-mix: |, | y ))+ # Lista de número de día
|
17
|
-
)
|
18
|
-
de\s(#{ MNAMES.compact.join('|') }) # Lista de mes
|
19
|
-
(?-mix: (?:del|de) (\d{4}))? # Año opcional
|
20
|
-
(?-mix: a las (.*))? # Hora opcional
|
21
|
-
}ixo
|
22
14
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
15
|
+
year = /(?: (?:del|de))? (\d{4})/
|
16
|
+
horarios = / a las (.*)/
|
17
|
+
DAY_LIST = %r{
|
18
|
+
(
|
19
|
+
(?:
|
20
|
+
\d{1,2}
|
21
|
+
(?-mix: |, | y )
|
22
|
+
)+ # Lista de número de día
|
23
|
+
)
|
24
|
+
de\s(#{ MNAMES.compact.join('|') }) # Lista de mes
|
25
|
+
(?:#{ year })? # Año opcional
|
26
|
+
(#{ horarios })? # Hora opcional
|
27
|
+
}ixo
|
28
|
+
|
29
|
+
DAY_PERIOD = %r{
|
30
|
+
(
|
31
|
+
(?: # Dia de la semana opcional
|
32
|
+
(?:#{ WDAY_LIST.join('|') }) # Nombre del día
|
33
|
+
(?-mix: |, | y ) # Concatenador
|
34
|
+
)*
|
35
|
+
)
|
36
|
+
(?-mix:del (\d{1,2}))\s # Comienzo del periodo
|
37
|
+
(?:de\s # Mes opcional
|
38
|
+
(#{ MNAMES.compact.join('|') }) # Nombre del mes
|
39
|
+
(?:#{ year })? # Año opcional
|
40
|
+
\s)?
|
41
|
+
(?-mix:al (\d{1,2}) de (#{ MNAMES.compact.join('|') })) # Mes requerido
|
42
|
+
(?:#{ year })? # Año opcional
|
43
|
+
(#{ horarios })? # Hora opcional
|
44
|
+
}ixo
|
42
45
|
|
43
|
-
def event_parse string,
|
44
|
-
parser
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
46
|
+
def event_parse string, opts = {}, &block
|
47
|
+
parser = opts.delete(:parser) || (self == Eventual ? DateTime : self)
|
48
|
+
use_trailing = opts.delete(:use_trailing)
|
49
|
+
string = Iconv.iconv("ASCII//IGNORE//TRANSLIT", "UTF-8", string).join.gsub(/'/, '')
|
50
|
+
results = []
|
51
|
+
scanner = StringScanner.new string
|
49
52
|
|
50
|
-
|
51
|
-
case
|
53
|
+
until scanner.eos?
|
54
|
+
case match = scanner.scan(/.*?(?:#{DAY_LIST}|#{DAY_PERIOD})/m)
|
52
55
|
|
53
56
|
when DAY_PERIOD
|
54
57
|
wdays, first_day, first_month, first_year, last_day, last_month, last_year, times = $1, $2, $3, $4, $5, $6, $7, $8
|
55
58
|
match = $&
|
56
|
-
wdays = wdays.scan( Regexp.new(
|
57
|
-
last_year ||= string.match(/\d{4
|
59
|
+
wdays = wdays.scan( Regexp.new(WDAY_LIST.join('|')) ).collect{ |d| WDAY_LIST.index d }
|
60
|
+
last_year ||= string.match(/\d{4}/) ? $& : Date.today.year
|
58
61
|
first_year ||= last_year
|
59
62
|
first_month ||= last_month
|
60
63
|
last_month = MNAMES.index last_month
|
@@ -70,22 +73,20 @@ module Eventual
|
|
70
73
|
end
|
71
74
|
|
72
75
|
when DAY_LIST
|
73
|
-
days, month, year, times = $1, MNAMES.index(
|
76
|
+
days, month, year, times = $1, MNAMES.index($2), $3, $4
|
74
77
|
match = $&
|
75
78
|
days = days.scan(/\d{1,2}/)
|
76
|
-
year ||= string.match(/\d{4
|
79
|
+
year ||= string.match(/\d{4}/) ? $& : Date.today.year
|
77
80
|
make_days = lambda do |hour, minute|
|
78
81
|
days.map do |day|
|
79
82
|
make_day parser, year, month, day, hour, minute
|
80
83
|
end
|
81
84
|
end
|
82
|
-
|
83
85
|
else
|
84
86
|
break
|
85
87
|
end
|
86
|
-
|
87
|
-
string.gsub!( match.to_s, '' )
|
88
88
|
|
89
|
+
extra = scanner.scan(/.*?(?=#{DAY_LIST}|#{DAY_PERIOD}|\n{2}|\z)/m)
|
89
90
|
results +=
|
90
91
|
if times
|
91
92
|
times.scan( /(\d{2}):(\d{2})/ ).map do |hour, minute|
|
@@ -95,16 +96,21 @@ module Eventual
|
|
95
96
|
make_days.call nil, nil
|
96
97
|
end
|
97
98
|
end
|
98
|
-
|
99
|
+
|
100
|
+
raise ArgumentError.new( 'El formato de las fechas parece ser incorrecto' ) if results.empty?
|
99
101
|
results.uniq!
|
100
102
|
results.sort!
|
101
|
-
|
102
|
-
results.map!
|
103
|
+
|
104
|
+
results.map! do |day|
|
105
|
+
if use_trailing
|
106
|
+
yield day, extra.to_s.gsub(/^[\n|.|,]*/, '')
|
107
|
+
else
|
108
|
+
yield day
|
109
|
+
end
|
110
|
+
end if block_given?
|
103
111
|
|
104
112
|
results
|
105
113
|
end
|
106
|
-
|
107
|
-
|
108
114
|
|
109
115
|
protected
|
110
116
|
def make_day *args
|
@@ -115,6 +121,5 @@ module Eventual
|
|
115
121
|
maker.civil *args.compact.collect{ |a| a.to_i }
|
116
122
|
end
|
117
123
|
end
|
118
|
-
|
119
124
|
end
|
120
125
|
|
data/spec/es_eventual_spec.rb
CHANGED
@@ -61,7 +61,7 @@ describe 'event parsing' do
|
|
61
61
|
r = ( DateTime.parse('2008-1-1T16:00')..DateTime.parse('2008-12-31T16:00') ).reject{ |day| not [2,4].include?(day.wday) }
|
62
62
|
e.should map_times( *r )
|
63
63
|
end
|
64
|
-
|
64
|
+
|
65
65
|
it "should parse a long period" do
|
66
66
|
e = Eventual.event_parse( 'martes y jueves del 1 de enero del 2000 al 31 de diciembre del 2010' )
|
67
67
|
r = (DateTime.parse('2000-1-1T00:00')..DateTime.parse('2010-12-31T00:00') ).reject{ |day| not [2,4].include?(day.wday) }
|
@@ -84,7 +84,36 @@ describe 'event parsing' do
|
|
84
84
|
end
|
85
85
|
|
86
86
|
it "should event_parse period spanning more than one month" do
|
87
|
-
Eventual.event_parse( '1 de enero, del 29 de enero al 3 de febrero
|
87
|
+
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' )
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should event_parse a several dates separated by \\n" do |d, extra|
|
91
|
+
Eventual.event_parse( "1 de enero del 2009\n2 de enero del 2009" ) do |d|
|
92
|
+
d.to_s
|
93
|
+
end.should == ["2009-01-01T00:00:00+00:00", "2009-01-02T00:00:00+00:00"]
|
94
|
+
end
|
95
|
+
|
96
|
+
describe 'With extra data' do
|
97
|
+
it "should event_parse one day with one time" do
|
98
|
+
Eventual.event_parse( "1 de enero del 2009 a las 16:00 horas\nSede:El tercer lugar\nCupo: limitado", :use_trailing => true ) do |day, extra|
|
99
|
+
day.to_s.should == "2009-01-01T16:00:00+00:00"
|
100
|
+
extra.should == "Sede:El tercer lugar\nCupo: limitado"
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
it "should event_parse a period with block" do
|
105
|
+
Eventual.event_parse( "del 5 al 7 de junio 2009\nSede:El tercer lugar\nCupo: limitado", :use_trailing => true ) do |d, extra|
|
106
|
+
extra.should == "Sede:El tercer lugar\nCupo: limitado"
|
107
|
+
Eventual::WDAY_LIST[ d.wday ]
|
108
|
+
end.should == ['viernes', 'sabado', 'domingo']
|
109
|
+
end
|
110
|
+
|
111
|
+
it "should event_parse a several dates" do |d, extra|
|
112
|
+
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|
|
113
|
+
extra.should == "Sede:El tercer lugar\nCupo: limitado"
|
114
|
+
d.to_s
|
115
|
+
end.should == ["2009-01-01T00:00:00+00:00", "2009-01-02T00:00:00+00:00"]
|
116
|
+
end
|
88
117
|
end
|
89
118
|
|
90
119
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: maca-eventual
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Macario Ortega
|
@@ -47,6 +47,7 @@ files:
|
|
47
47
|
- eventual.gemspec
|
48
48
|
has_rdoc: true
|
49
49
|
homepage: http://github.com/maca/eventual
|
50
|
+
licenses:
|
50
51
|
post_install_message:
|
51
52
|
rdoc_options:
|
52
53
|
- --main
|
@@ -68,7 +69,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
68
69
|
requirements: []
|
69
70
|
|
70
71
|
rubyforge_project: eventual
|
71
|
-
rubygems_version: 1.
|
72
|
+
rubygems_version: 1.3.5
|
72
73
|
signing_key:
|
73
74
|
specification_version: 2
|
74
75
|
summary: ""
|