Jak mogę znaleźć liczbę dni między dwoma obiektami Date w Rubim?

141

Jak mogę znaleźć liczbę dni między dwoma obiektami Date?

Bryg
źródło

Odpowiedzi:

170

Odejmij datę początkową od daty zakończenia:

endDate - beginDate 
Agile Jedi
źródło
2
myślisz, że masz na myśli odjęcie daty rozpoczęcia od daty końcowej :)
Nader
99
rodzaj antyklimaktyczny, co?
Brig
18
Uwaga: jeśli używasz Wirble w irb (do pokolorowania wyjścia), liczba wymierna będzie miała 1 dołączoną do końca. yikes! możesz użyć to_i, aby przekonwertować wynik na liczbę całkowitą
jwal
9
Jeśli masz DateTimeobiekt, pamiętaj, aby przekonwertować go na Datepierwszy, w przeciwnym razie zwraca liczbę sekund (chyba).
Joshua Muheim
44
zwróć również uwagę, że odejmowanie dwóch Dateobiektów daje Ci Rational, że może być konieczne wpisanie do liczby całkowitej, tak jak w przypadku(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

Wykorzystuje zmodyfikowany numer dnia juliańskiego .

Z Wikipedii :

Data juliańska (JD) to przedział czasu w dniach i ułamkach dnia od 1 stycznia 4713 rpne Południe w Greenwich, kalendarz proleptyczny juliański.

RyanJM
źródło
53

Mogło się to zmienić w Ruby 2.0

Kiedy to robię, dostaję ułamek. Na przykład na konsoli (irb lub 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) 

Oczywiście rzutowanie na int daje oczekiwany rezultat

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

Działa to również w przypadku obiektów DateTime, ale musisz wziąć pod uwagę sekundy, takie jak ten przykład

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
źródło
29

W Ruby 2.1.3 rzeczy się zmieniły:

> 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
źródło
21

Co powiesz na to?

(beginDate...endDate).count

The Range to zestaw unikalnych seriali. I ...to ekskluzywny dosłowny zakres.

Tak beginDate..(endDate - 1)jest. Z wyjątkiem nie jest.

W przypadku, gdy wartość beginDate równa się endDate , pierwszy element zostanie wykluczony ze względu na unikalność i ...wykluczy ostatni. Więc jeśli chcemy .countdatować od dzisiaj do dzisiaj, zwróci 0.

mpugach
źródło
To bardzo dobra odpowiedź, jeśli beginDate jest starsza niż endDate, zwróci 0, co działa doskonale w niektórych przypadkach. Ponadto, jeśli dwie daty są takie same, zwróci 0. Zwraca również zwykłą liczbę całkowitą. Inne odpowiedzi należy przekształcić na liczby całkowite lub może być konieczne przetłumaczenie na 0, jeśli wynik jest ujemny.
EmmanuelB,
8

To zadziałało dla mnie:

(endDate - beginDate).to_i
Henok T
źródło
6

Spróbuj tego:

num_days = later_date - earlier_date
Andrew Hare
źródło
6

wszystko to doprowadziło mnie do właściwego wyniku, ale skończyło się na tym

DateTime.now.mjd - DateTime.parse("01-01-1995").mjd
dabobert
źródło
Jedna ciekawostka na uwagę: DateTime.parse w Rubim oczekuje, że data zostanie podana jako DD / MM / RRRR lub DD-MM-RRRR. Jako Amerykanin zawsze mnie to wyrzuca!
rickumali
15
@rickumali Jako członek z reszty świata, dziękuję Ruby za użycie „naszego” domyślnego formatu daty.
Claudio Holanda
7
@rickumali Ruby akceptuje również datę w YYYY-MM-DDformacie, którego i tak każdy powinien używać.
user513951
1

days = (endDate - beginDate) / (60 * 60 * 24)

Michael
źródło
5
Data jest wyrażona w dniach, więc nie musisz tego robić. Myślę, że Twoje rozwiązanie staje się istotne dzięki różnicom między datami i godzinami.
suga_shane
1

Cóż, zadbaj też o to, co masz na myśli, mówiąc „pomiędzy” ...

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
źródło