Wie erhalte ich in Ruby die verstrichene Zeit in Millisekunden?

98

Wenn ich ein TimeObjekt habe von:

Time.now

und später instanziiere ich ein anderes Objekt mit derselben Zeile. Wie kann ich sehen, wie viele Millisekunden vergangen sind? Das zweite Objekt kann in derselben Minute, in den nächsten Minuten oder sogar Stunden erstellt werden.

Geo
quelle

Antworten:

132

Wie bereits erwähnt, können Sie weiterarbeiten Time Objekte so bearbeiten, als wären sie numerische (oder Gleitkomma-) Werte. Diese Operationen führen zu einer zweiten Auflösung, die leicht konvertiert werden kann.

Beispielsweise:

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

Sie müssen entscheiden, ob Sie das abschneiden möchten oder nicht.

ezpz
quelle
2
Fügen Sie ein to_i hinzu und Sie haben es als Ganzzahl, zB: ((Ende - Start) * 1000.0) .to_i
Travis Reeder
finish.to_f - start.to_f?
Bodacious
1
finish - startergibt Gleitkomma; .to_fwäre überflüssig.
Ezpz
5
Wenn Sie Schienen oder aktiven Support verwenden, können Sie die Methode #in_milliseconds verwenden, um dieselbe Konvertierung durchzuführen(t2 - t1).in_milliseconds
Nathan Hanna
58

Sie können der obigen Lösung ein wenig Syntaxzucker wie folgt hinzufügen:

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
quelle
31

Ich denke, die Antwort ist falsch gewählt, diese Methode gibt Sekunden, nicht Millisekunden.

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

Hier nehme ich an, dass der Gleitkommawert die Millisekunden sind

LowFieldTheory
quelle
1
Die gewählte Antwort ist richtig. Bei Verwendung von Addition oder Subtraktion Time.nowwird die Zeit als Gleitkommawert mit Sekunden vor dem Dezimalpunkt und bis zu Nanosekunden nach dem Dezimalpunkt behandelt (obwohl ns möglicherweise nicht vollständig genau sind). Multiplizieren Sie diesen Wert mit 1000.0Milisekunden.
dfherr
Ja, aber nur "Time.now" anzugeben ist ungenau und beantwortet die Frage nicht genau.
LowFieldTheory
12

Um Zeit in Millisekunden zu erhalten, ist es besser, sie hinzuzufügen .round(3), damit sie in einigen Fällen genauer ist:

puts Time.now.to_f # => 1453402722.577573

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

Die Antwort von ezpz ist fast perfekt, aber ich hoffe, ich kann noch ein bisschen mehr hinzufügen.

Geo fragte nach der Zeit in Millisekunden; Das klingt nach einer ganzzahligen Menge, und ich würde den Umweg durch Gleitkomma-Land nicht machen. Mein Ansatz wäre also:

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

Das Multiplizieren mit einer ganzen Zahl 1000 bewahrt die Bruchzahl perfekt und kann auch etwas schneller sein.

Wenn Sie mit Datum und Uhrzeit arbeiten , müssen Sie möglicherweise die DateTime- Klasse verwenden. Dies funktioniert ähnlich, aber der Umrechnungsfaktor beträgt 24 * 3600 * 1000 = 86400000 .

Ich habe festgestellt, dass die strptime- und strftime- Funktionen von DateTime beim Parsen und Formatieren von Datums- / Zeitzeichenfolgen (z. B. zu / von Protokollen) von unschätzbarem Wert sind. Was sich als nützlich erweist, ist:

  • Die Formatierungszeichen für diese Funktionen (% H,% M,% S, ...) sind fast dieselben wie für die C-Funktionen, die auf einem Unix / Linux-System vorhanden sind. und

  • Es gibt noch ein paar mehr: Insbesondere % L macht Millisekunden!

Carl Smotricz
quelle
Gut zu wissen! Danke unknown:)
Geo
1
Wie auch immer,% L existiert nur in Ruby 1.9;)
Rafa de Castro
7
DateTime.now.strftime("%Q")

Anwendungsbeispiel:

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

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

Time.now.to_f kann Ihnen helfen, gibt aber Sekunden zurück.

Wenn ich mit Benchmarks arbeite, gilt Folgendes:

  • die aktuelle Zeit variabel eingeben;
  • Setzen Sie den zu testenden Block ein.
  • Geben Sie die aktuelle Zeit in eine Variable ein und subtrahieren Sie den vorhergehenden Wert für die aktuelle Zeit.

Es ist ein sehr einfacher Prozess, daher bin ich mir nicht sicher, ob Sie das wirklich gefragt haben ...


quelle
6

%L gibt Millisekunden in Rubin

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

oder

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

gibt Ihnen den aktuellen Zeitstempel in Millisekunden.

Sandeep Singh Nagra
quelle
Dies sagt nicht aus, wie man die verstrichene Zeit erhält.
Robert
4

Die Antwort ist so etwas wie:

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

milliseconds = (t_start - t_end) * 1000.0

Die Time.now Ansatz kann jedoch ungenau sein. Ich habe diesen Beitrag von Luca Guidi gefunden:

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

Die Systemuhr schwebt ständig und bewegt sich nicht nur vorwärts. Wenn Ihre Berechnung der verstrichenen Zeit darauf basiert, treten sehr wahrscheinlich Berechnungsfehler oder sogar Ausfälle auf .

Es wird daher empfohlen, Process.clock_gettimestattdessen zu verwenden . Etwas wie:

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

Beispiel:

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

=> 2.232
Robert
quelle
3

Versuchen Sie, das erste Time.now vom zweiten zu subtrahieren. Wie so:

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

Dies gibt Ihnen eine Gleitkommazahl der Sekunden zwischen den beiden Zeiten (und damit den Millisekunden).

mrueg
quelle