Convertir UTC a hora local en Rails 3

95

Tengo problemas para convertir una UTC Timeo TimeWithZonela hora local en Rails 3.

Digamos que momentes una Timevariable en UTC (por ejemplo moment = Time.now.utc). ¿Cómo puedo convertir momenta mi zona horaria, teniendo en cuenta el horario de verano (es decir, usando EST / EDT)?

Más precisamente, me gustaría imprimir "Lunes 14 de marzo, 9 AM" si la hora corresponde a esta mañana 9 AM EDT y "Lunes 7 de marzo 9 AM" si la hora era 9 AM EST el pasado lunes.

¿Ojalá haya otra forma?

Editar : Primero pensé que "EDT" debería ser una zona horaria reconocida, pero "EDT" no es una zona horaria real, más como el estado de una zona horaria. Por ejemplo, no tendría ningún sentido pedirlo Time.utc(2011,1,1).in_time_zone("EDT"). Es un poco confuso, ya que "EST" es una zona horaria real, que se utiliza en algunos lugares que no utilizan el horario de verano y tienen (UTC-5) un año.

Marc-André Lafortune
fuente

Respuestas:

113

Rails tiene sus propios nombres. Véalos con:

rake time:zones:us

También puede ejecutar rake time:zones:allpara todas las zonas horarias. Para ver más tareas de rake relacionadas con la zona:rake -D time

Entonces, para convertir a EST, abastecimiento de DST automáticamente:

Time.now.in_time_zone("Eastern Time (US & Canada)")
Zabba
fuente
21
¿Cómo podría utilizar automáticamente la zona horaria para el usuario que accede a la aplicación web?
dmonopoly
La única forma que encontré fue con Javascript y luego devolviéndolo al servidor. (new Date()).getTimeZoneOffset(). Pero es bastante inconsistente, por lo que este tipo parece haber escrito el suyo: onlineaspect.com/2007/06/08/…
Duke
2
agregue automáticamente la zona horaria a todas las fechas de ActiveRecord - config.time_zone = 'Eastern Time (US & Canada)' - en config / application.rb
idrinkpabst
Actualización: el propietario de la solución JS vinculada apunta a una solución más nueva: pellepim.bitbucket.org/jstz
Miles
@dmonopoly puede establecer la zona horaria en la configuración de la aplicación config.time_zone = 'Wellington'y luego usar Time.current (que es equivalente a time.now pero usó la zona horaria que ha establecido)
Sean
114

Time#localtime le dará la hora en la zona horaria actual de la máquina que ejecuta el código:

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

Actualización: si desea conversar a zonas horarias específicas en lugar de su propia zona horaria, está en el camino correcto. Sin embargo, en lugar de preocuparse por EST vs EDT, simplemente pase en la zona horaria del este general; sabrá según el día si es EDT o 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
fuente
Eso es un comienzo. ¿Cómo puedo configurar la zona horaria actual (dado que ni siquiera estoy seguro de dónde se alojará la aplicación, el servidor podría estar en una zona horaria diferente a la que debería usarse)?
Marc-André Lafortune
6
El método "localtime" es genial, pero la zona horaria de la máquina que ejecuta el código no es tan útil como la zona horaria del usuario que accede a la aplicación web. (Como se menciona aquí: stackoverflow.com/questions/6003491/rails-3-user-timezones/… ) ¿Cómo podría obtener la zona horaria para el usuario que accede a la aplicación web?
dmonopoly
@daze Me imagino que podría configurar una opción para que sus usuarios elijan sus zonas horarias y luego usen el in_time_zonemétodo con su zona horaria.
Dylan Markow
1
Gracias, el método localtime es exactamente lo que necesitaba.
Bob
Time.now.localtimefunciona en una sesión normal de irb pero cuando intento ejecutarlo en una máquina que está en la zona horaria UTC, no funciona.
Ava
15

Es fácil configurarlo usando la zona local de su sistema, solo en su application.rb agregue esto

config.time_zone = Time.now.zone

Luego, los rieles deberían mostrarle marcas de tiempo en su hora local o puede usar algo como esta instrucción para obtener la hora local.

Post.created_at.localtime
jacr1614
fuente
15

En realidad, hay una gema agradable llamada local_timepor basecamp para hacer todo eso solo en el lado del cliente, creo:

https://github.com/basecamp/local_time

mahatmanich
fuente
Esto funciona mejor. Ya sabemos el tiempo almacenado, la forma de mostrarlo en el formato al usuario se hace mejor en el lado del cliente en mi opinión y esto lo hace.
Neeraj Shukla
1

No sé por qué, pero en mi caso no funciona de la forma sugerida anteriormente. Pero funciona así:

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

Por supuesto, necesita cambiar el offsetvalor al suyo.

Seybo Glaux
fuente
0

Si realmente lo está haciendo solo porque desea obtener la zona horaria del usuario, todo lo que tiene que hacer es cambiar su zona horaria en usted config/applications.rb.

Me gusta esto:

Rails, de forma predeterminada, guardará su registro de tiempo en UTC incluso si especifica la zona horaria actual.

config.time_zone = "Singapore"

Así que esto es todo lo que tienes que hacer y listo.

therealadrain
fuente