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


141

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

Odpowiedzi:


170

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

endDate - beginDate 

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.


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 

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 

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.


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,



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

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)


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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.