maca-eventual 0.4

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,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
+