Contare il numero di giorni tra due date


150

Come contare il numero di giorni tra queste due date?

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

Risposte:


208

Con le classi Date (e DateTime) puoi fare (end_date - start_date).to_iper ottenere la differenza del numero di giorni.


5
@MichaelDurrant Stai facendo un'ipotesi ingiustificata. L'utente non specifica se sono stringhe o meno. Infatti, poiché utilizzano Rails, è molto probabile che le date provengano da ActiveRecord, che le trasmetterà automaticamente agli oggetti della data. Il testo dato è identico anche alla rappresentazione dell'oggetto Date, il che rende molto probabile che provenga da una fonte nativa.
Andrew France,

84
Questo mi dà la differenza in secondi NON in giorni con rotaie v3 / 4
2called-caos

6
Per quanto ne so, il comportamento rimane lo stesso in tutte le versioni recenti di Ruby e ActiveSupport, includendo rispettivamente 2.0 e 4.1.0. Timegli oggetti restituiscono però dei secondi.
Andrew France,

5
per espandere la risposta @ 2called-caos, per ottenere giorni di cui avresti bisogno (end_date - start_date) /1.day, che ti darebbe un float. Se si desidera avere solo giorni interi, è possibile utilizzare ((end_date - start_date) /1.day) .ceil
David K.

2
@David Salvo che il commento di @ 2called-caos si riferisce erroneamente agli Timeoggetti, non agli Dateoggetti. Forse potresti aggiornare la denominazione nel tuo commento per riflettere che non sono date?
Andrew France,

109

Supponendo che end_datee start_datesono entrambi di classe ActiveSupport::TimeWithZonein Rails, allora si può usare:

(end_date.to_date - start_date.to_date).to_i

2
Se ha a che fare con i campi della tabella, questa risposta è la strada da percorrere; invece di quello più valutato proprio qui.
Ben

Non funziona (Time.zone.now.to_date - 23.hours.ago.to_date).to_i, dà 1 e dovrebbe essere 0
Yuri Ghensev

3
@YuriGhensev, dipende da quando si esegue il codice di esempio, ad esempio in questo momento Time.zone.now.to_daterestituisce "Mer, 15 nov 2017", mentre 23.hours.ago.to_daterestituisce "Mar, 14 nov 2017". La differenza nel numero di giorni è e dovrebbe essere 1 a meno che non sia stato eseguito il codice nell'ora prima di mezzanotte.
sottovento il

35

Rails ha alcuni helper integrati che potrebbero risolverlo per te. Una cosa da tenere a mente è che questo fa parte degli Helpview di Actionview, quindi non saranno disponibili direttamente dalla console.

Prova questo

<% 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 non dovrebbe essere quando è necessario il numero effettivo per i calcoli.
Fedcomp

Questa domanda è uno di quei casi in cui la domanda stessa è meglio posta in modo diverso. Se segui le altre risposte qui, ti imbatterai in casi in cui a volte vuoi che vengano mostrate settimane o anni anziché giorni. Questo dovrebbe davvero essere accettato come la risposta "giusta" di Rails.
Dylan Pierce,

34

Continuavo a ottenere risultati in pochi secondi, quindi questo ha funzionato per me:

(Time.now - self.created_at) / 86400

1
@Epigene 1.daynon è rubycome richiesto dall'OP (nei tag). È Railso più specifico active supportanche se in created_atpratica è un Modelmetodo in Railstal modo ...
Roko

26

per ottenere il numero di giorni in un intervallo di tempo (solo un conteggio di tutti i giorni)

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

per ottenere il numero di giorni tra 2 date

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

Grazie per questo @ a14m! Mi ha dato un modo per fare acquisizioni di date inclusive ed esclusive :)
Kris Boyd il

18

Nessuna delle risposte precedenti (a questa data) fornisce la differenza corretta in giorni tra due date.

Quello che si avvicina di più è quello che è umido . Una risposta completa verrebbe convertita to_ie quindi divisa:

(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

Nell'esempio specifico della domanda, non si dovrebbe analizzare Datese il tempo trascorso è rilevante. Usa Time.parseinvece.


Questo potrebbe non funzionare come previsto quando i tempi attraversano una transizione DST andando avanti. In questo caso, la durata del giorno di transizione dell'ora legale è legittimamente inferiore a 24 ore, ma a causa dell'aritmetica intera quel giorno non si rifletterà affatto.
PinnyM,

4

Per avere il numero di giorni interi tra due date ( DateTimeoggetti):

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

Stesso problema di ora legale della risposta che Yuri ha dato. L'aritmetica con il tempo non è mai così semplice come ti aspetteresti :)
PinnyM

0

Per ottenere il numero di giorni di differenza di due date:

(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
molto più facile sottrarre gli oggetti data.
OpenCoderX

L'OP non ha mai chiesto di adeguarsi ai giorni lavorativi. Questo è davvero contorto comunque.
Nathan,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.