Как узнать, находится ли сегодняшняя дата в диапазоне дат?


81

У меня есть событие с start_timeи end_timeи хочу проверить , если событие «в процессе». Это было бы для проверки того, находится ли сегодняшняя дата в диапазоне между двумя датами.

Как бы вы это сделали в функции?

Ответы:


61

Использовать ===


Собственно, есть оператор, который этим займется. Создайте объект Rangeи сравните Timeс ним объекты с помощью ===оператора.

start   = Time.now.to_i

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

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


Обновление post-comment-flood: эта версия хорошо работает везде. (В Rails, в Ruby 1 и в Ruby 2.) Предыдущий irbпример также работал нормально, но интерактивный пример не всегда воспроизводился правильно в некоторых экспериментах. Его легче вырезать и вставить.

Теперь все наладилось.


1
Не работает в Rails 3 на Ruby 1.8.7, поэтому я предпочитаю ответ @heathd.
Sandro L

3
Получение TypeError: невозможно
выполнить

3
В чем тут загвоздка? Как и два других комментария, я точно попробовал этот код и получил ту же ошибку. Почему за этот ответ проголосовали 19 человек? Это когда-нибудь работало? Ответ Хитда действительно работает для меня.
Райан Сэндридж

У меня тоже не работает. Возможно, это работало в более старой версии, но больше не работает.
stuckj 01

2
Примечание: чтобы это сработало, вам нужно преобразовать даты, .to_iа затем использовать их, ===чтобы увидеть, находятся ли они в диапазоне. ИМО, .coverage?это лучшее решение для дат.
ошибочный

246

В Ruby 1.9.2 ===не работает, выдает ошибку:

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>'

Вместо этого используйте #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

Это то, что мне нравится в рубине: вы всегда открываете для себя еще один отличный метод, который сделает работу за вас!
Дэниел

Ницца. Как раз то, что мне было нужно. Не знал о cover?методе
Райан Ребо

1
Это работает с Dateа(Date.yesterday..Date.tomorrow).cover?(Date.today) => true
Amit Patel

1
Руби прекрасна! .. Спасибо!
Ele

===отлично работает в Ruby 1.9.2. Вы просто забыли.to_i
DigitalRoss

38

Если вы используете Rails, вы можете использовать TimeWithZone#between?. Тогда у вас будет что-то вроде этого:

> 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

Поскольку класс даты включает модуль Comparable, каждый объект даты имеет between?метод.

require 'date'

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

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

Классное время тоже.
adass 07

Это более читабельно, чем принятый ответ. +1 за правильное использование способностей Руби :)
thutt

5

Если вы используете Rails, вы можете попробовать следующее:

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 

Примечание: я просто использовал beginning_of_dayи, end_of_dayчтобы указать легкий диапазон. Важной частью является include_with_range?метод Range.


Похоже, что Range # include_with_range? Метод, предоставляемый ActiveSupport, просто добавляет проверку способности, включает ли один диапазон другой диапазон, используя #include?, например: (1..5) .include? (1..5). В остальном он ведет себя идентично встроенному в Ruby include? метод. Поскольку ваш аргумент не является другим диапазоном, это расширение ActiveSupport не должно иметь значения. В любом случае вам следует просто вызвать include? а не include_with_range? так как include_with_range? это просто псевдоним для включения? (с использованием alias_method_chain).
Тайлер Рик

a = DateTime.now; (a.beginning_of_day..a.end_of_day) .include_with_range? (a) возвращает false для меня (неверно), когда я пробовал его в консоли в Rails 3.2.8 и ruby-1.9.3-p194. (a.beginning_of_day..a.end_of_day) .cover? (a), однако, возвращает true, поэтому я просто воспользуюсь этим.
Тайлер Рик

действительный момент. Не уверен, почему я решил использовать, include_with_rangeпоскольку это не тот случай, когда диапазон сравнивался с диапазоном. Наверное, какая-то опухоль мозга. Хороший улов, спасибо @TylerRick. Ответ @heathd действительно лучший.
sorens 04

3

Если это временные метки:

def in_progress?
  (start_time..end_time) .include? (Time.now)
конец

У меня на 1.9.2 это выдало ошибкуTypeError: can't iterate from Time
Benjamin Oakes

3

Проверяется текущая дата между двумя датами. Использование 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

3

резюме

  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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.