Jak przekonwertować DateTime.now na UTC w Rubim?

97

Jeśli tak d = DateTime.now, jak zamienić „d” na UTC (z odpowiednią datą)?

Popiół
źródło

Odpowiedzi:

155

d = DateTime.now.utc

Ups!

To wydaje się działać w Railsach, ale nie w waniliowym Ruby (i oczywiście o to chodzi w pytaniu)

d = Time.now.utc

Działa jednak.

Czy jest jakiś powód, dla którego musisz używać, DateTimea nie Time? Timepowinien zawierać wszystko, czego potrzebujesz:

irb(main):016:0> Time.now
=> Thu Apr 16 12:40:44 +0100 2009
DanSingerman
źródło
Ponieważ chcę poprawną datę konwersji, tj. Dla GMT +10 może być przed następnym dniem ...
Ash
2
Czas ci to zrobi. Czas obejmuje również część związaną z datą, a nie tylko porę dnia. Sprawdź Time.now.inspect, aby rzucić okiem.
DanSingerman
2
Och, słodko. Jaka jest zatem różnica między datą, godziną i datą i godziną?
Ash
18
Czas jest wewnętrznie przechowywany jako liczba sekund i mikrosekund od epoki, 1 stycznia 1970 00:00 UTC. Data jest wewnętrznie reprezentowana jako astronomiczna liczba juliańska, a DateTime jest po prostu dziwna (i prawdopodobnie dlatego Railsy ją zastępują)
DanSingerman
169
DateTime.now.new_offset(0)

będzie działać w standardowym Rubim (tj. bez ActiveSupport).

Greg Campbell
źródło
3
I to jest właściwie najbardziej poprawna odpowiedź na to pytanie.
Ernest
2
To powinno mieć więcej głosów za. DateTime różni się od Time. Potrzebowałem dokładnie tego.
d11wtq
1
new_offsetargument metody domyślnie 0już. Więc DateTime.now.new_offsetmoże być również używany.
Cryptor
8

Niestety, klasa DateTime nie ma wygodnych metod dostępnych w klasie Time, aby to zrobić. Możesz przekonwertować dowolny obiekt DateTime na UTC w następujący sposób:

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

Możesz przełączyć się z czasu UTC na czas lokalny za pomocą:

d.new_offset(DateTime.now.offset)

gdzie djest obiektem DateTime w czasie UTC. Jeśli chcesz, aby były to wygodne metody, możesz je utworzyć w następujący sposób:

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

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

Możesz to zobaczyć w akcji w następującej sesji 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" 

Jak widać powyżej, początkowy obiekt DateTime ma przesunięcie -04: 00 (czas wschodni). Jestem w czasie pacyficznym z przesunięciem -07: 00. Wywołanie localtimezgodnie z wcześniejszym opisem prawidłowo konwertuje obiekt DateTime na czas lokalny. Wywołanie utcobiektu poprawnie konwertuje go na przesunięcie czasu UTC.

Joel Watson
źródło
5

Spróbuj tego, działa w Rubim :

DateTime.now.to_time.utc
EEPAN
źródło
4

Możesz ustawić ENV, jeśli chcesz Time.nowi DateTime.nowodpowiadać w czasie 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
źródło
2

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

zamieni czas na utc. Ale jak napisano, jeśli jest to tylko czas, możesz użyć:

Time.now.utc

i otrzymaj to od razu.

nitecoder
źródło
1

Ciąg reprezentujący DateTime może być analizowany przez klasę Time.

> Time.parse(DateTime.now.to_s).utc
=> 2015-10-06 14:53:51 UTC
John C.
źródło