Bagaimana cara mengonversi DateTime.now ke UTC di Ruby?

96

Jika sudah d = DateTime.now, bagaimana cara mengubah 'd' menjadi UTC (dengan tanggal yang sesuai)?

Abu
sumber

Jawaban:

154

d = DateTime.now.utc

Ups!

Itu tampaknya berfungsi di Rails, tetapi tidak vanilla Ruby (dan tentu saja itulah yang ditanyakan oleh pertanyaan)

d = Time.now.utc

Namun berhasil.

Apakah ada alasan Anda perlu menggunakan DateTimedan tidak Time? Timeharus menyertakan semua yang Anda butuhkan:

irb(main):016:0> Time.now
=> Thu Apr 16 12:40:44 +0100 2009
DanSingerman
sumber
Karena saya ingin tanggal yang benar untuk konversinya, yaitu untuk GMT +10 bisa lebih cepat keesokan harinya ...
Ash
2
Waktu akan melakukannya untuk Anda dengan baik. Waktu juga mencakup bagian tanggal, bukan hanya waktu dalam sehari. Lakukan Time.now.inspect untuk melihatnya.
DanSingerman
2
Oh manisnya. Jadi apa perbedaan antara Date, Time dan DateTime?
Ash
18
Waktu disimpan secara internal sebagai jumlah detik dan mikrodetik sejak periode 1 Januari 1970 00:00 UTC. Tanggal, secara internal, direpresentasikan sebagai Astronomical Julian Day Number, dan DateTime benar-benar aneh (mungkin itulah sebabnya Rails
menimpanya
168
DateTime.now.new_offset(0)

akan bekerja di Ruby standar (yaitu tanpa ActiveSupport).

Greg Campbell
sumber
3
Dan ini sebenarnya jawaban paling benar untuk pertanyaan itu.
Ernest
2
Ini harus memiliki lebih banyak suara positif. DateTime berbeda dengan Time. Saya membutuhkan ini.
d11wtq
1
new_offsetargumen metode default 0sudah. Jadi DateTime.now.new_offsetsemoga bisa digunakan juga.
Cryptor
8

Sayangnya, kelas DateTime tidak memiliki metode praktis yang tersedia di kelas Waktu untuk melakukan ini. Anda dapat mengonversi objek DateTime apa pun menjadi UTC seperti ini:

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

Anda dapat beralih kembali dari UTC ke waktu lokal menggunakan:

d.new_offset(DateTime.now.offset)

dimana dadalah objek DateTime dalam waktu UTC. Jika Anda menginginkan ini sebagai metode praktis, Anda dapat membuatnya seperti ini:

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

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

Anda dapat melihat ini beraksi di sesi irb berikut:

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" 

Seperti yang Anda lihat di atas, objek DateTime awal memiliki offset -04: 00 (Waktu Bagian Timur). Saya berada di Waktu Pasifik dengan offset -07: 00. Memanggil localtimeseperti yang dijelaskan sebelumnya dengan benar mengubah objek DateTime menjadi waktu lokal. Memanggil utcobjek dengan benar mengubahnya menjadi offset UTC.

Joel Watson
sumber
5

Coba ini, bekerja di Ruby :

DateTime.now.to_time.utc
EEPAN
sumber
4

Anda dapat menyetel ENV jika Anda ingin Time.nowdan DateTime.nowmerespons dalam waktu 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
sumber
2

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

akan mengubah waktu menjadi utc. Tetapi seperti yang diposting jika itu hanya Waktu yang dapat Anda gunakan:

Time.now.utc

dan langsung dapatkan.

nitecoder
sumber
1

Representasi string dari DateTime dapat diurai oleh kelas Waktu.

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