Ubah UTC ke waktu lokal di Rails 3

95

Saya mengalami masalah saat mengonversi UTC Timeatau TimeWithZoneke waktu lokal di Rails 3.

Katakanlah momentbeberapa Timevariabel dalam UTC (misalnya moment = Time.now.utc). Bagaimana cara mengonversi momentke zona waktu saya, mengurus DST (yaitu menggunakan EST / EDT)?

Lebih tepatnya, saya ingin mencetak "Senin 14 Maret, 09.00" jika waktunya sesuai dengan pagi ini pukul 09.00 EDT dan "Senin 07 Maret, 09.00" jika waktunya adalah pukul 09.00 EST Senin lalu.

Semoga ada cara lain?

Sunting : Saya pertama kali berpikir bahwa "EDT" harus menjadi zona waktu yang dikenali, tetapi "EDT" bukanlah zona waktu yang sebenarnya, lebih seperti keadaan zona waktu. Misalnya, tidak masuk akal untuk meminta Time.utc(2011,1,1).in_time_zone("EDT"). Agak membingungkan, karena "EST" adalah zona waktu aktual, digunakan di beberapa tempat yang tidak menggunakan waktu musim panas dan (UTC-5) selama setahun.

Marc-André Lafortune
sumber

Jawaban:

113

Rails memiliki namanya sendiri. Lihat mereka dengan:

rake time:zones:us

Anda juga dapat berlari rake time:zones:alluntuk semua zona waktu. Untuk melihat lebih banyak tugas penggaruk terkait zona:rake -D time

Jadi, untuk mengonversi ke EST, melayani DST secara otomatis:

Time.now.in_time_zone("Eastern Time (US & Canada)")
Zabba
sumber
21
Bagaimana Anda bisa secara otomatis menggunakan zona waktu untuk pengguna yang mengakses aplikasi web?
dmonopoly
Satu-satunya cara yang saya temukan adalah dengan Javascript dan kemudian meneruskannya kembali ke server. (new Date()).getTimeZoneOffset(). Tapi itu cukup tidak konsisten, jadi orang ini sepertinya telah menulisnya sendiri: onlineaspect.com/2007/06/08/…
Duke
2
secara otomatis menambahkan zona waktu ke semua datetimes ActiveRecord - config.time_zone = 'Eastern Time (AS & Kanada)' - di config / application.rb
idrinkpabst
Pembaruan: pemilik solusi JS tertaut menunjuk ke solusi yang lebih baru: pellepim.bitbucket.org/jstz
Miles
@dmonopoly Anda dapat mengatur zona waktu dalam konfigurasi aplikasi config.time_zone = 'Wellington'dan kemudian menggunakan Time.current (yang setara dengan waktu.sekarang tetapi menggunakan Zona Waktu yang telah Anda tetapkan)
Sean
116

Time#localtime akan memberi Anda waktu dalam zona waktu saat ini dari mesin yang menjalankan kode:

> moment = Time.now.utc
  => 2011-03-14 15:15:58 UTC 
> moment.localtime
  => 2011-03-14 08:15:58 -0700 

Pembaruan: Jika Anda ingin mengkonversi ke zona waktu tertentu daripada zona waktu Anda sendiri, Anda berada di jalur yang benar. Namun, alih-alih mengkhawatirkan EST vs EDT, cukup lewati zona Waktu Timur umum - ia akan tahu berdasarkan hari apakah itu EDT atau EST:

> Time.now.utc.in_time_zone("Eastern Time (US & Canada)")
  => Mon, 14 Mar 2011 11:21:05 EDT -04:00 
> (Time.now.utc + 10.months).in_time_zone("Eastern Time (US & Canada)")
  => Sat, 14 Jan 2012 10:21:18 EST -05:00 
Dylan Markow
sumber
Itu awal. Bagaimana cara menyetel zona waktu saat ini (karena saya bahkan tidak yakin di mana aplikasi akan dihosting, server mungkin berada di zona waktu yang berbeda, lalu apa yang harus digunakan).
Marc-André Lafortune
6
Metode "waktu lokal" memang keren, tetapi zona waktu mesin yang menjalankan kode tidak membantu seperti zona waktu pengguna yang mengakses aplikasi web. (Seperti disebutkan di sini: stackoverflow.com/questions/6003491/rails-3-user-timezones/… ) Bagaimana Anda bisa mendapatkan zona waktu untuk pengguna yang mengakses aplikasi web?
dmonopoly
@daze Saya membayangkan Anda dapat menyiapkan opsi bagi pengguna Anda untuk memilih zona waktu mereka, dan kemudian menggunakan in_time_zonemetode dengan zona waktu mereka.
Dylan Markow
1
Terima kasih, metode waktu lokal persis seperti yang saya butuhkan.
Bob
Time.now.localtimebekerja pada sesi irb normal tetapi ketika saya mencoba menjalankannya pada mesin yang berada dalam zona waktu UTC, itu tidak berfungsi.
Ava
15

Sangat mudah untuk mengkonfigurasinya menggunakan zona lokal sistem Anda, Hanya di aplikasi Anda. Rb tambahkan ini

config.time_zone = Time.now.zone

Kemudian, rel harus menunjukkan stempel waktu di waktu lokal Anda atau Anda dapat menggunakan sesuatu seperti instruksi ini untuk mendapatkan waktu lokal

Post.created_at.localtime
jacr1614
sumber
15

Sebenarnya ada Permata bagus yang disebut local_timeoleh basecamp untuk melakukan semua itu hanya di sisi klien, saya percaya:

https://github.com/basecamp/local_time

mahatmanich.dll
sumber
Ini bekerja paling baik. Kami tahu waktu yang sudah disimpan, cara menunjukkannya dalam format kepada pengguna paling baik dilakukan di sisi klien menurut pendapat saya dan ini melakukannya.
Neeraj Shukla
1

Tidak tahu mengapa tetapi dalam kasus saya itu tidak berfungsi seperti yang disarankan sebelumnya. Tetapi cara kerjanya seperti ini:

Time.now.change(offset: "-3000")

Tentu saja Anda perlu mengubah offsetnilai menjadi milik Anda.

Seybo Glaux
sumber
0

Jika Anda benar-benar melakukannya hanya karena Anda ingin mendapatkan zona waktu pengguna, maka yang harus Anda lakukan adalah mengubah zona waktu Anda config/applications.rb.

Seperti ini:

Rails, secara default, akan menyimpan catatan waktu Anda dalam UTC meskipun Anda menentukan zona waktu saat ini.

config.time_zone = "Singapore"

Jadi hanya ini yang harus Anda lakukan dan Anda siap melakukannya.

di sana
sumber