Ruby'de milisaniye cinsinden geçen süreyi nasıl elde ederim?


99

Şuradan aldığım bir Timenesne varsa :

Time.now

ve daha sonra aynı satırla başka bir nesneyi somutlaştırıyorum, kaç milisaniyenin geçtiğini nasıl görebilirim? İkinci nesne aynı dakika, sonraki dakikalar ve hatta saatler içinde oluşturulabilir.

Yanıtlar:


134

Daha önce belirtildiği Timegibi , nesneler üzerinde sayısal (veya kayan nokta) değerlermiş gibi işlem yapabilirsiniz. Bu işlemler, kolayca dönüştürülebilen ikinci çözünürlükle sonuçlanır.

Örneğin:

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

Bunu kesip kesmeyeceğinize karar vermeniz gerekecek.


2
bir to_i ekleyin ve bir tam sayı olarak elde edersiniz, örneğin: ((bitiş - başlangıç) * 1000.0) .to_i
Travis Reeder

finish.to_f - start.to_f?
bodacious

1
finish - startkayan nokta verir; .to_fgereksiz olacaktır.
ezpz

5
Raylar veya aktif destek kullanıyorsanız, aynı dönüşümü yapmak için #in_milliseconds yöntemini kullanabilirsiniz(t2 - t1).in_milliseconds
Nathan Hanna

59

Aşağıdaki ile yukarıdaki çözüme biraz sözdizimi şekeri ekleyebilirsiniz:

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

31

Cevabın yanlış seçilmiş olduğunu düşünüyorum, bu yöntem milisaniye değil saniye veriyor.

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

Burada kayan değerin milisaniye olduğunu varsayıyorum


1
Seçilen cevap doğrudur. Toplama veya çıkarma Time.nowişleminin kullanılması, zamanı, ondalık noktadan önce ve ondalık noktadan sonra nanosaniye olmak üzere kayan nokta değerleri olarak ele almaktır (nsec tam olarak doğru olmayabilir). Yani bu değeri 1000.0milisaniye ile çarpmak, verir.
dfherr

evet, ancak sadece "Time.now" vermek yanlıştır ve soruyu tam olarak yanıtlamaz.
LowFieldTheory

12

Milisaniye cinsinden zaman elde etmek için eklemek daha iyidir .round(3), bu nedenle bazı durumlarda daha doğru olacaktır:

puts Time.now.to_f # => 1453402722.577573

(Time.now.to_f.round(3)*1000).to_i  # => 1453402722578

9

ezpz'in cevabı neredeyse mükemmel, ama umarım biraz daha ekleyebilirim.

Geo milisaniye cinsinden zamanı sordu; bu bir tamsayı miktarı gibi geliyor ve ben dolambaçlı yoldan kayan noktalı araziden geçmem. Dolayısıyla benim yaklaşımım şöyle olurdu:

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

1000 tamsayısıyla çarpmak, kesirli sayıyı mükemmel bir şekilde korur ve biraz daha hızlı olabilir.

Tarihler ve saatlerle uğraşıyorsanız, DateTime sınıfını kullanmanız gerekebilir . Bu benzer şekilde çalışır ancak dönüştürme faktörü 24 * 3600 * 1000 = 86400000'dir .

DateTime'ın strptime ve strftime işlevlerini tarih / saat dizgilerini ayrıştırmada ve biçimlendirmede paha biçilemez buldum (örneğin, günlüklere / günlüklerden). Bilmesi yararlı olan şey şudur:

  • Bu işlevlerin biçimlendirme karakterleri (% H,% M,% S, ...) herhangi bir Unix / Linux sisteminde bulunan C işlevleriyle hemen hemen aynıdır; ve

  • Birkaç tane daha var: Özellikle, % L milisaniye yapar!


Bunu bildiğim iyi oldu! Teşekkürler unknown:)
Geo

1
Her neyse,% L yalnızca Ruby 1.9'da bulunur;)
Rafa de Castro

7

%L Ruby'de milisaniye verir

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

veya

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

milisaniye cinsinden güncel zaman damgasını verecektir.


Bu geçen zamanın nasıl alınacağını söylemez.
Robert

7
DateTime.now.strftime("%Q")

Örnek kullanım:

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

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

6

Time.now.to_f size yardımcı olabilir, ancak saniye döndürür.

Genel olarak, kıyaslamalarla çalışırken:

  • değişkeni o anki zamanı koyun;
  • test etmek için bloğu yerleştirin;
  • önceki akım-zaman değerini çıkararak geçerli zamanı bir değişkene koyun;

Bu çok basit bir süreç, bu yüzden gerçekten bunu sorduğundan emin değilim ...


4

Cevap şuna benzer:

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

milliseconds = (t_start - t_end) * 1000.0

Ancak Time.now yaklaşımın yanlış olma riski vardır. Bu gönderiyi Luca Guidi tarafından buldum:

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

sistem saati sürekli yüzer ve sadece ileriye doğru hareket etmez. Geçen süre hesaplamanız buna dayanıyorsa, hesaplama hatalarıyla ve hatta kesintilerle karşılaşmanız çok olasıdır .

Bu yüzden Process.clock_gettimebunun yerine kullanılması tavsiye edilir . Gibi bir şey:

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

Misal:

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

=> 2.232

3

İlk Time.now değerini saniyeden çıkarmayı deneyin. Şöyle:

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

Bu size iki zaman arasındaki saniyelerin (ve bununla birlikte milisaniyelerin) kayan noktalı sayısını verir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.