¿Cómo saber si la fecha de hoy está dentro de un rango de fechas?


81

Tengo un evento con start_timey end_timequiero comprobar si el evento está "en curso". Eso sería verificar si la fecha de hoy está en el rango entre las dos fechas.

¿Cómo harías esto en una función?

Respuestas:


61

Utilizar ===


De hecho, hay un operador que hará esto. Haga un Rangey compare Timeobjetos con él usando el ===operador.

start   = Time.now.to_i

range   = start..(start + 2)
inside  = start + 1
outside = start + 3        # ok, now...

range === inside  # true
range === outside # false


Actualizar post-comment-flood: esta versión funciona bien en todas partes. (En Rails, en Ruby 1 y en Ruby 2.) El irbejemplo anterior también funcionó bien, pero el ejemplo interactivo no siempre se reprodujo correctamente en algunos experimentos. Éste es más fácil de cortar y pegar.

Todo está arreglado ahora.


1
No funciona en Rails 3 en Ruby 1.8.7, así que prefiero la respuesta @heathd.
Sandro L

3
Obteniendo TypeError: No se puede iterar desde el tiempo en ruby ​​2.0
Pencilcheck

3
¿Cuál es el truco aquí? Al igual que los otros dos comentarios, probé este código exactamente y obtuve el mismo error. ¿Por qué 19 personas votaron a favor de esta respuesta? ¿Alguna vez funcionó? la respuesta de heathd funciona para mí.
Ryan Sandridge

Tampoco funciona para mí. Quizás funcionó en una versión anterior, pero parece que ya no.
pegadoj

2
Nota: para que esto funcione, debe convertir las fechas .to_iy luego usarlas ===para ver si están en el rango. En mi opinión, .coverage?es una mejor solución para las fechas.
erroric

246

En Ruby 1.9.2 ===no funciona, aparece un error:

irb(main):019:0> (Time.now .. (Time.now+1)) === Time.now
TypeError: can't iterate from Time
    from (irb):19:in `each'
    from (irb):19:in `include?'
    from (irb):19:in `include?'
    from (irb):19:in `==='
    from (irb):19
    from /opt/ruby192/bin/irb:12:in `<main>'

En su lugar use #cover?:

irb(main):002:0> (Time.now..Time.now+4).cover?(Time.now)
=> true
irb(main):003:0> (Time.now..Time.now+4).cover?(Time.now+10)
=> false

Esto es lo que me encanta de ruby, ¡siempre descubres otro gran método que hace el trabajo por ti!
Daniel

Agradable. Justo lo que necesitaba. No conocía el cover?método
Ryan Rebo

1
Esto funciona con Dateasí(Date.yesterday..Date.tomorrow).cover?(Date.today) => true
Amit Patel

1
¡Ruby es hermosa! .. ¡Gracias!
Ele

===funciona bien en Ruby 1.9.2. Acabas de olvidar el.to_i
DigitalRoss

37

Si está usando Rails, puede usar TimeWithZone#between?. Entonces tendrías algo como esto:

> start_time = Time.zone.parse('12pm')      => Thu, 26 Jul 2012 12:00:00 EDT -04:00
> end_time = start_time + 1.hour            => Thu, 26 Jul 2012 13:00:00 EDT -04:00
> inside = Time.zone.parse('12:30pm')       => Thu, 26 Jul 2012 12:30:00 EDT -04:00
> outside = Time.zone.parse('1:30pm')       => Thu, 26 Jul 2012 13:30:00 EDT -04:00
> inside.between?(start_time, end_time)     => true
> outside.between?(start_time, end_time)    => false

17

Dado que la clase de fecha incluye el módulo Comparable, cada objeto de fecha tiene un between?método.

require 'date'

today           = Date.today
tomorrow        = today + 1
one_month_later = today >> 1

tomorrow.between?(today, one_month_later) # => true

Tiempo de clase también.
adass

Esto es mucho más legible que la respuesta aceptada. +1 por usar los poderes de Ruby correctamente :)
thutt

5

Si está utilizando Rails, puede intentar esto:

ruby-1.8.7-p299 :015 > a = DateTime.now
 => Fri, 02 Dec 2011 11:04:24 -0800 
ruby-1.8.7-p299 :016 > (a.beginning_of_day..a.end_of_day).include_with_range? a
 => true 
ruby-1.8.7-p299 :017 > (a.beginning_of_day..a.end_of_day).include_with_range? a+10.days
 => false 
ruby-1.8.7-p299 :018 > (a.beginning_of_day..a.end_of_day).include_with_range? a+25.hours
 => false 
ruby-1.8.7-p299 :019 > (a.beginning_of_day..a.end_of_day).include_with_range? a+2.hours
 => true 

Nota: Acabo de usar beginning_of_dayy end_of_daypara proporcionar un rango fácil. La parte importante es el include_with_range?método en un rango.


Parece que el rango # include_with_range? El método proporcionado por ActiveSupport simplemente agrega la verificación de capacidad si un rango incluye otro rango usando #include ?, por ejemplo: (1..5) .include? (1..5). Aparte de eso, se comporta de manera idéntica a la inclusión nativa de Ruby? método. Dado que su argumento no es otro rango, esta extensión de ActiveSupport no debería hacer ninguna diferencia. En cualquier caso, simplemente debería llamar a include? y no include_with_range? desde include_with_range? es simplemente un alias para incluir? (usando alias_method_chain).
Tyler Rick

a = DateTime.now; (a.beginning_of_day..a.end_of_day) .include_with_range? (a) devuelve falso para mí (no verdadero) cuando lo probé en la consola en Rails 3.2.8 y ruby-1.9.3-p194. (a.beginning_of_day..a.end_of_day) .cover? (a) devuelve verdadero, así que lo usaré en su lugar.
Tyler Rick

un punto válido. No estoy seguro de por qué opté por usarlo, include_with_rangeya que no era un caso en el que se comparara un rango con un rango. Probablemente algún tipo de tumor cerebral. Buen partido, gracias @TylerRick. La respuesta de @heathd es realmente la mejor.
llagas

3

Si son marcas de tiempo:

def in_progress?
  (hora_inicio..hora_final) .incluir? (Hora.hora)
fin

Para mí en 1.9.2, esto dio un errorTypeError: can't iterate from Time
Benjamin Oakes

3

Se marca la fecha actual entre dos fechas. Usando Ruby

currentDate = DateTime.now
start_date = "2017-03-31"
end_date = "2018-03-31"
currentDate.between?(start_date, end_date)

**Out Put Will be** true or false

2

resumen

  d1      = DateTime.parse('2018/04/01')
  d2      = DateTime.parse('2018/04/29')
  outside = DateTime.parse('2018/04/30')
  inside  = DateTime.parse('2018/04/15')

  # include?
  (d1...d2).include?(d1)      # true
  (d1...d2).include?(d2)      # false
  (d1...d2).include?(outside) # false
  (d1...d2).include?(inside)  # true

  (d1..d2).include?(d1)      # true
  (d1..d2).include?(d2)      # true
  (d1..d2).include?(outside) # false
  (d1..d2).include?(inside)  # true

  # ===
  (d1...d2) === d1      # true
  (d1...d2) === d2      # false
  (d1...d2) === outside # false
  (d1...d2) === inside  # true

  (d1..d2) === d1      # true
  (d1..d2) === d2      # true
  (d1..d2) === outside # false
  (d1..d2) === inside  # true

  # cover?
  (d1...d2).cover?(d1)      # true
  (d1...d2).cover?(d2)      # false
  (d1...d2).cover?(outside) # false
  (d1...d2).cover?(inside)  # true

  (d1..d2).cover?(d1)      # true
  (d1..d2).cover?(d2)      # true
  (d1..d2).cover?(outside) # false
  (d1..d2).cover?(inside)  # true

  # between?
  d1.between?(d1, d2)       # true
  d2.between?(d1, d2)       # true
  outside.between?(d1, d2)  # false
  inside.between?(d1, d2)   # true
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.