Contar o número de dias entre duas datas


149

Como posso contar o número de dias entre essas duas datas?

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

Respostas:


207

Com as classes Date (e DateTime), você pode fazer (end_date - start_date).to_ipara obter a diferença do número de dias.


5
@MichaelDurrant Você está fazendo uma suposição injustificada. O usuário não especifica se são cadeias ou não. De fato, como eles estão usando o Rails, é mais provável que as datas sejam provenientes do ActiveRecord, que as converterá automaticamente em objetos de data. O texto fornecido também é idêntico à representação do objeto Date, aumentando a probabilidade de ele ter vindo de uma fonte nativa.
Andrew France

84
Isso me dá a diferença em segundos, NÃO em dias com o Rails v3 / 4
2called-chaos

6
Tanto quanto posso dizer, o comportamento permanece o mesmo em todas as versões recentes do Ruby e ActiveSupport, incluindo 2.0 e 4.1.0, respectivamente. Timeobjetos retornam segundos embora.
Andrew France

5
para expandir a resposta @ 2called-caos, para obter os dias que você precisaria (end_date - start_date) /1.day, o que lhe proporcionaria uma flutuação. Se você queria ter dias cheios somente que você pode usar ((end_date - start_date) /1.day) .ceil
David K.

2
@ David Exceto que o comentário do @ 2called-caos se refere erroneamente a Timeobjetos, não a Dateobjetos. Talvez você possa atualizar o nome no seu comentário para refletir que não são datas?
Andrew France

109

Supondo que end_datee start_datesejam de classe ActiveSupport::TimeWithZoneno Rails, você pode usar:

(end_date.to_date - start_date.to_date).to_i

2
Se tiver a ver com os campos da tabela, esta resposta é o caminho a seguir; em vez do mais avaliado aqui.
Ben

Não funciona (Time.zone.now.to_date - 23.hours.ago.to_date).to_i, dá 1 e deve ser 0
Yuri Ghensev

3
@YuriGhensev, depende de quando você executa o código de exemplo, por exemplo, no momento, Time.zone.now.to_dateretorna "Qua, 15 de novembro de 2017", enquanto 23.hours.ago.to_dateretorna "Ter, 14 de novembro de 2017". A diferença no número de dias é e deve ser 1, a menos que você tenha executado seu código na hora anterior à meia-noite.
Lee15

35

O Rails tem alguns auxiliares integrados que podem resolver isso para você. Uma coisa a ter em mente é que isso faz parte dos Actionview Helpers, portanto eles não estarão disponíveis diretamente no console.

Tente isto

<% 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 não deve ser quando você precisar do número real para cálculos.
Fedcomp 18/03/19

Essa pergunta é um daqueles casos em que a pergunta em si é melhor feita de maneira diferente. Se você seguir as outras respostas aqui, encontrará casos em que, às vezes, deseja semanas ou anos, em vez de dias. Isso realmente deve ser aceito como a resposta "certa" do Rails.
Dylan Pierce

34

Eu continuava obtendo resultados em segundos, então isso funcionou para mim:

(Time.now - self.created_at) / 86400

1
@Epigene 1.daynão é o rubyOP solicitado (em tags). É Railsou mais específico active supportque created_até, basicamente, um Modelmétodo em Railstão ..
Roko

26

para obter o número de dias em um intervalo de tempo (apenas uma contagem de todos os dias)

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

para obter o número de dias entre 2 datas

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

Obrigado por este @ a14m! Deu-me uma maneira de fazer inclusivos e exclusivos capturas data :)
Kris Boyd

18

Nenhuma das respostas anteriores (até a presente data) fornece a diferença correta em dias entre duas datas.

O que mais se aproxima é por esse dankent . Uma resposta completa seria convertida to_ie depois dividida:

(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

No exemplo específico da pergunta, não se deve analisar Datese o tempo passado é relevante. Use em Time.parsevez disso.


Isso pode não funcionar conforme o esperado quando os horários atravessam uma transição de horário de verão. Nesse caso, a duração do dia de transição do horário de verão é legitimamente menor que 24 horas, mas devido à aritmética inteira desse dia não será refletida.
PinnyM

4

Para ter o número de dias inteiros entre duas datas ( DateTimeobjetos):

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

O mesmo problema de horário de verão que a resposta que Yuri deu. Aritmética com o tempo nunca é tão simples como seria de esperar :)
PinnyM

0

Para obter a diferença do número de dias em duas datas:

(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
muito mais fácil subtrair os objetos de data.
precisa

O OP nunca perguntou sobre o ajuste para dias úteis. Isso é realmente complicado de qualquer maneira.
Nathan
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.