lib/eventual.rb in eventual-0.4.9 vs lib/eventual.rb in eventual-0.5.0
- old
+ new
@@ -1,193 +1,7 @@
+require 'rubygems'
+require 'treetop'
require 'date'
-require 'iconv'
-require 'strscan'
-module Eventual
- class WdayMatchError < StandardError; end
-
-
- VERSION = '0.4.9'
- extend self
+require "#{ File.dirname __FILE__ }/eventual/syntax_nodes"
- WDAY_LIST = %w(domingo lunes martes miércoles jueves viernes sábado).freeze
- MESES = %w(enero febrero marzo abril mayo junio julio agosto septiembre octubre noviembre diciembre).unshift(nil).freeze
- DIAS_DE_LA_SEMANA = WDAY_LIST.map{ |d| d.match(/s$/) ? d : "#{d}s?" }
-
- def rango_de a, b = nil
- a = a.join('|') if Array === a
- b ||= a
- /(?:de |del )?(?:#{ a }) (?:a|al) (?:#{ b })/
- end
-
- def lista_de elementos
- elementos = elementos.join('|') if Array === elementos
- /(?:#{ elementos }) # Primer elemento -requerido-
- (?: # Cualquier número de
- (?-x:, | y ) # concatenador
- (?:#{ elementos }) # y elemento.
- )*/ix
- end
-
- def plural_opcional elementos
- elementos.map{ |d| d.match(/s$/) ? d : "#{d}s?" }
- end
-
- year = /(?-x:del |de )?(\d{4})/i
- horarios = /a las (#{ lista_de '\d{1,2}:\d{2}' })(?: horas| hrs)?/i
-
-
- DAY_LIST = /
- (#{ lista_de %r"(?:(?:#{ DIAS_DE_LA_SEMANA.join('|') }) )?\d{1,2}" })\s
- de\s(#{ MESES.compact.join('|') }) # Mes
- (?:\s#{ year })? # Año opcional
- (\s#{ horarios })? # Hora opcional
- /ixo
-
- DAY_PERIOD = /
- (?:
- (
- (?:#{ rango_de DIAS_DE_LA_SEMANA })\s
- |
- (?:#{ lista_de DIAS_DE_LA_SEMANA })\s
- )
- (?-x:de |del )
- )?
- (?-x:(?:de |del )?(?:(#{ DIAS_DE_LA_SEMANA.join('|') }) )?(\d{1,2})(?: de (#{ MESES.compact.join('|') })(?: #{ year })?)?)
- (?-x: (?:a|al) (?:(#{ DIAS_DE_LA_SEMANA.join('|') }) )?(\d{1,2}) de (#{ MESES.compact.join('|') })(?: #{ year })?)
- (?:\s#{ horarios })?
- /ixo
-
- WHOLE_MONTH = /
- ( # Dias de la semana opcionales
- (?-x:los |todos los )?
- (?:
- (?:#{ rango_de DIAS_DE_LA_SEMANA })
- |
- (?:#{ lista_de DIAS_DE_LA_SEMANA })
- )\s
- (?-x:de|durante|durante todo)\s
- )?
- (?:
- (?:#{ rango_de %r"(#{ MESES.compact.join('|') })(?:\s#{ year })?" })
- |
- (#{ lista_de MESES.compact })(?:\s#{ year })?
- )
- (?:\s#{ horarios })? # Hora opcional
- /ixo
-
- def event_parse string, opts = {}, &block
- parser = opts.delete(:parser) || (self == Eventual ? DateTime : self)
- use_trailing = opts.delete(:use_trailing)
- string = string.gsub('miercoles', 'miércoles').gsub('sabado', 'sábado').gsub(/'/, '').gsub(/(\s)+/, '\1')
- results = []
- scanner = StringScanner.new string
-
- map_months = lambda{ |months| months.scan(/#{ MESES.compact.join('|') }/).map{ |m| MESES.index(m.downcase) } }
- make_range = lambda{ |first, last, min, max| first > last ? (first..max).map + (min..last).map : (first..last).map }
-
- extract_wdays = lambda do |wdays|
- wdays_array = wdays ? wdays.scan( /#{ WDAY_LIST.join('|') }/ ).map{ |d| WDAY_LIST.index d.downcase } : []
- next wdays_array unless rango_de(DIAS_DE_LA_SEMANA) === wdays
- make_range[wdays_array.first, wdays_array.last, 0, 6]
- end
-
- until scanner.eos?
- case match = scanner.scan(/.*?(?:#{ DAY_LIST }|#{ DAY_PERIOD }|#{ WHOLE_MONTH })/m)
-
- when DAY_PERIOD
- 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
-
- wdays_array = extract_wdays[wdays]
- last_year ||= string.match(/\d{4}/) ? $& : Date.today.year
- first_year ||= last_year
- first_month ||= last_month
- last_month = MESES.index last_month.downcase
- first_month = MESES.index first_month.downcase
-
- make_days = lambda do |hour, minute|
- first = make_day parser, first_year, first_month, first_day, hour, minute
- last = make_day parser, last_year, last_month, last_day, hour, minute
-
- [first, last].zip([first_wday, last_wday]).each do |day, wday|
- 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
- end
-
- next (first..last).map if wdays_array.empty?
- (first..last).select{ |day| wdays_array.include? day.wday }
- end
-
- when DAY_LIST
- daynums, month, year, times = $1, MESES.index($2.downcase), $3, $4
-
- year ||= string.match(/\d{4}/) ? $& : Date.today.year
- make_days = lambda do |hour, minute|
- daynums.scan(/(?:(#{ DIAS_DE_LA_SEMANA.join('|') }) )?(\d{1,2})/).collect do |wday, daynum|
- day = make_day(parser, year, month, daynum, hour, minute)
- 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
- day
- end
- end
-
- when WHOLE_MONTH
- wdays, month_range_start, starting_year, month_range_end, ending_year, months, year, times = $1, $2, $3, $4, $5, $6, $7, $8
- wdays_array = extract_wdays[wdays]
-
- month_array =
- if month_range_start
- ending_year ||= Date.today.year
- first = Date.civil( (starting_year || ending_year).to_i, MESES.index(month_range_start.downcase) )
- last = Date.civil ending_year.to_i, MESES.index(month_range_end.downcase)
- (first..last)
- else
- year ||= Date.today.year
- months.scan(/#{ MESES.compact.join('|') }/).map do |m|
- Date.civil year.to_i, MESES.index(m.downcase)
- end
- end
-
- make_days = lambda do |hour, minute|
- months = month_array.map do |date|
- first = make_day(parser, date.year, date.month, 1, hour, minute)
- last = (first >> 1) - 1
- next (first..last).map if wdays_array.empty?
- (first..last).select{ |day| wdays_array.include? day.wday }
- end.flatten
- end
-
- else
- break
- end
-
- extra = scanner.scan(/.*?(?=#{ DAY_LIST }|#{ DAY_PERIOD }|\z)/m).to_s.chomp
- extra.gsub!(/^(,|\n|\.)/, '')
-
- days =
- if times
- times.scan( /(\d{2}):(\d{2})/ ).map{ |hour, minute| make_days.call hour, minute }.flatten
- else
- make_days.call nil, nil
- end
-
- days.each { |day| day.instance_variable_set('@extra', extra) }
- results += days
- end
-
- raise ArgumentError.new( 'El formato de las fechas parece ser incorrecto' ) if results.empty?
- results.uniq!
- results.sort!
-
- use_trailing ? results.map!{ |day| yield day, day.instance_variable_get('@extra') } : results.map!{ |day| yield day } if block_given?
- results
- end
-
- protected
- def make_day *args
- maker = args.shift
- if maker == Date
- maker.civil *args.compact.collect{ |a| a.to_i }[0...4]
- else
- maker.civil *args.compact.collect{ |a| a.to_i }
- end
- end
-end
-
+autoload :EsDatesParser, 'eventual/es'
\ No newline at end of file