Policz liczbę dni między dwiema datami


149

Jak policzyć liczbę dni między tymi dwiema datami?

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

Odpowiedzi:


207

Za pomocą klas Date (i DateTime) możesz (end_date - start_date).to_iuzyskać różnicę w liczbie dni.


5
@MichaelDurrant Robisz nieuzasadnione założenie. Użytkownik nie określa, czy są to łańcuchy, czy nie. W rzeczywistości, ponieważ używają Railsów, najprawdopodobniej daty pochodzą z ActiveRecord, który automatycznie rzutuje je na obiekty daty. Podany tekst jest również identyczny z reprezentacją obiektu Date, co sprawia, że ​​jest wysoce prawdopodobne, że pochodzi z natywnego źródła.
Andrew France

84
To daje mi różnicę w sekundach, a nie w dniach z szynami v3 / 4
wezwany-chaos

6
O ile wiem, zachowanie pozostaje takie samo we wszystkich ostatnich wersjach Ruby i ActiveSupport, uwzględnij odpowiednio 2.0 i 4.1.0. Timeobiekty zwracają jednak sekundy.
Andrew France

5
aby rozwinąć odpowiedź @ 2called-chaos, aby uzyskać dni, których potrzebujesz (data_końcowa - data_początkowa) /1.day, co da ci liczbę zmiennoprzecinkową. Jeśli chcesz mieć tylko pełne dni, możesz użyć ((data_końcowa
David K.

2
@David Tyle że komentarz @ 2called-chaos błędnie odnosi się do Timeobiektów, a nie Dateobiektów. Może mógłbyś zaktualizować nazewnictwo w swoim komentarzu, aby odzwierciedlić, że nie są to daty?
Andrew France

109

Zakładając, że end_datei start_dateoba są klasą ActiveSupport::TimeWithZonew Railsach, możesz użyć:

(end_date.to_date - start_date.to_date).to_i

2
Jeśli ma to związek z polami tabeli, ta odpowiedź jest do zrobienia; zamiast najwyżej ocenianego tutaj.
Ben,

Nie działa (Time.zone.now.to_date - 23.hours.ago.to_date).to_i, daje 1 i powinno być 0
Yuri Ghensev

3
@YuriGhensev, zależy to od tego, kiedy uruchomisz przykładowy kod, na przykład teraz Time.zone.now.to_datezwraca „Wed, 15 Nov 2017”, a 23.hours.ago.to_datezwraca „Tue, 14 Nov 2017”. Różnica w liczbie dni wynosi i powinna wynosić 1, chyba że uruchomiłeś kod na godzinę przed północą.
lee

35

Railsy mają wbudowanych pomocników, które mogą rozwiązać ten problem. Należy pamiętać, że jest to część pomocników Actionview, więc nie będą one dostępne bezpośrednio z konsoli.

Spróbuj tego

<% 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 nie powinno być, gdy potrzebujesz rzeczywistej liczby do obliczeń.
Fedcomp

To pytanie jest jednym z tych przypadków, w których samo pytanie lepiej jest zadać inaczej. Jeśli zastosujesz się do innych odpowiedzi tutaj, napotkasz przypadki, w których czasami chcesz, aby zamiast dni były wyświetlane tygodnie lub lata. To naprawdę powinno zostać zaakceptowane jako „właściwa” odpowiedź Railsów.
Dylan Pierce

34

Otrzymywałem wyniki w ciągu kilku sekund, więc to zadziałało:

(Time.now - self.created_at) / 86400

1
@Epigene 1.daynie jest rubyzgodne z żądaniem OP (w tagach). Jest to Railslub bardziej szczegółowe, active supportchociaż created_atjest w zasadzie Modelmetodą w Railstak ..
Roko

26

aby uzyskać liczbę dni w zakresie czasowym (tylko liczba wszystkich dni)

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

aby uzyskać liczbę dni między dwiema datami

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

Dzięki za to @ a14m! Dał mi sposób na robienie inkluzywnych i ekskluzywnych ujęć randkowych :)
Kris Boyd

18

Żadna z poprzednich odpowiedzi (do tej pory) nie podaje prawidłowej różnicy w dniach między dwiema datami.

Ten, który jest najbliżej, jest godny . Pełna odpowiedź przekształciłaby, to_ia następnie podzieliłaby:

(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

W konkretnym przykładzie pytania nie należy analizować, Dateczy upływający czas jest istotny. Użyj Time.parsezamiast tego.


Może to nie działać zgodnie z oczekiwaniami, gdy czasy przekraczają przejście na czas letni do przodu. W tym przypadku długość dnia przejściowego DST jest zgodnie z prawem krótsza niż 24 godziny, ale z powodu arytmetyki całkowitej ten dzień w ogóle nie zostanie odzwierciedlony.
PinnyM

4

Aby mieć liczbę pełnych dni między dwiema datami ( DateTimeobiektami):

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

Ten sam problem z czasem letnim, co w odpowiedzi, której udzielił Jurij. Arytmetyka z czasem nigdy nie jest tak prosta, jak można by się tego spodziewać :)
PinnyM

0

Aby uzyskać różnicę w liczbie dni w dwóch datach:

(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
znacznie łatwiej odjąć obiekty daty.
OpenCoderX

OP nigdy nie pytał o dostosowanie do dni roboczych. I tak jest to naprawdę zawiłe.
Nathan
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.