¿Cómo convierto DateTime.now a UTC en Ruby?

96

Si es así d = DateTime.now, ¿cómo convierto 'd' a UTC (con la fecha apropiada)?

Ceniza
fuente

Respuestas:

154

d = DateTime.now.utc

¡Ups!

Eso parece funcionar en Rails, pero no vainilla Ruby (y por supuesto eso es lo que hace la pregunta)

d = Time.now.utc

Sin embargo, funciona.

¿Hay alguna razón por la que debas usar DateTimey no Time? Timedebe incluir todo lo que necesita:

irb(main):016:0> Time.now
=> Thu Apr 16 12:40:44 +0100 2009
DanSingerman
fuente
Porque quiero la fecha correcta para la conversión, es decir, para GMT +10 se puede adelantar al día siguiente ...
Ash
2
El tiempo lo hará bien. La hora también incluye la parte de la fecha, no solo la hora del día. Haz Time.now.inspecta para echar un vistazo.
DanSingerman
2
Oh dulce. Entonces, ¿cuál es la diferencia entre Date, Time y DateTime?
Ash
18
El tiempo se almacena internamente como el número de segundos y microsegundos desde la época, 1 de enero de 1970 a las 00:00 UTC. La fecha, internamente, se representa como un número de día juliano astronómico, y DateTime es simplemente extraño (que probablemente sea la razón por la que Rails lo anula)
DanSingerman
168
DateTime.now.new_offset(0)

funcionará en Ruby estándar (es decir, sin ActiveSupport).

Greg Campbell
fuente
3
Y esta es en realidad la respuesta más correcta a la pregunta.
Ernest
2
Esto debería tener más votos a favor. DateTime es diferente a Time. Necesitaba exactamente esto.
d11wtq
1
new_offsetEl argumento del método 0ya es predeterminado . Así que también DateTime.now.new_offsetse puede utilizar.
Cryptor
8

Desafortunadamente, la clase DateTime no tiene los métodos de conveniencia disponibles en la clase Time para hacer esto. Puede convertir cualquier objeto DateTime en UTC como este:

d = DateTime.now
d.new_offset(Rational(0, 24))

Puede volver de UTC a la hora local usando:

d.new_offset(DateTime.now.offset)

donde des un objeto DateTime en hora UTC. Si desea que estos sean métodos de conveniencia, puede crearlos así:

class DateTime
  def localtime
    new_offset(DateTime.now.offset)
  end

  def utc
    new_offset(Rational(0, 24))
  end
end

Puede ver esto en acción en la siguiente sesión de irb:

d = DateTime.now.new_offset(Rational(-4, 24))
 => #<DateTime: 106105391484260677/43200000000,-1/6,2299161> 
1.8.7 :185 > d.to_s
 => "2012-08-03T15:42:48-04:00" 
1.8.7 :186 > d.localtime.to_s
 => "2012-08-03T12:42:48-07:00" 
1.8.7 :187 > d.utc.to_s
 => "2012-08-03T19:42:48+00:00" 

Como puede ver arriba, el objeto DateTime inicial tiene un desplazamiento de -04: 00 (hora del este). Estoy en la hora del Pacífico con un desplazamiento de -07: 00. Llamar localtimecomo se describió anteriormente convierte correctamente el objeto DateTime en la hora local. Llamar utcal objeto lo convierte correctamente en un desplazamiento UTC.

Joel Watson
fuente
5

Prueba esto, funciona en Ruby:

DateTime.now.to_time.utc
EEPAN
fuente
4

Puede configurar un ENV si desea que su Time.nowy DateTime.nowresponda en hora UTC.

require 'date'
Time.now #=> 2015-11-30 11:37:14 -0800
DateTime.now.to_s #=> "2015-11-30T11:37:25-08:00"
ENV['TZ'] = 'UTC'
Time.now #=> 2015-11-30 19:37:38 +0000
DateTime.now.to_s #=> "2015-11-30T19:37:36+00:00"
jeremywoertink
fuente
2

En irb:

>>d = DateTime.now
=> #<DateTime: 11783702280454271/4800000000,5/12,2299161>
>> "#{d.hour.to_i - d.zone.to_i}:#{d.min}:#{d.sec}"
=> "11:16:41"

convertirá la hora a la utc. Pero como se publicó, si es solo la hora, puede usar:

Time.now.utc

y consígalo de inmediato.

nitecoder
fuente
1

La clase Time puede analizar la representación de cadena de un DateTime.

> Time.parse(DateTime.now.to_s).utc
=> 2015-10-06 14:53:51 UTC
John C.
fuente