Jak sprawdzić, czy dzisiejsza data należy do zakresu dat?


81

Mam wydarzenie z start_timei end_timechcę sprawdzić, czy wydarzenie jest w toku. Miałoby to na celu sprawdzenie, czy dzisiejsza data mieści się w przedziale między tymi dwiema datami.

Jak byś to zrobił w funkcji?

Odpowiedzi:


61

Posługiwać się ===


Właściwie istnieje operator, który to zrobi. Utwórz a Rangei porównaj Timez nim obiekty za pomocą ===operatora.

start   = Time.now.to_i

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

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


Aktualizacja post-comment-flood: Ta wersja działa dobrze wszędzie. (W Railsach, Ruby 1 i Ruby 2.) Wcześniejszy irbprzykład również działał dobrze, ale przykład interaktywny nie zawsze był poprawnie odtwarzany w niektórych eksperymentach. Ten jest łatwiejszy do wycinania i wklejania.

Teraz wszystko się wyjaśniło.


1
Nie działa w Rails 3 w Ruby 1.8.7, więc wolę odpowiedź @heathd.
Sandro L

3
Getting TypeError: Can't iterate from time in ruby ​​2.0
Pencilcheck

3
Jaki jest haczyk? Podobnie jak w przypadku pozostałych dwóch komentarzy, wypróbowałem dokładnie ten kod i otrzymałem ten sam błąd. Dlaczego 19 osób zagłosowało za tą odpowiedzią? Czy to kiedykolwiek działało? odpowiedź Heathda działa dla mnie.
Ryan Sandridge

U mnie też nie działa. Być może działało w starszej wersji, ale już się nie wydaje.
utknął

2
Uwaga: aby to zadziałało, musisz przekonwertować daty, .to_ia następnie użyć ich ===do sprawdzenia, czy mieszczą się w zakresie. IMO, .coverage?jest lepszym rozwiązaniem na randki.
błędny

246

W Ruby 1.9.2 ===nie działa, pojawia się błąd:

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

Zamiast tego użyj #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

To jest to, co kocham w Ruby, zawsze odkrywasz inną świetną metodę, która działa za Ciebie!
daniel

Miły. Dokładnie to, czego potrzebowałem. Był nieświadomy cover?metody
Ryan Rebo

1
Działa to Daterównież(Date.yesterday..Date.tomorrow).cover?(Date.today) => true
Amit Patel

1
Ruby jest piękna! .. Dzięki!
Ele

===działa dobrze w Rubim 1.9.2. Po prostu zapomniałeś.to_i
DigitalRoss

38

Jeśli używasz Railsów, możesz użyć TimeWithZone#between?. Miałbyś wtedy coś takiego:

> 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

Ponieważ klasa Date zawiera moduł Comparable, każdy obiekt Date posiada between?metodę.

require 'date'

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

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

Czas zajęć również.
adass

Jest to o wiele bardziej czytelne niż zaakceptowana odpowiedź. +1 za prawidłowe użycie mocy Ruby :)
mimo

5

Jeśli używasz Railsów, możesz spróbować tego:

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 

Uwaga: właśnie użyłem beginning_of_dayi end_of_dayaby zapewnić łatwy zakres. Ważną częścią jest include_with_range?metoda na Range.


Wygląda na to, że zakres # include_with_range? metoda udostępniona przez ActiveSupport po prostu dodaje możliwość sprawdzenia możliwości, czy jeden zakres obejmuje inny zakres za pomocą #include?, na przykład: (1..5) .include? (1..5). Poza tym zachowuje się identycznie jak natywne dołączenie Rubiego? metoda. Ponieważ Twój argument nie jest innym zakresem, to rozszerzenie ActiveSupport nie powinno mieć żadnego znaczenia. W każdym razie powinieneś po prostu zadzwonić do include? i nie include_with_range? ponieważ include_with_range? jest po prostu aliasem do uwzględnienia? (używając alias_method_chain).
Tyler Rick

a = DateTime.now; (a.beginning_of_day..a.end_of_day) .include_with_range? (a) zwraca dla mnie fałsz (nieprawda), gdy próbowałem to w konsoli w Railsach 3.2.8 i ruby-1.9.3-p194. (a.beginning_of_day..a.end_of_day) .cover? (a) zwraca prawdę, więc użyję tego zamiast tego.
Tyler Rick

ważny punkt. Nie jestem pewien, dlaczego zdecydowałem się użyć, include_with_rangeponieważ nie był to przypadek, w którym zakres był porównywany z zakresem. Prawdopodobnie jakiś rodzaj guza mózgu. Dobry chwyt, dzięki @TylerRick. Odpowiedź @heathd jest naprawdę najlepsza.
sorens

3

Jeśli są to sygnatury czasowe:

def in_progress?
  (czas_początkowy..czas_końcowy). uwzględniać? (Czas.now)
koniec

U mnie w 1.9.2 dało to błądTypeError: can't iterate from Time
Benjamin Oakes

3

Zaznaczona jest aktualna data pomiędzy dwoma datami. Korzystanie z Rubiego

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

Podsumowanie

  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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.