Cómo convertir una marca de tiempo unix (segundos desde época) a Ruby DateTime?


¿Cómo convertir una marca de tiempo Unix (segundos desde época) a Ruby DateTime?

Author: Johannes Hoff, 2011-10-19

6 answers

DateTime.strptime puede manejar segundos desde epoch. El número debe convertirse en una cadena:

require 'date'
DateTime.strptime("1318996912",'%s')
 302
Author: steenslag,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-04 12:31:10

Lo siento, breve momento de falla de la sinapsis. Aquí está la verdadera respuesta.

require 'date'

Time.at(seconds_since_epoch_integer).to_datetime

Breve ejemplo (esto tiene en cuenta la zona horaria actual del sistema):

$ date +%s
1318996912

$ irb

ruby-1.9.2-p180 :001 > require 'date'
 => true 

ruby-1.9.2-p180 :002 > Time.at(1318996912).to_datetime
 => #<DateTime: 2011-10-18T23:01:52-05:00 (13261609807/5400,-5/24,2299161)> 

Actualización posterior (para UTC):

ruby-1.9.2-p180 :003 > Time.at(1318996912).utc.to_datetime
 => #<DateTime: 2011-10-19T04:01:52+00:00 (13261609807/5400,0/1,2299161)>

Actualización reciente : Comparé las mejores soluciones en este hilo mientras trabajaba en un servicio de HA hace una semana o dos, y me sorprendió encontrar que Time.at(..) supera a DateTime.strptime(..) (actualización: se agregaron más puntos de referencia).

# ~ % ruby -v
#  => ruby 2.1.5p273 (2014-11-13 revision 48405) [x86_64-darwin13.0]

irb(main):038:0> Benchmark.measure do
irb(main):039:1*   ["1318996912", "1318496912"].each do |s|
irb(main):040:2*     DateTime.strptime(s, '%s')
irb(main):041:2>   end
irb(main):042:1> end

=> #<Benchmark ... @real=2.9e-05 ... @total=0.0>

irb(main):044:0> Benchmark.measure do
irb(main):045:1>   [1318996912, 1318496912].each do |i|
irb(main):046:2>     DateTime.strptime(i.to_s, '%s')
irb(main):047:2>   end
irb(main):048:1> end

=> #<Benchmark ... @real=2.0e-05 ... @total=0.0>

irb(main):050:0* Benchmark.measure do
irb(main):051:1*   ["1318996912", "1318496912"].each do |s|
irb(main):052:2*     Time.at(s.to_i).to_datetime
irb(main):053:2>   end
irb(main):054:1> end

=> #<Benchmark ... @real=1.5e-05 ... @total=0.0>

irb(main):056:0* Benchmark.measure do
irb(main):057:1*   [1318996912, 1318496912].each do |i|
irb(main):058:2*     Time.at(i).to_datetime
irb(main):059:2>   end
irb(main):060:1> end

=> #<Benchmark ... @real=2.0e-05 ... @total=0.0>
 572
Author: Adam Eberlin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-06 02:12:34

Manejo de Zonas Horarias

Solo quiero aclarar, a pesar de que esto ha sido comentado para que las personas futuras no se pierdan esta distinción tan importante.

DateTime.strptime("1318996912",'%s') # => Wed, 19 Oct 2011 04:01:52 +0000

Muestra un valor de retorno en UTC y requiere que los segundos sean una cadena y muestra un objeto de tiempo UTC, mientras que

Time.at(1318996912) # => 2011-10-19 00:01:52 -0400

Muestra un valor devuelto en la zona horaria LOCAL, normalmente requiere un argumento FixNum, pero el objeto Time en sí sigue estando en UTC aunque la visualización no lo esté.

So a pesar de que pasé el mismo entero a ambos métodos, aparentemente dos resultados diferentes debido a cómo funciona el método class' #to_s. Sin embargo, como @Eero tuvo que recordarme dos veces:

Time.at(1318996912) == DateTime.strptime("1318996912",'%s') # => true

Una comparación de igualdad entre los dos valores de retorno todavía devuelve true. De nuevo, esto se debe a que los valores son básicamente los mismos (aunque diferentes clases, el método #== se encarga de esto por usted), pero el método #to_s imprime cadenas drásticamente diferentes. Aunque, si nos fijamos en la cadenas, podemos ver que son de hecho el mismo tiempo, sólo impreso en diferentes zonas horarias.

Método Argumento Clarificación

Los documentos también dicen "Si se da un argumento numérico, el resultado es en hora local."lo cual tiene sentido, pero fue un poco confuso para mí porque no dan ningún ejemplo de argumentos no enteros en los documentos. Por lo tanto, para algunos ejemplos de argumentos no enteros:

Time.at("1318996912")
TypeError: can't convert String into an exact number

No puede usar un argumento de cadena, pero puede usar un argumento de tiempo en Time.at y devolverá el resultado en la zona horaria del argumento:

Time.at(Time.new(2007,11,1,15,25,0, "+09:00"))
=> 2007-11-01 15:25:00 +0900

* * * * editado para no ser completa y totalmente incorrecto en todos los sentidos * * * *

 46
Author: WattsInABox,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-30 20:02:46

Un comando para convertir date time a formato Unix y luego a string

    DateTime.strptime(Time.now.utc.to_i.to_s,'%s').strftime("%d %m %y")

    Time.now.utc.to_i #Converts time from Unix format
    DateTime.strptime(Time.now.utc.to_i.to_s,'%s') #Converts date and time from unix format to DateTime

Finalmente strftime se utiliza para formatear la fecha

Ejemplo:

    irb(main):034:0> DateTime.strptime("1410321600",'%s').strftime("%d %m %y")
    "10 09 14"
 7
Author: Tejasvi Manmatha,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-12 15:53:21

Esto le indica la fecha del número de segundos en el futuro desde el momento en que ejecuta el código.

time = Time.new + 1000000000 #date in 1 billion seconds

Pone (tiempo)

De acuerdo con el tiempo actual estoy respondiendo a la pregunta que imprime 047-05-14 05:16:16 +0000 (1 mil millones de segundos en el futuro)

O si desea contar mil millones de segundos de un momento en particular, está en formato Time.mktime(year, month,date,hours,minutes)

time = Time.mktime(1987,8,18,6,45) + 1000000000

Pone ("Tendría 1 mil millones de segundos de edad en:" +tiempo)

 1
Author: sbutterworth,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-05 03:42:48

Si solo quieres una Fecha, puedes hacer Date.strptime(invoice.date.to_s, '%s') donde invoice.date viene en forma deFixnum y luego se convierte en String.

 0
Author: pjammer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-10 18:25:09