2009-02-19 13 views
48

Tôi có mã theo dõi thời gian cho nhân viên. Nó tạo ra một truy cập để hiển thị các nhân viên bao lâu họ đã được đồng hồ in cho.Làm cách nào để lấy số giây giữa hai DateTimes trong Ruby trên Rails

Đây là mã hiện tại:

start_time = Time.parse(self.settings.first_clock_in) 
    total_seconds = Time.now - start_time 
    hours = (total_seconds/ 3600).to_i 
    minutes = ((total_seconds % 3600)/60).to_i 
    seconds = ((total_seconds % 3600) % 60).to_i 

này hoạt động tốt. Nhưng bởi vì Thời gian được giới hạn trong phạm vi 1970 - 2038, chúng tôi đang cố gắng thay thế tất cả Thời gian sử dụng bằng DateTimes. Tôi không thể tìm ra cách lấy số giây giữa hai DateTimes. Trừ chúng sẽ mang lại một Rational mà tôi không biết cách diễn giải, trừ khi trừ đi Times sẽ tạo ra sự khác biệt trong vài giây.

Trả lời

64

Trừ hai DateTimes trả về thời gian trôi qua trong ngày, vì vậy bạn chỉ có thể làm:

elapsed_seconds = ((end_time - start_time) * 24 * 60 * 60).to_i 
+0

Ah, tôi biết nó trả về nó trong vài ngày, tôi không biết rằng điều này sẽ bao gồm cả phân số của một ngày là tốt. Cảm ơn. – Tilendor

+4

Điều này không hoạt động chính xác trong trường hợp bước nhảy vọt thứ hai (https://en.wikipedia.org/wiki/Leap_second). –

+31

Chỉ cần một lưu ý cho bất cứ ai khác có thể bị nhầm lẫn bởi điều này. Có, trừ hai 'DateTime's trả về thời gian trôi qua trong ngày. Tuy nhiên, trong Rails một thuộc tính mô hình mà bạn di chuyển dưới dạng 'datetime' thực sự có thể là' ActiveSupport :: TimeWithZone' và trừ hai trong số đó trả về thời gian trôi qua trong * giây *. – evanrmurphy

24

Bạn có thể chuyển đổi chúng thành phao nổi với to_f, mặc dù điều này sẽ làm mất đi độ chính xác thông thường liên quan đến phao nổi. Nếu bạn chỉ cần đúc đến một số nguyên cho toàn bộ giây, nó không đủ lớn để có thể lo lắng.

Kết quả là chỉ trong vài giây:

>> end_time.to_f - start_time.to_f 
=> 7.39954495429993 

>> (end_time.to_f - start_time.to_f).to_i 
=> 7 

Nếu không, bạn có thể xem xét sử dụng to_formatted_s trên đối tượng DateTime và nhìn thấy nếu bạn có thể dỗ đầu ra vào một cái gì đó lớp Decimal sẽ chấp nhận, hoặc chỉ định dạng nó như thời gian Unix đơn giản dưới dạng một chuỗi và gọi số to_i trên đó.

+0

Cảm ơn Luke, chuyển đổi .to_f là tuyệt vời! Nó hoạt động độc lập với lớp Date: hoặc là DateTime hoặc ActiveSupport :: TimeWithZone. – yaru

+0

NoMethodError: phương thức undefined 'to_f 'cho # jameshfisher

45

Hoặc, readably hơn:

diff = datetime_1 - datetime_2 
diff * 1.days # => difference in seconds; requires Ruby on Rails 

Lưu ý, những gì bạn hay một số người tìm kiếm khác thực sự có thể là tìm kiếm là:

diff = datetime_1 - datetime_2 
Date.day_fraction_to_time(diff) # => [h, m, s, frac_s] 
+0

Điều này dường như không hoạt động với tôi (created_at và updated_at). Hai số của tôi là '2016-08-07 20: 33: 54.863568' và' 2016-08-07 20: 33: 54.788684', nhưng sự khác biệt là 6469.9776. Posgres nói rằng các trường đó là 'dấu thời gian không có múi giờ', nếu điều đó tạo nên sự khác biệt. – CHawk

+1

NoMethodError: phương thức undefined 'days 'cho 1: Fixnum –

+1

lưu ý rằng .days là một phương thức đường ray và không có sẵn trong ruby ​​mà không có nó. – sakurashinken

6

Tôi đang sử dụng ruby-2.1.4 và cho tôi làm việc sau

Time.now - Time.new(2014,11,05,17,30,0) 

đã cho tôi sự khác biệt thời gian trong giây

tham khảo: ruby doc

+1

OP đề cập đến đối tượng "Ngày giờ" không phải là đối tượng "Thời gian". –

3

có một phương pháp thực hiện cho rằng:

Time.now.minus_with_coercion(10.seconds.ago)

bằng 10

Nguồn: http://apidock.com/rails/Time/minus_with_coercion

Hy vọng tôi đã giúp.

+0

Chúng ta đang nói về lớp DateTime không phải là lớp Thời gian. – user1735921

+3

Trong thực tế, nếu bạn đọc bài viết gốc, chúng tôi không. – Francois

5

Khác không chính xác dựa vào phân số hoặc hàm trợ giúp. Nó đơn giản hơn nhiều. Bản thân DateTime là số nguyên bên dưới. Dưới đây là cách Ruby:

stop.to_i - start.to_i 

Ví dụ:

start = Time.now 
=> 2016-06-21 14:55:36 -0700 
stop = start + 5.seconds 
=> 2016-06-21 14:55:41 -0700 
stop.to_i - start.to_i 
=> 5 
0

tại sao không sử dụng được xây dựng trong "giây".Dưới đây là một ví dụ:

t1 = Time.now.sec 

elapsed_t = Time.now.sec - t1 

puts "it took me : #{elapsed_t} seconds to do something that is useful \n" 
+0

Phương pháp sec sẽ trả lại thành phần giây của mỗi lần, trừ phút, giờ, v.v ... Thay vào đó, có thể sử dụng ví dụ: to_i để làm việc với tổng số giây kể từ khi epoc. –

0

Xác định một chức năng của Ruby như thế này,

def time_diff(start_time, end_time) 
    seconds_diff = (start_time - end_time).to_i.abs 

    days = seconds_diff/86400 
    seconds_diff -= days * 86400 

    hours = seconds_diff/3600 
    seconds_diff -= hours * 3600 

    minutes = seconds_diff/60 
    seconds_diff -= minutes * 60 

    seconds = seconds_diff 

    "#{days} Days #{hours} Hrs #{minutes} Min #{seconds} Sec" 
end 

Và Gọi chức năng này,

time_diff(Time.now, Time.now-4.days-2.hours-1.minutes-53.seconds) 
Các vấn đề liên quan