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?

Brigue
fonte

Respostas:

170

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

endDate - beginDate 
Agile Jedi
fonte
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.

RyanJM
fonte
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 
Joe Basirico
fonte
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 
wieczorek1990
fonte
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.

mpugach
fonte
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
Henok T
fonte
6

Tente o seguinte:

num_days = later_date - earlier_date
Andrew Hare
fonte
6

tudo isso me levou ao resultado correto, mas acabei fazendo

DateTime.now.mjd - DateTime.parse("01-01-1995").mjd
dabobert
fonte
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)

Michael
fonte
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
estani
fonte