Woher wissen Sie, ob das heutige Datum in einem Datumsbereich liegt?


81

Ich habe ein Ereignis mit start_timeund end_timeund möchte überprüfen, ob das Ereignis "in Bearbeitung" ist. Das wäre zu prüfen, ob das heutige Datum im Bereich zwischen den beiden Daten liegt.

Wie würden Sie dies in einer Funktion tun?

Antworten:


61

Verwenden ===


Tatsächlich gibt es einen Operator, der dies erledigt. Erstellen Sie ein Rangeund vergleichen Sie TimeObjekte mit dem ===Operator.

start   = Time.now.to_i

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

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


Update Post-Kommentar-Flut: Diese Version funktioniert überall gut. (In Rails, in Ruby 1 und in Ruby 2.) Das vorherige irbBeispiel hat ebenfalls gut funktioniert, aber das interaktive Beispiel wurde in einigen Experimenten nicht immer korrekt wiedergegeben. Dieser ist einfacher auszuschneiden und einzufügen.

Es ist jetzt alles gerade.


1
Funktioniert nicht in Rails 3 unter Ruby 1.8.7, daher bevorzuge ich die Antwort von @heathd.
Sandro L

3
Getting TypeError: Kann nicht von Zeit zu Zeit in Ruby 2.0 iterieren
Pencilcheck

3
Was ist der Haken hier? Wie die beiden anderen Kommentare habe ich diesen Code genau ausprobiert und den gleichen Fehler erhalten. Warum haben 19 Personen diese Antwort gewählt? Hat es jemals funktioniert? Heathds Antwort funktioniert bei mir.
Ryan Sandridge

Funktioniert auch nicht bei mir. Vielleicht hat es in einer älteren Version funktioniert, scheint aber nicht mehr zu funktionieren.
Stuckj

2
Hinweis: Damit dies funktioniert, müssen Sie die Daten konvertieren .to_iund dann überprüfen ===, ob sie im Bereich liegen. IMO .coverage?ist eine bessere Lösung für Daten.
Fehler

244

In Ruby 1.9.2 ===funktioniert nicht, ich bekomme eine Fehlermeldung:

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

Verwenden Sie stattdessen #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

Das ist es, was ich an Ruby liebe. Sie entdecken immer eine andere großartige Methode, die den Job für Sie erledigt!
Daniel

Nett. Genau das, was ich brauchte. War sich der cover?Methode nicht bewusst
Ryan Rebo

1
Dies funktioniert mit Dateals auch(Date.yesterday..Date.tomorrow).cover?(Date.today) => true
Amit Patel

1
Ruby ist wunderschön! .. Danke!
Ele

===funktioniert gut in Ruby 1.9.2. Sie haben gerade vergessen.to_i
DigitalRoss

37

Wenn Sie Rails verwenden, können Sie verwenden TimeWithZone#between?. Sie hätten dann so etwas:

> 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

Da die Datumsklasse das Modul Vergleichbar enthält, verfügt jedes Datumsobjekt über eine between?Methode.

require 'date'

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

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

Unterrichtszeit auch.
Adass

Dies ist viel besser lesbar als die akzeptierte Antwort. +1 für die korrekte Nutzung der Kräfte von Ruby :)
Thutt

5

Wenn Sie Rails verwenden, können Sie Folgendes versuchen:

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 

Hinweis: Ich habe gerade verwendet beginning_of_dayund end_of_dayum eine einfache Reichweite bereitzustellen. Der wichtige Teil ist die include_with_range?Methode für einen Bereich.


Es sieht aus wie der Bereich # include_with_range? Die von ActiveSupport bereitgestellte Methode fügt einfach die Fähigkeitsprüfung hinzu, ob ein Bereich einen anderen Bereich enthält, indem #include? verwendet wird, zum Beispiel: (1..5) .include? (1..5). Davon abgesehen verhält es sich identisch mit Rubys nativem Include? Methode. Da Ihr Argument kein anderer Bereich ist, sollte diese ActiveSupport-Erweiterung keinen Unterschied machen. In jedem Fall sollten Sie einfach include aufrufen? und nicht include_with_range? seit include_with_range? ist einfach ein Alias ​​einzuschließen? (mit alias_method_chain).
Tyler Rick

a = DateTime.now; (a.beginning_of_day..a.end_of_day) .include_with_range? (a) gibt für mich false zurück (nicht true), als ich es in der Konsole in Rails 3.2.8 und ruby-1.9.3-p194 ausprobiert habe. (a.beginning_of_day..a.end_of_day) .cover? (a) gibt jedoch true zurück, daher verwende ich das stattdessen einfach.
Tyler Rick

ein gültiger Punkt. Ich bin mir nicht sicher, warum ich mich für die Verwendung entschieden habe, include_with_rangeda es kein Fall war, in dem ein Bereich mit einem Bereich verglichen wurde. Wahrscheinlich eine Art Gehirntumor. Guter Fang, danke @TylerRick. @ Heathd Antwort ist wirklich die beste.
Sorens

3

Wenn es sich um Zeitstempel handelt:

def in_progress?
  (start_time..end_time) .include? (Time.now)
Ende

Für mich am 1.9.2 gab dies einen FehlerTypeError: can't iterate from Time
Benjamin Oakes

3

Überprüft ist das aktuelle Datum zwischen zwei Daten. Verwenden von 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

Zusammenfassung

  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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.