Đếm số ngày giữa hai ngày


149

Làm thế nào để tôi đếm số ngày giữa hai ngày này?

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

Câu trả lời:


207

Với các lớp Date (và DateTime), bạn có thể làm (end_date - start_date).to_iđể có được số ngày chênh lệch.


5
@MichaelDurrant Bạn đang đưa ra một giả định không chính đáng. Người dùng không chỉ định nếu chúng là chuỗi hay không. Trong thực tế vì họ đang sử dụng Rails, rất có thể ngày đến từ ActiveRecord sẽ tự động chuyển chúng thành các đối tượng ngày. Văn bản đã cho cũng giống hệt với biểu diễn đối tượng Date, khiến nó rất có thể đến từ nguồn gốc.
Andrew France

84
Điều đó mang lại cho tôi sự khác biệt trong vài giây KHÔNG tính theo ngày với đường ray v3 / 4
2called-hỗn loạn

6
Theo như tôi có thể nói hành vi vẫn giống nhau trong tất cả các phiên bản gần đây của Ruby và ActiveSupport, bao gồm 2.0 và 4.1.0 tương ứng. Timeđối tượng làm trở lại giây mặc dù.
Andrew France

5
để mở rộng câu trả lời @ 2called-chaos, để có được số ngày bạn cần (end_date - start_date) /1.day, sẽ cung cấp cho bạn một số float. Nếu bạn muốn có đầy đủ ngày, bạn chỉ có thể sử dụng ((end_date - start_date) /1.day) .ceil
David K.

2
@David Ngoại trừ nhận xét của @ 2called-chaos là nói sai về Timecác đối tượng, không phải Datecác đối tượng. Có lẽ bạn có thể cập nhật cách đặt tên trong bình luận của bạn để phản ánh rằng họ không phải là ngày?
Andrew France

109

Giả sử rằng end_datestart_datecả hai lớp ActiveSupport::TimeWithZonetrong Rails, thì bạn có thể sử dụng:

(end_date.to_date - start_date.to_date).to_i

2
Nếu nó phải làm với các trường bảng, câu trả lời này là cách để đi; thay vì được đánh giá cao nhất ngay tại đây.
Ben

Không hoạt động (Time.zone.now.to_date - 23.hours.ago.to_date).to_i, nó cho 1 và nên là 0
Yuri Ghensev

3
@YuriGhensev, tùy thuộc vào thời điểm bạn chạy mã ví dụ của mình, ví dụ ngay bây giờ Time.zone.now.to_datetrả về "Thứ tư, ngày 15 tháng 11 năm 2017", trong khi 23.hours.ago.to_datetrả về "Thứ ba, ngày 14 tháng 11 năm 2017". Sự khác biệt về số ngày là và nên là 1 trừ khi bạn chạy mã của mình trong giờ trước nửa đêm.
lee

35

Rails có một số trợ giúp tích hợp có thể giải quyết điều này cho bạn. Một điều cần lưu ý là đây là một phần của Actionview Helpers, vì vậy chúng sẽ không có sẵn trực tiếp từ bảng điều khiển.

Thử cái này

<% 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 không nên khi bạn cần số thực tế để tính toán.
Fedcomp 18/03/19

Câu hỏi này là một trong những trường hợp mà bản thân câu hỏi tốt hơn là hỏi khác nhau. Nếu bạn làm theo các câu trả lời khác ở đây, bạn sẽ gặp phải trường hợp đôi khi bạn muốn hàng tuần hoặc hàng năm hiển thị thay vì ngày. Điều này thực sự nên được chấp nhận là câu trả lời Rails "đúng".
Dylan Pierce

34

Tôi tiếp tục nhận được kết quả trong vài giây, vì vậy điều này làm việc cho tôi:

(Time.now - self.created_at) / 86400

1
@Epigene 1.daykhông rubynhư OP yêu cầu (trong thẻ). Nó Railstrở lên cụ thể active supportmặc dù created_atvề cơ bản là một Modelphương pháp trong Railsquá ..
Roko

26

để có được số ngày trong một khoảng thời gian (chỉ là tổng số ngày)

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

để có được số ngày giữa 2 ngày

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

Cảm ơn vì điều này @ a14m! Đã cho tôi một cách để chụp ngày bao gồm và độc quyền :)
Kris Boyd

18

Không có câu trả lời nào trước đó (cho đến ngày nay) đưa ra sự khác biệt chính xác về số ngày giữa hai ngày.

Một trong những gần nhất là bởi đó . Một câu trả lời đầy đủ sẽ chuyển đổi to_ivà sau đó chia:

(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

Trong ví dụ cụ thể của câu hỏi, người ta không nên phân tích Datenếu thời gian trôi qua có liên quan. Sử dụng Time.parsethay thế.


Điều này có thể không hoạt động như mong đợi khi thời gian chuyển qua DST chuyển tiếp. Trong trường hợp này, độ dài ngày chuyển tiếp DST là hợp pháp dưới 24 giờ, nhưng do số học số nguyên mà ngày đó sẽ không được phản ánh.
PinnyM

4

Để có số ngày trong cả hai ngày ( DateTimeđối tượng):

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

Vấn đề DST tương tự như câu trả lời mà Yuri đưa ra. Số học với thời gian không bao giờ đơn giản như bạn mong đợi :)
PinnyM

0

Để có được số ngày chênh lệch theo hai ngày:

(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
dễ dàng hơn nhiều để trừ các đối tượng ngày.
OpenCoderX

OP không bao giờ hỏi về việc điều chỉnh cho ngày làm việc. Điều này thực sự là phức tạp.
Nathan
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.