Converti l'ora da un fuso orario a un altro in Rails


105

I miei created_attimestamp sono memorizzati in UTC:

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

Come si converte uno di questi in "Fuso orario orientale (USA e Canada)" (tenendo conto dell'ora legale)? Qualcosa di simile a:

Annotation.last.created_at.in_eastern_time

Risposte:


191

Usa il metodo in_time_zone della classe 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

Quindi per il tuo esempio particolare

Annotation.last.created_at.in_time_zone('Eastern Time (US & Canada)')

7
oppure puoi semplicemente usare l' now.in_time_zone(3)
identificativo

8
created_at.in_time_zone("EST")è più breve
Orlando

51
"EST" = "Eastern Standard Time", quindi sarà sbagliato durante l'ora legale. "Fuso orario orientale (USA e Canada)" determina se è l'ora legale o no per te.
jhiro009

1
Nota che il metodo in_time_zone fa parte di ActiveSupport, quindi è integrato in Rails, ma non fa parte dello stdlib di Ruby. Se hai un'app rails, nessun problema. Se hai un'app Ruby diretta, assicurati di richiedere supporto attivo.
Gayle

Il link alla documentazione per questo metodo è qui: apidock.com/rails/DateTime/in_time_zone
Naved Khan

17

Sebbene questa sia una vecchia domanda, vale la pena menzionare qualcosa. In una risposta precedente si suggerisce di utilizzare un before_filter per impostare temporalmente il fuso orario.

Non dovresti mai, mai farlo perché Time.zone memorizza le informazioni nel thread e probabilmente trapeleranno alla successiva richiesta gestita da quel thread.

Invece dovresti usare un around_filter per assicurarti che Time.zone venga reimpostato dopo che la richiesta è stata completata. Qualcosa di simile a:

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

Leggi di più su questo qui


1
Al giorno d'oggi esiste un bel metodo Time.use_zone .
freemanoid

9

Se aggiungi questo al tuo file /config/application.rb

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

Allora puoi fare il cellulare

Annotation.last.created_at.in_time_zone

per ottenere l'ora nel fuso orario specificato.


se stiamo configurando il fuso orario in application.rb, non è necessario chiamare ".in_time_zone". rails lo fa automaticamente per noi jyst deve chiamare Annotation.last.created_at
Vishal

3

Se configuri il tuo /config/application.rb

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

Time.now.in_time_zone

DateTime.now.in_time_zone

2

Imposta il fuso orario sull'ora della costa orientale.

Puoi impostare il fuso orario predefinito in config / environment.rb

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

Ora tutti i record che tirerai fuori saranno in quel fuso orario. Se hai bisogno di fusi orari diversi, ad esempio in base al fuso orario di un utente puoi cambiarlo con un before_filter nel tuo controller.

class ApplicationController < ActionController::Base

  before_filter :set_timezone

  def set_timezone
    Time.zone = current_user.time_zone
  end
end

Assicurati solo di memorizzare tutti i tuoi tempi nel database come UTC e tutto sarà dolce.


È importante se stai utilizzando un server di applicazioni come mongrel, thin o passenger? Eseguono più di un'istanza, a thread singolo credo? Potrei sbagliarmi, mi piacerebbe saperlo!
nitecoder


Potrebbe non essere stato nel '09?
nitecoder

2
@jpwynn: secondo questo: github.com/rails/rails/commit/… è Thread safe da più di 5 anni. Qualche fonte o esempio per il tuo problema?
Pascal

1
Un thread può servire più sessioni. Se lo imposti una volta quando l'utente è connesso, ad esempio, l'ULTIMO utente che accede imposterà il fuso orario per TUTTI gli utenti la cui sessione utilizza lo stesso thread. Quindi DEVI usare un before_filter per impostarlo per ogni utente per ogni caricamento della pagina.
jpw
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.