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"
andkjaer
quelle

Antworten:

206

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

Andrew France
quelle
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
Lee
quelle
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"
Justin Herrick
quelle
@ 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
dasdankent
quelle
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
a14m
quelle
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.

Juri Ghensev
quelle
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
Dorian
quelle
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
giapnh
quelle
-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
Teja
quelle
3
viel einfacher, die Datumsobjekte zu subtrahieren.
OpenCoderX
Das OP hat nie nach Anpassungen für Werktage gefragt. Das ist sowieso wirklich verworren.
Nathan