Bagaimana cara mendapatkan waktu berlalu dalam milidetik di Ruby?

98

Jika saya punya Timebenda didapat dari:

Time.now

dan kemudian saya membuat instance objek lain dengan baris yang sama, bagaimana saya bisa melihat berapa milidetik yang telah berlalu? Objek kedua dapat dibuat pada menit yang sama, selama beberapa menit atau bahkan jam berikutnya.

Geo
sumber

Jawaban:

133

Seperti yang telah dinyatakan, Anda dapat mengoperasikan Timeobjek seolah-olah itu adalah nilai numerik (atau floating point). Operasi ini menghasilkan resolusi kedua yang dapat dengan mudah diubah.

Sebagai contoh:

def time_diff_milli(start, finish)
   (finish - start) * 1000.0
end

t1 = Time.now
# arbitrary elapsed time
t2 = Time.now

msecs = time_diff_milli t1, t2

Anda harus memutuskan apakah akan memotongnya atau tidak.

ezpz
sumber
2
tambahkan to_i dan Anda memilikinya sebagai integer, misalnya: ((finish - start) * 1000.0) .to_i
Travis Reeder
finish.to_f - start.to_f?
bodacious
1
finish - startmenghasilkan floating point; .to_fakan menjadi mubazir.
ezpz
5
Jika menggunakan rel atau dukungan aktif, Anda dapat menggunakan metode #in_milliseconds untuk melakukan konversi yang sama(t2 - t1).in_milliseconds
Nathan Hanna
58

Anda dapat menambahkan sedikit gula sintaks ke solusi di atas dengan yang berikut:

class Time
  def to_ms
    (self.to_f * 1000.0).to_i
  end
end

start_time = Time.now
sleep(3)
end_time = Time.now
elapsed_time = end_time.to_ms - start_time.to_ms  # => 3004
phlipper
sumber
31

Saya pikir jawabannya salah dipilih, metode itu memberikan detik, bukan milidetik.

t = Time.now.t­o_f
=> 1382471965.146

Di sini saya kira nilai mengambang adalah milidetik

Teori LowField
sumber
1
Jawaban yang dipilih benar. Menggunakan penjumlahan atau pengurangan aktif Time.nowmemperlakukan waktu sebagai nilai titik mengambang dengan detik sebelum titik desimal dan hingga nanodetik setelah titik desimal (meskipun nsec mungkin tidak sepenuhnya akurat). Jadi, mengalikan nilai itu dengan 1000.0menghasilkan milidetik.
dfherr
ya, tetapi memberikan "Time.now" saja tidak akurat dan tidak menjawab pertanyaan dengan tepat.
LowFieldTheory
12

Untuk mendapatkan waktu dalam milidetik, lebih baik ditambahkan .round(3), sehingga akan lebih akurat dalam beberapa kasus:

puts Time.now.to_f # => 1453402722.577573

(Time.now.to_f.round(3)*1000).to_i  # => 1453402722578
Steven Yue
sumber
9

Jawaban ezpz hampir sempurna, tapi saya harap saya bisa menambahkan lebih banyak.

Geo bertanya tentang waktu dalam milidetik; ini terdengar seperti kuantitas integer, dan saya tidak akan mengambil jalan memutar melalui tanah floating-point. Jadi pendekatan saya adalah:

irb(main):038:0> t8 = Time.now
=> Sun Nov 01 15:18:04 +0100 2009
irb(main):039:0> t9 = Time.now
=> Sun Nov 01 15:18:18 +0100 2009
irb(main):040:0> dif = t9 - t8
=> 13.940166
irb(main):041:0> (1000 * dif).to_i
=> 13940

Mengalikan dengan bilangan bulat 1000 mempertahankan bilangan pecahan dengan sempurna dan mungkin sedikit lebih cepat juga.

Jika Anda berurusan dengan tanggal dan waktu, Anda mungkin perlu menggunakan kelas DateTime . Ini berfungsi serupa tetapi faktor konversinya adalah 24 * 3600 * 1000 = 86400000 .

Saya telah menemukan bahwa fungsi strptime dan strftime DateTime sangat berharga dalam parsing dan format string tanggal / waktu (misalnya ke / dari log). Apa yang berguna untuk diketahui adalah:

  • Karakter pemformatan untuk fungsi ini (% H,% M,% S, ...) hampir sama dengan fungsi C yang ditemukan pada sistem Unix / Linux manapun; dan

  • Ada beberapa lagi: Secara khusus, % L melakukan milidetik!

Carl Smotricz
sumber
Senang mendengarnya! Terima kasih unknown:)
Geo
1
Bagaimanapun% L hanya ada di Ruby 1.9;)
Rafa de Castro
7
DateTime.now.strftime("%Q")

Contoh penggunaan:

>> DateTime.now.strftime("%Q")
=> "1541433332357"

>> DateTime.now.strftime("%Q").to_i
=> 1541433332357
Ryan McGeary
sumber
6

Time.now.to_f dapat membantu Anda tetapi mengembalikan detik.

Secara umum, saat bekerja dengan tolok ukur I:

  • masukkan ke dalam variabel waktu saat ini;
  • masukkan blok untuk diuji;
  • memasukkan variabel waktu saat ini, mengurangkan nilai waktu saat ini sebelumnya;

Ini proses yang sangat sederhana, jadi saya tidak yakin Anda benar-benar menanyakan ini ...


sumber
6

%L memberikan milidetik dalam ruby

require 'time'
puts Time.now.strftime("%Y-%m-%dT%H:%M:%S.%L")

atau

puts Time.now.strftime("%Y-%m-%d %H:%M:%S.%L")

akan memberi Anda stempel waktu saat ini dalam milidetik.

Sandeep Singh Nagra
sumber
Ini tidak menjelaskan bagaimana mendapatkan waktu yang telah berlalu.
Robert
4

Jawabannya seperti ini:

t_start = Time.now
# time-consuming operation
t_end = Time.now

milliseconds = (t_start - t_end) * 1000.0

Namun, Time.now pendekatan tersebut berisiko menjadi tidak akurat. Saya menemukan posting ini oleh Luca Guidi:

https://blog.dnsimple.com/2018/03/elapsed-time-with-ruby-the-right-way/

jam sistem terus mengambang dan tidak hanya bergerak maju. Jika perhitungan Anda atas waktu yang telah berlalu didasarkan padanya, kemungkinan besar Anda akan mengalami kesalahan perhitungan atau bahkan pemadaman .

Jadi, sebaiknya gunakan Process.clock_gettimesaja. Sesuatu seperti:

def measure_time
  start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
  yield
  end_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
  elapsed_time = end_time - start_time
  elapsed_time.round(3)
end

Contoh:

elapsed = measure_time do
    # your time-consuming task here:
    sleep 2.2321
end

=> 2.232
Robert
sumber
3

Cobalah mengurangi waktu pertama. Sekarang dari yang kedua. Seperti:

a = Time.now
sleep(3)
puts Time.now - a # about 3.0

Ini memberi Anda angka floating-point dari detik antara dua waktu (dan dengan itu, milidetik).

mrueg
sumber