Convertir UTC en heure locale dans Rails 3

95

J'ai du mal à convertir un UTC Timeou TimeWithZoneune heure locale dans Rails 3.

Say momentest une Timevariable en UTC (par exemple moment = Time.now.utc). Comment puis-je convertir momentmon fuseau horaire en prenant soin de l'heure d'été (c'est-à-dire en utilisant EST / EDT)?

Plus précisément, j'aimerais imprimer "Lundi 14 mars, 9h00" si l'heure correspond à ce matin à 9h00 HAE et "Lundi 7 mars 9h00" si l'heure était 9h00 HNE lundi dernier.

Espérons qu'il existe un autre moyen?

Edit : J'ai d'abord pensé que "EDT" devrait être un fuseau horaire reconnu, mais "EDT" n'est pas un fuseau horaire réel, plus comme l'état d'un fuseau horaire. Par exemple, cela n'aurait aucun sens de demander Time.utc(2011,1,1).in_time_zone("EDT"). C'est un peu déroutant, car "EST" est un fuseau horaire réel, utilisé dans quelques endroits qui n'utilisent pas l'heure d'été et qui durent (UTC-5) toute l'année.

Marc-André Lafortune
la source

Réponses:

113

Rails a ses propres noms. Découvrez-les avec:

rake time:zones:us

Vous pouvez également exécuter rake time:zones:allpour tous les fuseaux horaires. Pour voir plus de tâches de râteau liées à la zone:rake -D time

Donc, pour convertir en EST, la restauration automatique pour l'heure d'été:

Time.now.in_time_zone("Eastern Time (US & Canada)")
Zabba
la source
21
Comment pouvez-vous utiliser automatiquement le fuseau horaire pour l'utilisateur accédant à l'application Web?
dmonopoly
Le seul moyen que j'ai trouvé était d'utiliser Javascript, puis de le renvoyer au serveur. (new Date()).getTimeZoneOffset(). Mais c'est assez incohérent, donc ce gars semble avoir écrit le sien: onlineaspect.com/2007/06/08
Duke
2
ajouter automatiquement le fuseau horaire à toutes les heures de données ActiveRecord - config.time_zone = 'Eastern Time (US & Canada)' - dans config / application.rb
idrinkpabst
Mise à jour: le propriétaire de la solution JS liée pointe vers une solution plus récente: pellepim.bitbucket.org/jstz
Miles
@dmonopoly, vous pouvez définir le fuseau horaire dans la configuration de l'application config.time_zone = 'Wellington', puis utiliser Time.current (qui est équivalent à time.now mais a utilisé le fuseau horaire que vous avez défini)
Sean
115

Time#localtime vous donnera l'heure dans le fuseau horaire actuel de la machine exécutant le code:

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

Mise à jour: si vous souhaitez convertir vers des fuseaux horaires spécifiques plutôt que vers votre propre fuseau horaire, vous êtes sur la bonne voie. Cependant, au lieu de vous soucier de EST vs EDT, passez simplement dans le fuseau horaire général de l'Est - il saura en fonction du jour s'il est EDT ou 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
la source
C'est un début. Comment puis-je définir le fuseau horaire actuel (puisque je ne suis même pas sûr de l'endroit où l'application sera hébergée, le serveur pourrait être dans un fuseau horaire différent de celui qui devrait être utilisé).
Marc-André Lafortune
6
La méthode "localtime" est cool, mais le fuseau horaire de la machine exécutant le code n'est pas aussi utile que le fuseau horaire de l'utilisateur accédant à l'application Web. (Comme mentionné ici: stackoverflow.com/questions/6003491/rails-3-user-timezones/… ) Comment pouvez-vous obtenir le fuseau horaire de l'utilisateur accédant à l'application Web?
dmonopoly
@daze J'imagine que vous pourriez configurer une option permettant à vos utilisateurs de choisir leur fuseau horaire, puis utiliser la in_time_zoneméthode avec leur fuseau horaire.
Dylan Markow
1
Merci, la méthode localtime est exactement ce dont j'avais besoin.
Bob
Time.now.localtimefonctionne sur une session irb normale mais lorsque j'essaye de l'exécuter sur une machine qui est dans le fuseau horaire UTC, cela ne fonctionne pas.
Ava le
15

Il est facile de le configurer en utilisant la zone locale de votre système, juste dans votre application.rb ajoutez ceci

config.time_zone = Time.now.zone

Ensuite, les rails devraient vous montrer les horodatages dans votre heure locale ou vous pouvez utiliser quelque chose comme cette instruction pour obtenir l'heure locale

Post.created_at.localtime
jacr1614
la source
15

Il y a en fait un joli Gem appelé local_timepar basecamp pour faire tout cela du côté client uniquement, je crois:

https://github.com/basecamp/local_time

mahatmanich
la source
Cela fonctionne le mieux. Nous connaissons déjà l'heure stockée, la manière de l'afficher dans le format à l'utilisateur est mieux faite du côté client à mon avis et cela le fait.
Neeraj Shukla
1

Je ne sais pas pourquoi, mais dans mon cas, cela ne fonctionne pas comme suggéré précédemment. Mais cela fonctionne comme ceci:

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

Bien sûr, vous devez changer la offsetvaleur de la vôtre.

Seybo Glaux
la source
0

Si vous le faites simplement parce que vous souhaitez obtenir le fuseau horaire de l'utilisateur, tout ce que vous avez à faire est de changer votre fuseau horaire en vous config/applications.rb.

Comme ça:

Les rails, par défaut, enregistreront votre enregistrement de temps en UTC même si vous spécifiez le fuseau horaire actuel.

config.time_zone = "Singapore"

C'est donc tout ce que vous avez à faire et vous êtes prêt à partir.

therealadrain
la source