¿Cómo obtengo el tiempo transcurrido en milisegundos en Ruby?

98

Si tengo un Timeobjeto obtenido de:

Time.now

y luego instancia otro objeto con esa misma línea, ¿cómo puedo ver cuántos milisegundos han pasado? El segundo objeto puede crearse ese mismo minuto, durante los siguientes minutos o incluso horas.

Geo
fuente

Respuestas:

133

Como ya se dijo, puede operar sobre Timeobjetos como si fueran valores numéricos (o de coma flotante). Estas operaciones dan como resultado una segunda resolución que se puede convertir fácilmente.

Por ejemplo:

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

Deberá decidir si truncarlo o no.

ezpz
fuente
2
agregue un to_i y lo tendrá como un número entero, por ejemplo: ((fin - inicio) * 1000.0) .to_i
Travis Reeder
finish.to_f - start.to_f?
bodacious
1
finish - startproduce punto flotante; .to_fsería redundante.
ezpz
5
Si usa rieles o soporte activo, puede usar el método #in_milliseconds para hacer la misma conversión(t2 - t1).in_milliseconds
Nathan Hanna
58

Puede agregar un poco de azúcar de sintaxis a la solución anterior con lo siguiente:

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

Creo que la respuesta se eligió incorrectamente, ese método da segundos, no milisegundos.

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

Aquí supongo que el valor flotante son los milisegundos

LowFieldTheory
fuente
1
La respuesta elegida es correcta. Usar la suma o la resta Time.nowes tratar el tiempo como valores de punto flotante con segundos antes del punto decimal y hasta nanosegundos después del punto decimal (aunque nsec podría no ser completamente exacto). Entonces, multiplicar ese valor por 1000.0produce milisegundos.
dfherr
sí, pero dar sólo "Time.now" es inexacto y no responde la pregunta con precisión.
LowFieldTheory
12

Para obtener el tiempo en milisegundos, es mejor agregar .round(3), por lo que será más preciso en algunos casos:

puts Time.now.to_f # => 1453402722.577573

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

La respuesta de ezpz es casi perfecta, pero espero poder agregar un poco más.

Geo preguntó sobre el tiempo en milisegundos; esto suena como una cantidad entera, y yo no tomaría el desvío a través de tierra de punto flotante. Entonces mi enfoque sería:

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

Multiplicar por un número entero 1000 conserva el número fraccionario perfectamente y puede ser un poco más rápido también.

Si está tratando con fechas y horas, es posible que deba usar la clase DateTime . Esto funciona de manera similar, pero el factor de conversión es 24 * 3600 * 1000 = 86400000 .

Encontré que las funciones strptime y strftime de DateTime son invaluables para analizar y formatear cadenas de fecha / hora (por ejemplo, hacia / desde registros). Lo que es útil saber es:

  • Los caracteres de formato para estas funciones (% H,% M,% S, ...) son casi los mismos que para las funciones C que se encuentran en cualquier sistema Unix / Linux; y

  • Hay algunas más: ¡En particular, % L hace milisegundos!

Carl Smotricz
fuente
¡Bueno saber! Gracias unknown:)
Geo
1
De todos modos% L existe solo en Ruby 1.9;)
Rafa de Castro
7
DateTime.now.strftime("%Q")

Uso de ejemplo:

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

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

Time.now.to_f puede ayudarte pero devuelve segundos.

En general, cuando trabajo con puntos de referencia, yo:

  • poner en variable la hora actual;
  • inserte el bloque para probar;
  • poner en una variable la hora actual, restando el valor de la hora actual anterior;

Es un proceso muy simple, así que no estoy seguro de que realmente estuvieras preguntando esto ...


fuente
6

%L da milisegundos en rubí

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

o

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

le dará la marca de tiempo actual en milisegundos.

Sandeep Singh Nagra
fuente
Esto no dice cómo obtener el tiempo transcurrido.
Robert
4

La respuesta es algo como:

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

milliseconds = (t_start - t_end) * 1000.0

sin embargo, el Time.now enfoque corre riesgo de ser inexacto. Encontré esta publicación de Luca Guidi:

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

El reloj del sistema flota constantemente y no solo avanza. Si su cálculo del tiempo transcurrido se basa en él, es muy probable que se produzcan errores de cálculo o incluso interrupciones .

Por lo tanto, se recomienda usar Process.clock_gettimeen su lugar. Algo como:

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

Ejemplo:

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

=> 2.232
Robert
fuente
3

Intente restar el primer tiempo ahora del segundo. Al igual que:

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

Esto le da un número de punto flotante de los segundos entre los dos tiempos (y con eso, los milisegundos).

mrueg
fuente