Convertir el tiempo de una zona horaria a otra en Rails

105

Mis created_atmarcas de tiempo se almacenan en UTC:

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

¿Cómo convierto uno de ellos a 'Hora del Este (EE. UU. Y Canadá)' (teniendo en cuenta el horario de verano)? Algo como:

Annotation.last.created_at.in_eastern_time
Tom Lehman
fuente

Respuestas:

191

Utilice el método in_time_zone de la clase 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

Entonces, para tu ejemplo particular

Annotation.last.created_at.in_time_zone('Eastern Time (US & Canada)')
Steve Weet
fuente
7
o simplemente puede usar identificador de horanow.in_time_zone(3)
fl00r
8
created_at.in_time_zone("EST")es más corto
Orlando
51
"EST" = "Hora estándar del este", por lo que será incorrecto durante el horario de verano. "Hora del Este (EE.UU. y Canadá)" determina si es horario de verano o no para usted.
jhiro009
1
Tenga en cuenta que el método in_time_zone es parte de ActiveSupport, por lo que está integrado en Rails, pero no es parte de Ruby stdlib. Si tiene una aplicación de rieles, no hay problema. Si tiene una aplicación Ruby directa, deberá asegurarse de requerir soporte activo.
Gayle
El enlace a la documentación de este método está aquí: apidock.com/rails/DateTime/in_time_zone
Naved Khan
17

Aunque esta es una pregunta antigua, vale la pena mencionar algo. En una respuesta anterior, se sugiere usar un before_filter para establecer la zona horaria temporalmente.

Nunca, nunca debe hacer eso porque Time.zone almacena la información en el hilo, y probablemente se filtrará a la siguiente solicitud manejada por ese hilo.

En su lugar, debe usar un filtro around_filter para asegurarse de que Time.zone se restablezca después de que se complete la solicitud. Algo como:

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

Leer más sobre esto aquí

opsidao
fuente
1
Hay un buen método Time.use_zone hoy en día.
Freemanoid
9

Si agrega esto a su /config/application.rb

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

Entonces puedes celular

Annotation.last.created_at.in_time_zone

para obtener la hora en la zona horaria especificada.

Eifion
fuente
si estamos configurando la zona horaria en application.rb, entonces no es necesario llamar a ".in_time_zone". rieles lo hacen automáticamente por nosotros jyst necesita llamar a Annotation.last.created_at
Vishal
3

Si configura su /config/application.rb

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

Time.now.in_time_zone

DateTime.now.in_time_zone
dorio
fuente
2

Establezca su zona horaria en Hora del Este.

Puede establecer su zona horaria predeterminada en config / environment.rb

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

Ahora todos los registros que extraiga estarán en esa zona horaria. Si necesita diferentes zonas horarias, digamos que según la zona horaria de un usuario, puede cambiarla con un before_filter en su controlador.

class ApplicationController < ActionController::Base

  before_filter :set_timezone

  def set_timezone
    Time.zone = current_user.time_zone
  end
end

Solo asegúrese de almacenar todos sus tiempos en la base de datos como UTC y todo será perfecto.

nitecoder
fuente
¿Importa esto si está ejecutando un servidor de aplicaciones como mestizo, delgado o pasajero? Ejecutan más de una instancia, creo que de un solo hilo. Puede que me equivoque, ¡me encantaría saberlo!
nitecoder
4
Time.zone=es github.com/rails/rails/blob/master/activesupport/lib/… seguro para subprocesos .
no sea que el
¿Puede que no haya sido en el '09?
nitecoder
2
@jpwynn: de acuerdo con esto: github.com/rails/rails/commit/… es seguro para subprocesos desde hace más de 5 años. ¿Alguna fuente o ejemplo para su problema?
Pascal
1
Un hilo puede servir para múltiples sesiones. Si lo configura una vez cuando el usuario inicia sesión, por ejemplo, el ÚLTIMO usuario en iniciar sesión establecerá la zona horaria para TODOS los usuarios cuya sesión use ese mismo hilo. Por lo tanto, DEBE usar un before_filter para configurarlo para cada usuario para cada carga de página.
jpw