Ubah Waktu dari satu zona waktu ke zona waktu lainnya di Rails

105

created_atStempel waktu saya disimpan dalam UTC:

>> Annotation.last.created_at
=> Sat, 29 Aug 2009 23:30:09 UTC +00:00

Bagaimana cara mengonversi salah satunya ke 'Waktu Bagian Timur (AS & Kanada)' (dengan memperhitungkan penghematan siang hari)? Sesuatu seperti:

Annotation.last.created_at.in_eastern_time
Tom Lehman
sumber

Jawaban:

191

Gunakan metode in_time_zone kelas DateTime

Loading development environment (Rails 2.3.2)
>> now = DateTime.now.utc
=> Sun, 06 Sep 2009 22:27:45 +0000
>> now.in_time_zone('Eastern Time (US & Canada)')
=> Sun, 06 Sep 2009 18:27:45 EDT -04:00
>> quit

Jadi untuk contoh khusus Anda

Annotation.last.created_at.in_time_zone('Eastern Time (US & Canada)')
Steve Weet
sumber
7
atau Anda dapat menggunakan now.in_time_zone(3)
ID
8
created_at.in_time_zone("EST")lebih pendek
Orlando
51
"EST" = "Waktu Standar Timur", jadi ini akan menjadi salah selama Waktu Musim Panas. "Waktu Timur (AS & Kanada)" akan menentukan apakah itu DST atau bukan untuk Anda.
jhiro009
1
Perhatikan bahwa metode in_time_zone adalah bagian dari ActiveSupport, oleh karena itu ia dibangun ke dalam Rails, tetapi bukan bagian dari stdlib Ruby. Jika Anda memiliki aplikasi rel, tidak masalah. Jika Anda memiliki aplikasi Ruby langsung, Anda harus memastikan untuk membutuhkan dukungan aktif.
Gayle
Tautan ke dokumentasi untuk metode ini ada di sini: apidock.com/rails/DateTime/in_time_zone
Naved Khan
17

Meskipun ini adalah pertanyaan lama, ada baiknya menyebutkan sesuatu. Dalam balasan sebelumnya , disarankan untuk menggunakan before_filter untuk menyetel zona waktu untuk sementara.

Anda tidak boleh melakukan itu karena Time.zone menyimpan informasi di utas, dan mungkin akan bocor ke permintaan berikutnya yang ditangani oleh utas itu.

Sebagai gantinya Anda harus menggunakan around_filter untuk memastikan bahwa Time.zone disetel ulang setelah permintaan selesai. Sesuatu seperti:

around_filter :set_time_zone

private

def set_time_zone
  old_time_zone = Time.zone
  Time.zone = current_user.time_zone if logged_in?
  yield
ensure
  Time.zone = old_time_zone
end

Baca lebih lanjut tentang ini di sini

opsidao
sumber
1
Ada metode Time.use_zone yang bagus saat ini.
freemanoid
9

Jika Anda menambahkan ini ke file /config/application.rb

config.time_zone = 'Eastern Time (US & Canada)'

Lalu Anda bisa sel

Annotation.last.created_at.in_time_zone

untuk mendapatkan waktu dalam zona waktu yang ditentukan.

Eifion
sumber
jika kita mengkonfigurasi zona waktu di application.rb maka tidak perlu memanggil ".in_time_zone". rel secara otomatis melakukannya untuk kita jyst perlu memanggil Annotation.last.created_at
Vishal
3

Jika Anda mengkonfigurasi file /config/application.rb

config.time_zone = 'Eastern Time (US & Canada)'

Time.now.in_time_zone

DateTime.now.in_time_zone
Dorian
sumber
2

Setel zona waktu Anda ke Waktu Bagian Timur.

Anda dapat menyetel zona waktu default Anda di config / environment.rb

config.time_zone = "Eastern Time (US & Canada)"

Sekarang semua catatan yang Anda keluarkan akan berada di zona waktu itu. Jika Anda membutuhkan zona waktu yang berbeda, katakanlah berdasarkan zona waktu pengguna, Anda dapat mengubahnya dengan before_filter di pengontrol Anda.

class ApplicationController < ActionController::Base

  before_filter :set_timezone

  def set_timezone
    Time.zone = current_user.time_zone
  end
end

Pastikan Anda menyimpan semua waktu Anda di database sebagai UTC dan semuanya akan menyenangkan.

nitecoder
sumber
Apakah ini penting jika Anda menjalankan server aplikasi seperti anjing kampung, kurus, atau penumpang? Mereka menjalankan lebih dari satu contoh, satu utas saya percaya? Saya mungkin salah, ingin tahu!
nitecoder
4
Time.zone=adalah thread-safe github.com/rails/rails/blob/master/activesupport/lib/… .
jangan sampai
Mungkin bukan di '09?
nitecoder
2
@jpwynn: menurut ini: github.com/rails/rails/commit/… Thread aman sejak lebih dari 5 tahun. Ada sumber atau contoh untuk Masalah Anda?
Pascal
1
Sebuah utas dapat melayani banyak sesi. Jika Anda menyetelnya sekali saat pengguna masuk, misalnya, pengguna TERAKHIR yang masuk akan menyetel zona waktu untuk SEMUA pengguna yang sesinya menggunakan utas yang sama. Jadi, Anda HARUS menggunakan before_filter untuk mengaturnya bagi setiap pengguna untuk setiap pemuatan halaman.
jpw