Zählen Sie die Anzahl der Tage zwischen zwei Daten


148

Wie zähle ich die Anzahl der Tage zwischen diesen beiden Daten?

start_date = Date.parse "2012-03-02 14:46:21 +0100"
end_date =  Date.parse "2012-04-02 14:46:21 +0200"

Antworten:


206

Mit den Klassen Date (und DateTime) können Sie (end_date - start_date).to_idie Differenz der Anzahl der Tage ermitteln.


5
@MichaelDurrant Sie machen eine ungerechtfertigte Annahme. Der Benutzer gibt nicht an, ob es sich um Zeichenfolgen handelt oder nicht. Da sie Rails verwenden, stammen die Daten höchstwahrscheinlich von ActiveRecord, wodurch sie automatisch in Datumsobjekte umgewandelt werden. Der angegebene Text ist ebenfalls identisch mit der Datumsobjektdarstellung, sodass es sehr wahrscheinlich ist, dass er aus einer nativen Quelle stammt.
Andrew France

84
Das gibt mir den Unterschied in Sekunden NICHT in Tagen mit Rails v3 / 4
2called-Chaos

6
Soweit ich das beurteilen kann, bleibt das Verhalten in allen neueren Versionen von Ruby und ActiveSupport gleich, einschließlich 2.0 bzw. 4.1.0. TimeObjekte geben jedoch Sekunden zurück.
Andrew France

5
Um die Antwort auf @ 2called-Chaos zu erweitern und die benötigten Tage (end_date - start_date) /1.day zu erhalten, erhalten Sie einen Float. Wenn Sie nur volle Tage haben möchten, können Sie ((end_date - start_date) /1.day) .ceil
David K.

2
@ David Abgesehen davon, dass sich der Kommentar von @ 2called-Chaos fälschlicherweise auf TimeObjekte bezieht , nicht auf DateObjekte. Vielleicht könnten Sie die Benennung in Ihrem Kommentar aktualisieren, um anzuzeigen, dass es sich nicht um Daten handelt?
Andrew France

108

Unter der Annahme , dass end_dateund start_datesind beide Klasse ActiveSupport::TimeWithZonein Rails, dann können Sie verwenden:

(end_date.to_date - start_date.to_date).to_i

1
Wenn es um Tabellenfelder geht, ist diese Antwort der richtige Weg. anstelle der am besten bewerteten hier.
Ben

Funktioniert nicht für (Time.zone.now.to_date - 23.hours.ago.to_date).to_i, es gibt 1 und sollte 0 sein
Yuri Ghensev

3
@YuriGhensev, es hängt davon ab, wann Sie Ihren Beispielcode ausführen. Beispielsweise wird derzeit Time.zone.now.to_date"Mi, 15. November 2017" und 23.hours.ago.to_date"Di, 14. November 2017" zurückgegeben. Der Unterschied in der Anzahl der Tage ist und sollte 1 sein, es sei denn, Sie haben Ihren Code in der Stunde vor Mitternacht ausgeführt.
Lee

35

Rails hat einige eingebaute Helfer , die dies für Sie lösen könnten. Beachten Sie, dass dies Teil der Actionview-Helfer ist und daher nicht direkt über die Konsole verfügbar ist.

Versuche dies

<% start_time =  "2012-03-02 14:46:21 +0100" %>
<% end_time   =  "2012-04-02 14:46:21 +0200" %>
<%= distance_of_time_in_words(start_time, end_time)  %>

 "about 1 month"

@ MaayanNaveh sollte es nicht sein, wenn Sie die tatsächliche Anzahl für Berechnungen benötigen.
Fedcomp

Diese Frage ist einer der Fälle, in denen die Frage selbst besser anders gestellt wird. Wenn Sie den anderen Antworten hier folgen, werden Sie auf Fälle stoßen, in denen manchmal Wochen oder Jahre anstelle von Tagen angezeigt werden sollen. Dies sollte wirklich als die "richtige" Antwort von Rails akzeptiert werden.
Dylan Pierce

34

Ich habe in Sekundenschnelle Ergebnisse erzielt, also hat das bei mir funktioniert:

(Time.now - self.created_at) / 86400

1
@Epigene 1.dayist nicht rubywie OP angefordert (in Tags). Es ist Railsnoch spezifischere active supportobwohl created_atist im Grunde ein ModelVerfahren in Railsso ..
Roko

26

um die Anzahl der Tage in einem Zeitbereich zu erhalten (nur eine Zählung aller Tage)

(start_date..end_date).count
(start_date..end_date).to_a.size
#=> 32

um die Anzahl der Tage zwischen 2 Daten zu erhalten

(start_date...end_date).count
(start_date...end_date).to_a.size
#=> 31

Danke dafür @ a14m! Hat mir eine Möglichkeit gegeben, inklusive und exklusive Datumsaufnahmen zu machen :)
Kris Boyd

18

Keine der vorherigen Antworten (bis zu diesem Datum) gibt den korrekten Unterschied in Tagen zwischen zwei Daten an.

Derjenige , der am nächsten kommt, ist von diesem Dankent . Eine vollständige Antwort würde konvertieren to_iund dann teilen:

(Time.now.to_i - 23.hours.ago.to_i) / 86400
>> 0

(Time.now.to_i - 25.hours.ago.to_i) / 86400
>> 1

(Time.now.to_i - 1.day.ago.to_i) / 86400
>> 1

Im konkreten Beispiel der Frage sollte nicht analysiert werden, Dateob die verstrichene Zeit relevant ist. Verwenden Sie Time.parsestattdessen.


Dies funktioniert möglicherweise nicht wie erwartet, wenn die Zeiten einen Sommerzeitübergang überschreiten, der sich vorwärts bewegt. In diesem Fall beträgt die DST-Übergangstaglänge zu Recht weniger als 24 Stunden, wird jedoch aufgrund der ganzzahligen Arithmetik an diesem Tag überhaupt nicht berücksichtigt.
PinnyM

4

So haben Sie die Anzahl der ganzen Tage zwischen zwei Daten ( DateTimeObjekten):

((end_at - start_at).to_f / 1.day).floor

Gleiches DST-Problem wie die Antwort, die Yuri gegeben hat. Arithmetik mit der Zeit ist nie so einfach wie erwartet :)
PinnyM

0

So ermitteln Sie die Anzahl der Tage zwischen zwei Daten:

(start.to_date...end.to_date).count - 1
or 
(end.to_date - start.to_date).to_i

-8
def business_days_between(date1, date2)
  business_days = 0
  date = date2
  while date > date1
   business_days = business_days + 1 unless date.saturday? or date.sunday?
   date = date - 1.day
  end
  business_days
end

3
viel einfacher, die Datumsobjekte zu subtrahieren.
OpenCoderX

Das OP hat nie nach Anpassungen für Werktage gefragt. Das ist sowieso wirklich verworren.
Nathan
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.