¿Cómo obtener la hora actual como un entero de 13 dígitos en Ruby?

88

Tengo esta jQueryfunción que devuelve la hora actual como el número de milisegundos desde la época (1 de enero de 1970):

time = new Date().getTime();

¿Hay alguna forma de hacer lo mismo en Ruby?

En este momento, estoy usando Ruby, Time.now.to_ique funciona muy bien pero devuelve un número entero de 10 dígitos (número de segundos)

¿Cómo puedo hacer que muestre el número de milisegundos, como en jQuery?

Tintín81
fuente
5
Eso no es una "función jQuery", es simplemente ECMAScript (javascript). Quizás eso es lo que provocó el -1, aunque un poco duro.
RobG
Véase también stackoverflow.com/q/20001883/238886
Wayne Conrad

Respuestas:

151
require 'date'

p DateTime.now.strftime('%s') # "1384526946" (seconds)
p DateTime.now.strftime('%Q') # "1384526946523" (milliseconds)
Steenslag
fuente
31
Nota para los usuarios de Rails: el strftimemétodo proporcionado por ActiveSupport::TimeWithZoneno incluye los especificadores %sy %Q. DateTimePrimero deberá convertir a un Ruby simple , usando el to_datetimemétodo.
Lonnon Foster
6
@LonnonFoster Ahora funciona (recién probado en la consola de Rails).
Nikola Stojaković
Hola, ¿cómo puedo hacer lo mismo, pero no por ahora, sino desde un campo de fecha?
Tomer
101

Javascript gettime()devuelve el número de milisegundos desde época.

Ruby's Time.now.to_ite dará la cantidad de segundos desde la época. Si cambia eso a Time.now.to_f, todavía obtiene segundos pero con un componente fraccionario. Simplemente multiplique eso por 1,000 y tendrá milisegundos. Luego utilícelo #to_ipara convertirlo en un número entero. Y terminas con:

(Time.now.to_f * 1000).to_i
Anthony DeSimone
fuente
¡Muchas gracias por la explicación! Todavía es nuevo en todo esto ... No sé qué respuesta marcar como la correcta en realidad ...
Tintin81
1
Solo para más información, Time.nowproviene de Ruby ya que Time.currentproviene de Rails. Por Time.currentlo tanto, es reconocido por la zona horaria de la aplicación Rails y Time.nowestá utilizando la zona horaria del servidor. En mi experiencia, siempre utilícelo Time.currenten su aplicación Rails para
lograr la
1
No, no debería usar Time.currentaquí en absoluto, lleva más tiempo construirlo, y dado que lo está convirtiendo inmediatamente a una marca de tiempo Unix, no le importa en absoluto la coherencia de la zona horaria. (Las marcas de tiempo de Unix siempre se relacionan con UTC). Entonces, si bien lo que está diciendo es cierto en el 99% de los casos, este en términos de rendimiento cae en el último 1%.
The Pellmeister
1
Este es mi enfoque preferido. Una cosa que me gusta hacer es aumentar la clase Time para agregar un :epochmétodo: class Time def epoch (self.to_f * 1000) .to_i end end
Matt Welke
1
esto finge milisegundos
brauliobo
31

(Time.now.to_f * 1000).to_i debería hacer lo mismo.

Zach Kemp
fuente
1
@brauliobo ¿qué son los milisegundos falsos?
Erik Rothoff
1
@brauliobo No lo hace, ya que to_fincluye milisegundos como decimal.
CashIsClay
20

Con strftime, puede obtener la cantidad de segundos y agregar milisegundos fraccionarios (o unidades más pequeñas, si es necesario):

2.2.2 :001 > t = Time.new
 => 2015-06-02 12:16:56 -0700 
2.2.2 :002 > t.strftime('%s%3N')
 => "1433272616888" 

Sin embargo, tenga en cuenta que esto no se redondea, se trunca, como puede ver con to_fo si sale a microsegundos:

2.2.2 :003 > t.to_f
 => 1433272616.888615
2.2.2 :004 > t.usec
 => 888615 

y la solución to_f/ to_itiene el mismo problema:

2.2.2 :009 > (t.to_f * 1000).to_i
 => 1433272616888

así que si realmente le importa la precisión de milisegundos, una mejor apuesta puede ser to_fcon round:

2.2.2 :010 > (t.to_f * 1000).round
 => 1433272616889

Dicho esto, como se indica en los documentos , "IEEE 754 double no es lo suficientemente preciso para representar el número de nanosegundos desde la Época", así que si realmente te importa, considera en to_rlugar de to_f:

2.2.2 :011 > (t.to_r * 1000).round
 => 1433272616889 

- aunque si solo está redondeando a milisegundos probablemente esté bien.

David Moles
fuente
18

Tenga cuidado, no se confunda. El hecho de que Ruby apoye la idea de los segundos fraccionarios como flotante no lo convierte en realidad en un número de coma flotante. Me metí en problemas con esto cuando estaba haciendo comparaciones de tiempo de marca de tiempo de Wireshark en Python ... los cálculos de tiempo en pcap-ng simplemente no funcionaban. Fue solo cuando traté las dos partes (segundos integrales y nanosegundos integrales) como ambos enteros que pude obtener los números adecuados.

Eso es porque los números de coma flotante tienen problemas de precisión . De hecho, un poco de Ruby le mostrará que to_f no es igual, digamos, nsec:

irb(main):019:0> t=Time.now
=> 2015-04-10 16:41:35 -0500
irb(main):020:0> puts "#{t.to_f}; #{t.nsec}"
1428702095.1435847; 143584844

Programador de advertencias. Puede estar seguro de tener 3 dígitos significativos, pero el hecho es que los números de coma flotante en las computadoras son aproximaciones. Los contadores de nanosegundos de las computadoras modernas son números enteros.

Mike S
fuente
La mejor respuesta. Gracias. .strftime("%9N")También se puede utilizar el formato de directiva . ruby-doc.org/core-2.3.1/Time.html#method-i-strftime
rplaurindo
13

Obtener un objeto Time con la Time.nowllamada #to_idevuelve una marca de tiempo de Unix (segundos desde la época). #to_fda fracciones de segundo que puede usar para obtener milisegundos de época:

Time.now.to_f * 1000
levinalex
fuente
3
este falsifica la milisegundos
brauliobo
0

El encasillado Integer (1e6 * Time.now.to_f) devuelve un Bignum que puede contener milisegundos

chava
fuente