Como faço para converter DateTime.now para UTC em Ruby?

96

Se d = DateTime.nowsim, como faço para converter 'd' em UTC (com a data apropriada)?

Cinza
fonte

Respostas:

154

d = DateTime.now.utc

Ops!

Isso parece funcionar no Rails, mas não no Ruby vanilla (e é claro que é isso que a pergunta está perguntando)

d = Time.now.utc

Funciona no entanto.

Existe algum motivo que você precisa usar DateTimee não Time? Timedeve incluir tudo que você precisa:

irb(main):016:0> Time.now
=> Thu Apr 16 12:40:44 +0100 2009
DanSingerman
fonte
Porque eu quero a data correta para a conversão, ou seja, para GMT +10 posso estar adiantado no dia seguinte ...
Cinza
2
O tempo fará isso por você muito bem. O tempo também inclui a parte da data, não apenas a hora do dia. Faça Time.now.inspect para dar uma olhada.
DanSingerman,
2
Oh, querida. Então, qual é a diferença entre Date, Time e DateTime?
Ash,
18
O tempo é armazenado internamente como o número de segundos e microssegundos desde a época, 1º de janeiro de 1970, 00:00 UTC. Data, internamente, é representada como um número de dia juliano astronômico, e DateTime é simplesmente estranho (provavelmente é por isso que Rails o substitui)
DanSingerman
168
DateTime.now.new_offset(0)

funcionará em Ruby padrão (ou seja, sem ActiveSupport).

Greg Campbell
fonte
3
E esta é realmente a resposta mais correta para a pergunta.
Ernest
2
Isso deve ter mais votos positivos. DateTime é diferente de Time. Eu precisava exatamente disso.
d11wtq
1
new_offsetmétodo padrão argumento para 0já. Portanto, também DateTime.now.new_offsetpode ser usado.
Cryptor
8

Infelizmente, a classe DateTime não tem os métodos de conveniência disponíveis na classe Time para fazer isso. Você pode converter qualquer objeto DateTime em UTC assim:

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

Você pode voltar do UTC para o local usando:

d.new_offset(DateTime.now.offset)

onde dé um objeto DateTime no horário UTC. Se você quiser esses métodos de conveniência, poderá criá-los assim:

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

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

Você pode ver isso em ação na seguinte sessão 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 você pode ver acima, o objeto DateTime inicial tem um deslocamento de -04: 00 (horário do leste). Estou no horário do Pacífico com uma diferença de -07: 00. Chamar localtimeconforme descrito anteriormente converte corretamente o objeto DateTime na hora local. Chamar utco objeto corretamente o converte em um deslocamento UTC.

Joel Watson
fonte
5

Experimente isso, funciona em Ruby:

DateTime.now.to_time.utc
EEPAN
fonte
4

Você pode definir um ENV se desejar Time.nowe DateTime.nowresponder no horário 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
fonte
2

No 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"

irá converter a hora em utc. Mas, conforme postado, se for apenas o tempo que você pode usar:

Time.now.utc

e receba imediatamente.

nitecoder
fonte
1

A representação de string de um DateTime pode ser analisada pela classe Time.

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