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.