maca-eventual 0.4

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt ADDED
@@ -0,0 +1,4 @@
1
+ == 0.0.1 2009-06-03
2
+
3
+ * 1 major enhancement:
4
+ * Initial release
data/Manifest.txt ADDED
@@ -0,0 +1,12 @@
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
12
+
data/README.rdoc ADDED
@@ -0,0 +1,91 @@
1
+ = eventual
2
+
3
+ * http://github.com/maca/eventual
4
+
5
+ == DESCRIPCIÓN:
6
+
7
+ Reconocimiento de fechas y periodos en lenguaje natural.
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
+ * martes y miércoles del 1 al 20 de junio del 2009 a las 16:00 y 18:00 horas
36
+
37
+ Se puede extender _Date_ y _DateTime_ con Eventual pero en principio no extienden Eventual.
38
+ Para activar el parche:
39
+
40
+ require 'rubygems'
41
+ require 'eventual'
42
+ require 'eventual/date_time'
43
+ require 'eventual/date'
44
+
45
+ DateTime.event_parse( 'del 5 al 7 de junio' )
46
+ => [#<DateTime: 4909975/2,0,2299161>, #<DateTime: 4909977/2,0,2299161>, #<DateTime: 4909979/2,0,2299161>]
47
+
48
+ Date.event_parse( 'del 5 al 7 de junio 2009' )
49
+ => [#<Date: 4909975/2,0,2299161>, #<Date: 4909977/2,0,2299161>, #<Date: 4909979/2,0,2299161>]
50
+
51
+
52
+ == ETC:
53
+
54
+ * No estoy seguro de que Iconv funcione en windows
55
+
56
+ Formatos a reconocer
57
+
58
+ * todos los lunes de junio
59
+ * domingos de septiembre
60
+ * martes y miércoles de agosto
61
+ * todo el año
62
+ * todo junio
63
+
64
+ == INSTALACIÓN:
65
+
66
+ sudo gem install maca-eventual -s http://gems.github.com
67
+
68
+ == LICENCIA:
69
+
70
+ (The MIT License)
71
+
72
+ Copyright (c) 2009 Macario Ortega
73
+
74
+ Permission is hereby granted, free of charge, to any person obtaining
75
+ a copy of this software and associated documentation files (the
76
+ 'Software'), to deal in the Software without restriction, including
77
+ without limitation the rights to use, copy, modify, merge, publish,
78
+ distribute, sublicense, and/or sell copies of the Software, and to
79
+ permit persons to whom the Software is furnished to do so, subject to
80
+ the following conditions:
81
+
82
+ The above copyright notice and this permission notice shall be
83
+ included in all copies or substantial portions of the Software.
84
+
85
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
86
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
87
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
88
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
89
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
90
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
91
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,21 @@
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
+ # Generate all the Rake tasks
6
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
7
+ $hoe = Hoe.new('eventual', Eventual::VERSION) do |p|
8
+ p.developer('Macario Ortega', 'macarui@gmail.com')
9
+ p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
10
+ p.rubyforge_name = p.name
11
+
12
+ p.clean_globs |= %w[**/.DS_Store tmp *.log]
13
+ # path = (p.rubyforge_name == p.name) ? p.rubyforge_name : "\#{p.rubyforge_name}/\#{p.name}"
14
+ # p.remote_rdoc_dir = File.join(path.gsub(/^#{p.rubyforge_name}\/?/,''), 'rdoc')
15
+ p.rsync_args = '-av --delete --ignore-errors'
16
+ end
17
+
18
+ require 'newgem/tasks' # load /tasks/*.rake
19
+ Dir['tasks/**/*.rake'].each { |t| load t }
20
+
21
+ task :default => :spec
@@ -0,0 +1 @@
1
+ Date.send( :extend, Eventual )
@@ -0,0 +1 @@
1
+ DateTime.send( :extend, Eventual )
data/lib/eventual.rb ADDED
@@ -0,0 +1,92 @@
1
+ require 'date'
2
+ require 'iconv'
3
+
4
+ $:.unshift(File.dirname(__FILE__)) unless $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
5
+
6
+
7
+ module Eventual
8
+ VERSION = '0.4'
9
+ extend self
10
+
11
+ WDAY_LIST = ["domingo", "lunes", "martes", "miercoles", "jueves", "viernes", "sabado"]
12
+ MNAMES = [nil, "enero", "febrero", "marzo", "abril", "mayo", "junio", "julio", "agosto", "septiembre", "octubre", "noviembre", "diciembre"]
13
+ OPT_YEAR = %r{(?:(?:(?:\s+(?:del|de)\s+)|\s+)(\d{4}))?}i
14
+ OPT_TIME24 = %r{(?:\s+a\s+las\s+(.*))?}i
15
+ LIST_SEPARATOR = %r{(?:\s+|,\s+|\s+y\s+)}i
16
+ OPT_WDAYS = %r{((?:(?:#{ WDAY_LIST.join('|') })#{ LIST_SEPARATOR })*)}i
17
+ DAY_LIST = %r{((?:\d{1,2}#{ LIST_SEPARATOR })+)de (#{ MNAMES.compact.join('|') })#{ OPT_YEAR }#{ OPT_TIME24 }}i
18
+ DAY_PERIOD = %r{#{ OPT_WDAYS }del\s+(\d{1,2})\s+(?:de\s+(#{ MNAMES.compact.join('|') })#{ OPT_YEAR }\s+)?al\s+(\d{1,2})\s+de\s+(#{ MNAMES.compact.join('|') })#{ OPT_YEAR }#{ OPT_TIME24 }}i
19
+
20
+ def event_parse string, parser = nil, &block
21
+ parser ||= ( self == Eventual ? DateTime : self )
22
+ string = Iconv.iconv("ASCII//IGNORE//TRANSLIT", "UTF-8", string).join.gsub(/'/, '')
23
+ results = []
24
+
25
+ string = string
26
+
27
+ while true
28
+ case string
29
+
30
+ when DAY_PERIOD
31
+ wdays, first_day, first_month, first_year, last_day, last_month, last_year, times = $1, $2, $3, $4, $5, $6, $7, $8
32
+ match = $&
33
+ wdays = wdays.scan( Regexp.new( WDAY_LIST.join('|') ) ).collect{ |d| WDAY_LIST.index d }
34
+ last_year ||= string.match(/\d{4,4}/) ? $& : Date.today.year
35
+ first_year ||= last_year
36
+ first_month ||= last_month
37
+ last_month = MNAMES.index last_month
38
+ first_month = MNAMES.index first_month
39
+ make_days = lambda do |hour, minute|
40
+ first = make_day parser, first_year, first_month, first_day, hour, minute
41
+ last = make_day parser, last_year, last_month, last_day, hour, minute
42
+ if wdays.empty?
43
+ (first..last).map
44
+ else
45
+ (first..last).select{ |day| wdays.include? day.wday }
46
+ end
47
+ end
48
+
49
+ when DAY_LIST
50
+ days, month, year, times = $1, MNAMES.index( $2 ), $3, $4
51
+ match = $&
52
+ days = days.scan(/\d{1,2}/)
53
+ year ||= string.match(/\d{4,4}/) ? $& : Date.today.year
54
+ make_days = lambda do |hour, minute|
55
+ days.map do |day|
56
+ make_day parser, year, month, day, hour, minute
57
+ end
58
+ end
59
+
60
+ else
61
+ break
62
+ end
63
+
64
+ string.gsub!( match.to_s, '' )
65
+
66
+ results +=
67
+ if times
68
+ times.scan( /(\d{2}):(\d{2})/ ).map do |hour, minute|
69
+ make_days.call hour, minute
70
+ end.flatten
71
+ else
72
+ make_days.call nil, nil
73
+ end
74
+ end
75
+
76
+ results.uniq!
77
+ results.sort!
78
+ raise ArgumentError.new( 'El formato de las fechas parece ser incorrecto' ) if results.empty?
79
+ results.map!{ |day| yield( day ) } if block_given?
80
+
81
+ results
82
+ end
83
+
84
+
85
+
86
+ protected
87
+ def make_day *args
88
+ args.shift.civil *args.compact.collect{ |a| a.to_i }
89
+ end
90
+
91
+ end
92
+
@@ -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' ).should map_times( '2009-1-1' )
9
+ end
10
+
11
+ it 'should monkey patch Date' do
12
+ Date.event_parse( '1 de enero del 2009' ).should map_dates( '2009-1-1' )
13
+ end
14
+ end
15
+
@@ -0,0 +1,91 @@
1
+ require File.expand_path( File.dirname(__FILE__) + '/spec_helper' )
2
+
3
+ describe 'event parsing' do
4
+
5
+ it "should event_parse one day" do
6
+ Eventual.event_parse( '1 de enero del 2009' ).should map_times( '2009-1-1' )
7
+ end
8
+
9
+ it "should event_parse several days" do
10
+ Eventual.event_parse( '1, 2 y 3 de enero' ).should map_times( "2009-1-1", "2009-1-2", "2009-1-3" )
11
+ end
12
+
13
+ it "should match several days with year" do
14
+ Eventual.event_parse( '1, 2 y 3 de enero del 2010' ).should map_times( "2010-1-1", "2010-1-2", "2010-1-3" )
15
+ end
16
+
17
+ it "should match several days with year" do
18
+ Eventual.event_parse( '1, 2 y 3 de enero del 2010' ).should map_times( "2010-1-1", "2010-1-2", "2010-1-3" )
19
+ end
20
+
21
+ it "should event_parse one day with one time" do
22
+ Eventual.event_parse( '1 de enero del 2009 a las 16:00 horas' ).should map_times( '2009-1-1T16:00' )
23
+ end
24
+
25
+ it "should event_parse a period" do
26
+ Eventual.event_parse( 'del 1 al 3 de enero' ).should map_times( '2009-1-1', '2009-1-2', '2009-1-3' )
27
+ end
28
+
29
+ it "should event_parse a period with year" do
30
+ Eventual.event_parse( 'del 1 al 3 de enero 2010' ).should map_times( '2010-1-1', '2010-1-2', '2010-1-3' )
31
+ end
32
+
33
+ it "should event_parse a period with time" do
34
+ Eventual.event_parse( 'miércoles del 1 al 3 de junio' ).should map_times( '2009-6-3' )
35
+ end
36
+
37
+ it "should event_parse a period with time" do
38
+ Eventual.event_parse( 'miércoles del 1 al 3 de junio a las 16:00 horas' ).should map_times( '2009-6-3T16:00' )
39
+ end
40
+
41
+ it "should event_parse one day with several times" do
42
+ 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' )
43
+ end
44
+
45
+ it "should event_parse period spanning more than one month" do
46
+ 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' )
47
+ end
48
+
49
+ it "should parse period spanning across year" do
50
+ 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')
51
+ end
52
+
53
+ it "should parse all tuesdays and thursdays of the year" do
54
+ e = Eventual.event_parse( 'martes y jueves del 1 de enero al 30 de diciembre del 2008')
55
+ r = ( DateTime.parse('2008-1-1')..DateTime.parse('2008-12-31') ).reject{ |day| not [2,4].include?(day.wday) }
56
+ e.should map_times( *r )
57
+ end
58
+
59
+ it "should parse all tuesdays and thursdays of the year with time" do
60
+ e = Eventual.event_parse( 'martes y jueves del 1 de enero al 30 de diciembre del 2008 a las 16:00')
61
+ r = ( DateTime.parse('2008-1-1T16:00')..DateTime.parse('2008-12-31T16:00') ).reject{ |day| not [2,4].include?(day.wday) }
62
+ e.should map_times( *r )
63
+ end
64
+
65
+ it "should parse a long period" do
66
+ e = Eventual.event_parse( 'martes y jueves del 1 de enero del 2000 al 31 de diciembre del 2010' )
67
+ r = (DateTime.parse('2000-1-1T00:00')..DateTime.parse('2010-12-31T00:00') ).reject{ |day| not [2,4].include?(day.wday) }
68
+ e.should map_times( *r )
69
+ end
70
+
71
+ it "should parse a long period with multiple times" do
72
+ e = Eventual.event_parse( 'martes y jueves del 1 de enero del 2000 al 31 de diciembre del 2010 a las 16:00 y 18:00 horas' )
73
+ r = (DateTime.parse('2000-1-1T16:00')...DateTime.parse('2010-12-31T16:00') ).reject{ |day| not [2,4].include?(day.wday) } +
74
+ (DateTime.parse('2000-1-1T18:00')...DateTime.parse('2010-12-31T18:00') ).reject{ |day| not [2,4].include?(day.wday) }
75
+ e.should map_times( *r.sort )
76
+ end
77
+
78
+ it "should event_parse a period with block" do
79
+ Eventual.event_parse( 'del 5 al 7 de junio 2009' ){ |d| Eventual::WDAY_LIST[ d.wday ] }.should == ['viernes', 'sabado', 'domingo']
80
+ end
81
+
82
+ it "should parse several expressions" do
83
+ Eventual.event_parse( '1 de enero y 2 de febrero del 2008' ).should map_times( '2008-1-1', '2008-2-2' )
84
+ end
85
+
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, 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
+ end
91
+
@@ -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,75 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: maca-eventual
3
+ version: !ruby/object:Gem::Version
4
+ version: "0.4"
5
+ platform: ruby
6
+ authors:
7
+ - Macario Ortega
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain:
11
+ - /Users/sistemasinteractivos/.gem/gem-public_cert.pem
12
+ date: 2009-06-05 00:00:00 -07: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
+ has_rdoc: true
48
+ homepage: http://github.com/maca/eventual
49
+ post_install_message:
50
+ rdoc_options:
51
+ - --main
52
+ - README.rdoc
53
+ require_paths:
54
+ - lib
55
+ required_ruby_version: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: "0"
60
+ version:
61
+ required_rubygems_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: "0"
66
+ version:
67
+ requirements: []
68
+
69
+ rubyforge_project: eventual
70
+ rubygems_version: 1.2.0
71
+ signing_key:
72
+ specification_version: 2
73
+ summary: ""
74
+ test_files: []
75
+