Convertendo carimbo de data / hora UTC para ISO 8601 em Ruby

86

Eu tenho um carimbo de data / hora que está em UTC

"2010-10-25 23:48:46 UTC"

Eu preciso convertê-lo para ISO 8601

"2010-10-29 06: 09Z"

A documentação é muito confusa - qual é a maneira mais fácil de fazer isso?

ming yow
fonte

Respostas:

187

Acho que você está tentando nos enganar.

A data de entrada para sua pergunta é 25 de outubro de 2010 , enquanto a saída é 29 de outubro de 2010 . Bem jogado!

Continuando neste tópico picuinhas: seus tempos também são completamente diferentes e você está perdendo os segundos do tempo de saída.

Agora, para a verdadeira resposta.

No entanto, primeiro um pequeno fato: a saída ISO 8601 em Ruby é semelhante à saída "Data e hora combinadas" da página da Wikipedia da ISO 8601 .

Você tem uma string e, portanto, precisará convertê-la em um Timeobjeto com o qual possa fazer isso to_time. Então é simplesmente uma questão de chamar iso8601esse objeto para obter a versão ISO 8601:

"2010-10-25 23:48:46 UTC".to_time.iso8601

O to_timemétodo é cortesia do Rails, enquanto o iso8601é cortesia da biblioteca padrão do Ruby.

Ryan Bigg
fonte
7
Boa resposta, mas não entendi a primeira parte (era para ser humor?)
Mark Thomas
5
Droga! vocês viram meu plano para enganar vocês. = P Obrigado pela ótima resposta, eu me pergunto por que eles não escrevem isso apenas na documentação!
ming yow
13
@Mark Thomas: sim, era para ser humor. Ele deu uma entrada e um tempo de saída que nunca corresponderiam. Pequeno hobbit malandro!
Ryan Bigg
Isso funciona, mas embora sua pergunta indagasse como fazê-lo em ruby, não presumia que fosse no ambiente de trilhos.
courtimas
1
Relacionado, obrigado por me apontar para formatos 'to_time' ~ Time.now.iso8601 como "2010-10-25T23: 48: 46Z", se você quiser usar '+00: 00' em vez de 'Z' (que eu tinha para um sistema legado) Time.now.to_time.iso8601 parece fazer isso.
lucygenik
21

Depois de muito experimentar, acho que o parser da biblioteca Time é melhor do que DateTime, embora as razões me escapem no momento. Com essa ressalva, eu sempre uso Time em vez de DateTime para esse tipo de coisa, e a documentação do ruby ​​também é difícil de entender por que isso acontece,

require 'time'
puts Time.parse("2010-10-25 23:48:46 UTC").iso8601
"2010-10-25T23:48:46Z"
Steeve McCauley
fonte
5
boa solução de rubi puro. Só quero adicionar, se a hora original não for UTC, você pode querer isto Time.parse("...").utc.iso8601:, do contrário, você obterá a hora com o sufixo +03:00ou algum outro valor dependendo do fuso horário original com a string de hora. Quero dizer, em vez de Z.
akostadinov de
4

Nota: você deve converter (analisar) uma string de tempo em um objeto de tempo antes de poder aplicar o método to_time.

ruby-1.9.2-p180 :016 > "2010-10-25 23:48:46 UTC".to_time.iso8601
NoMethodError: undefined method `to_time' for "2010-10-25 23:48:46 UTC":String
    from (irb):16

Procedimento correto:

irb> ut = DateTime.parse("2010-10-25 23:48:46 UTC")

irb> ut.iso8601
 => "2010-10-25T23:48:46+00:00" 
Aerodame
fonte
1

Adicionando uma resposta a esta pergunta super antiga porque se você estiver usando Rails, não há necessidade de convertê-lo / analisá-lo da maneira que as outras respostas aqui estão dizendo para você fazer:

  • Se já for um carimbo de data / hora (por exemplo, um atributo created_atou updated_at), você pode chamar diretamente o iso8601método nesse carimbo de data / hora (por exemplo, object.created_at.iso8601).
  • O iso8601método também aceita um argumento numérico para exibir dígitos fracionários; você usaria isso se quiser em 2020-04-06T19:16:55.604Zvez de 2020-04-06T19:16:55Z.

https://api.rubyonrails.org/v5.2.4/classes/ActiveSupport/TimeWithZone.html#method-i-iso8601

Allison
fonte