Como posso encontrar o número de dias entre dois objetos Date no Ruby?


141

Como posso encontrar o número de dias entre dois objetos Date?

Respostas:


170

Subtraia a data de início da data de término:

endDate - beginDate 

2
acho que você quer dizer subtrair a data de início a partir da data de término :)
Nader

99
tipo de anticlímax eh?
Brig

18
nota: se você estiver usando Wirble no irb (para colorir a saída), o número racional terá 1 concatenado até o final. caramba! você pode usar to_i para converter o resultado em um número inteiro
jwal

9
Se você tiver um DateTimeobjeto, certifique-se de converter para o Dateprimeiro; caso contrário, ele retornará o número de segundos (eu acho).
Joshua Muheim

44
Observe também subtraindo dois Dateobjetos lhe dá uma Rationalque você pode precisar de typecast em um número inteiro, como com(endDate - beginDate).to_i
MusikAnimal

98
irb(main):005:0> a = Date.parse("12/1/2010")
=> #<Date: 4911063/2,0,2299161>

irb(main):007:0> b = Date.parse("12/21/2010")
=> #<Date: 4911103/2,0,2299161>

irb(main):016:0> c = b.mjd - a.mjd
=> 20

Isso usa um número de dia juliano modificado .

Da wikipedia :

A data juliana (JD) é o intervalo de tempo em dias e frações de um dia desde 1º de janeiro de 4713 aC Greenwich ao meio-dia, calendário pré-séptico juliano.


53

Isso pode ter mudado no Ruby 2.0

Quando faço isso, recebo uma fração. Por exemplo, no console (irb ou rails c)

2.0.0-p195 :005 > require 'date'
 => true 
2.0.0-p195 :006 >  a_date = Date.parse("25/12/2013")
 => #<Date: 2013-12-25 ((2456652j,0s,0n),+0s,2299161j)> 
2.0.0-p195 :007 >  b_date = Date.parse("10/12/2013")
 => #<Date: 2013-12-10 ((2456637j,0s,0n),+0s,2299161j)> 
2.0.0-p195 :008 > a_date-b_date
 => (15/1) 

Obviamente, converter para um int fornece o resultado esperado

2.0.0-p195 :009 > (a_date-b_date).to_i
 => 15 

Isso também funciona para objetos DateTime, mas você deve levar em consideração segundos, como este exemplo

2.0.0-p195 :017 >   a_date_time = DateTime.now
 => #<DateTime: 2013-12-31T12:23:03-08:00 ((2456658j,73383s,725757000n),-28800s,2299161j)> 
2.0.0-p195 :018 > b_date_time = DateTime.now-20
 => #<DateTime: 2013-12-11T12:23:06-08:00 ((2456638j,73386s,69998000n),-28800s,2299161j)> 
2.0.0-p195 :019 > a_date_time - b_date_time
 => (1727997655759/86400000000) 
2.0.0-p195 :020 > (a_date_time - b_date_time).to_i
 => 19 
2.0.0-p195 :021 > c_date_time = a_date_time-20
 => #<DateTime: 2013-12-11T12:23:03-08:00 ((2456638j,73383s,725757000n),-28800s,2299161j)> 
2.0.0-p195 :022 > a_date_time - c_date_time
 => (20/1) 
2.0.0-p195 :023 > (a_date_time - c_date_time).to_i
 => 20 

29

No Ruby 2.1.3, as coisas mudaram:

> endDate = Date.new(2014, 1, 2)
 => #<Date: 2014-01-02 ((2456660j,0s,0n),+0s,2299161j)> 
> beginDate = Date.new(2014, 1, 1)
 => #<Date: 2014-01-01 ((2456659j,0s,0n),+0s,2299161j)> 
> days = endDate - beginDate
 => (1/1) 
> days.class
 => Rational 
> days.to_i
 => 1 

21

Que tal agora?

(beginDate...endDate).count

O intervalo é um conjunto de seriados exclusivos. E ...é um literal exclusivo Range.

Então beginDate..(endDate - 1)é o mesmo. Exceto que não é.

No caso em que beginDate for igual a endDate , o primeiro elemento será excluído devido à exclusividade e ...o último. Portanto, se queremos .countdatas entre hoje e hoje, retornará 0.


Essa é uma resposta muito boa, se o beginDate for mais antigo que o endDate, ele retornará 0, o que funcionará perfeitamente em alguns casos. Além disso, se as duas datas forem iguais, ele retornará 0. Ele também retornará um número inteiro simples. Outras respostas precisam ser transformadas em números inteiros ou talvez você precise traduzir para 0 se o resultado for negativo.
EmmanuelB

8

Isso funcionou para mim:

(endDate - beginDate).to_i


6

tudo isso me levou ao resultado correto, mas acabei fazendo

DateTime.now.mjd - DateTime.parse("01-01-1995").mjd

Um detalhe a destacar: DateTime.parse no Ruby espera que a data seja dada como DD / MM / AAAA ou DD-MM-AAAA. Como americano, isso sempre me impressiona!
Rickumali #

15
@rickumali Como membro do resto do mundo, agradeço ao Ruby por usar o "nosso" formato de data padrão.
Claudio Holanda

7
@rickumali Ruby também aceita a data no YYYY-MM-DDformato, que é o que todos deveriam estar usando de qualquer maneira.
user513951

1

dias = (data final - data inicial) / (60 * 60 * 24)


5
A data é em dias, portanto você não precisa fazer isso. Eu acho que sua solução se torna relevante com as diferenças de DateTime.
suga_shane

1

Bem, cuide do que você quer dizer com "entre" também ...

days_apart = (to - from).to_i     # from + days_apart = to
total_days = (to - from).to_i + 1 # number of "selected" days
in_between_days = (to - from).to_i - 1 # how many days are in between from and to, i.e. excluding those two days
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.