Як дізнатися, чи є сьогоднішня дата в діапазоні дат?


81

У мене подія з start_timeі end_timeхочу перевірити, чи подія "триває". Це було б перевірити, чи є сьогоднішня дата в діапазоні між двома датами.

Як би ви зробили це у функції?

Відповіді:


61

Використовуйте ===


Власне, є оператор, який це зробить. Створіть a 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


Оновлення після коментарів-розливу: ця версія добре працює скрізь. (У Rails, у Ruby 1 та у Ruby 2.) Попередній irbприклад також працював нормально, але інтерактивний приклад не завжди відтворювався правильно в деяких експериментах. Цю легше вирізати і вставити.

Зараз це все виправлено.


1
Не працює в Rails 3 на Ruby 1.8.7, тому я віддаю перевагу відповіді @heathd.
Сандро Л

3
Отримання TypeError: Не вдається повторити час у ruby ​​2.0
Pencilcheck

3
У чому тут улов? Як і інші два коментарі, я спробував саме цей код і отримав ту ж помилку. Чому 19 людей проголосували за цю відповідь? Це колись працювало? відповідь Хітда працює для мене.
Райан Сандрідж,

Також не працює для мене. Можливо, це працювало в попередній версії, але, схоже, більше не існує.
stuckj

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
Рубі красива! .. Дякую!
Еле

===чудово працює в 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

18

Оскільки клас дати включає модуль Comparable, кожен об'єкт дати має between?метод.

require 'date'

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

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

Час занять також.
adass

Це спосіб більш читабельний, ніж прийнята відповідь. +1 за правильне використання повноважень Ruby :)
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?метод на діапазоні.


Схоже, діапазон # включає_з_діапазоном? Метод, наданий ActiveSupport, просто додає перевірку можливостей, чи включає один діапазон інший діапазон, використовуючи #include ?, наприклад: (1..5) .include? (1..5). Крім цього, він поводиться ідентично рідному включенню Рубі? метод. Оскільки ваш аргумент не є іншим діапазоном, це розширення ActiveSupport не повинно мати різниці. У будь-якому випадку вам слід просто зателефонувати включити? а не включати_з_діапазоном? оскільки include_with_range? просто псевдонім включити? (використовуючи псевдонім_методу_ланцюжка).
Тайлер Рік,

a = DateTime.now; (a.beginning_of_day..a.end_of_day) .include_with_range? (a) повертає false для мене (not true), коли я пробував це в консолі в 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

3

Якщо це мітки часу:

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

Для мене 1.9.2 це призвело до помилкиTypeError: can't iterate from Time
Бенджамін Оукс

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.