ruby on rails - rails - ¿Cómo puedo recorrer un rango de fecha con diferentes intervalos?
ruby on rails que es (4)
Bucle hasta la fecha más 1.day
, 1.week
o 1.month
es mayor que la fecha 1.month
.
> from = Time.now
=> 2012-05-12 09:21:24 -0400
> to = Time.now + 1.month + 2.week + 3.day
=> 2012-06-29 09:21:34 -0400
> tmp = from
=> 2012-05-12 09:21:24 -0400
> begin
?> tmp += 1.week
?> puts tmp
?> end while tmp <= to
2012-05-19 09:21:24 -0400
2012-05-26 09:21:24 -0400
2012-06-02 09:21:24 -0400
2012-06-09 09:21:24 -0400
2012-06-16 09:21:24 -0400
2012-06-23 09:21:24 -0400
2012-06-30 09:21:24 -0400
=> nil
Tengo un rango de fecha (de, a) que quiero repetir en un intervalo diferente (diario, semanal, mensual, ...)
¿Cómo puedo recorrer este intervalo de fechas?
Actualizar
Gracias por sus respuestas, se me ocurrió lo siguiente:
interval = ''week'' # month, year
start = from
while start < to
stop = start.send("end_of_#{interval}")
if stop > to
stop = to
end
logger.debug "Interval from #{start.inspect} to #{stop.inspect}"
start = stop.send("beginning_of_#{interval}")
start += 1.send(interval)
end
Esto recorrerá un intervalo de fechas con intervalos de semana, mes o año y respeta el comienzo y el final del intervalo dado.
Como no mencioné esto en mi pregunta, elegí la respuesta que me empujó en la dirección correcta.
Tienes el método de paso en el objeto Range. http://ruby-doc.org/core-1.9.3/Range.html#method-i-step
El método succ está en desuso en el rango 1.9. Queriendo hacer lo mismo por semana, llegué a esta solución:
def by_week(start_date, number_of_weeks)
number_of_weeks.times.inject([]) { |memo, w| memo << start_date + w.weeks }
end
Esto devuelve un conjunto de semanas en el intervalo. Fácilmente adaptable por meses.
En Ruby 1.9, agregué mi propio método en Range para recorrer los intervalos de tiempo:
class Range
def time_step(step, &block)
return enum_for(:time_step, step) unless block_given?
start_time, end_time = first, last
begin
yield(start_time)
end while (start_time += step) <= end_time
end
end
Entonces, puede llamar esto, por ejemplo (Mi ejemplo usa un método específico de Rails: 15.minutos):
irb(main):001:0> (1.hour.ago..Time.current).time_step(15.minutes) { |time| puts time }
2012-07-01 21:07:48 -0400
2012-07-01 21:22:48 -0400
2012-07-01 21:37:48 -0400
2012-07-01 21:52:48 -0400
2012-07-01 22:07:48 -0400
=> nil
irb(main):002:0> (1.hour.ago..Time.current).time_step(15.minutes).map { |time| time.to_s(:short) }
=> ["01 Jul 21:10", "01 Jul 21:25", "01 Jul 21:40", "01 Jul 21:55", "01 Jul 22:10"]
Tenga en cuenta que este método utiliza la convención de Ruby 1.9, donde los métodos de enumeración devuelven un enumerador si no se proporciona ningún bloque, lo que le permite encuestar a los enumeradores.
ACTUALIZAR
He agregado el método Range # time_step a mi "gema" core_extensions
personal . Si desea utilizar esto en su proyecto de Rails, simplemente agregue lo siguiente a su Gemfile:
gem ''core_extensions'', github: ''pdobb/core_extensions''