48 votes

Comment afficher l'heure dans le fuseau horaire de l'utilisateur ?

J'utilise rails 3.0.5 et j'ai stocké created_at et updated_at en UTC. Maintenant, je veux afficher l'heure de created_at dans le fuseau horaire des utilisateurs. Je pense qu'il est possible de choisir le fuseau horaire de l'utilisateur à partir du navigateur, puis de convertir l'heure dans le fuseau horaire de l'utilisateur.

Je suis sûr que rails aura une gemme/un plugin pour s'occuper de quelque chose comme ça. Y a-t-il quelque chose ?

1 votes

0 votes

Je donnerais bien une réponse régulière avec des détails, mais je suis à court de temps. Le lien ci-dessus devrait cependant vous aider.

1 votes

@Ben : Je vois ce que vous avez fait là ;)

70voto

Simone Carletti Points 77653

Par défaut, Rails convertit chaque date en UTC avant de stocker la valeur dans la base de données. Cela signifie que, quel que soit le fuseau horaire du serveur, vous aurez toujours des dates UTC dans votre base de données.

Pour convertir les dates dans le fuseau horaire de votre utilisateur, vous avez essentiellement deux possibilités :

  1. approche côté serveur
  2. approche client

Approche côté serveur

Si votre site permet l'enregistrement, vous pouvez enregistrer le fuseau horaire de l'utilisateur comme préférence de l'utilisateur. Dans la table des utilisateurs, enregistrez le fuseau horaire de l'utilisateur. Créez ensuite une aide personnalisée que vous pourrez utiliser pour formater n'importe quelle date/heure dans le fuseau horaire approprié à l'aide de l'attribut in_time_zone méthode.

> t = Time.current
# => Mon, 23 Dec 2013 18:25:55 UTC +00:00 
> t.zone
# => "UTC" 
> t.in_time_zone("CET")
# => Mon, 23 Dec 2013 19:25:55 CET +01:00 

Votre aide peut ressembler à

def format_time(time, timezone)
  time.in_time_zone(timezone)
end

Normalement, j'aime aussi sortir un format standard, en utilisant la fonction I18n.l aide

def format_time(time, timezone)
  I18n.l time.to_time.in_time_zone(timezone), format: :long
end

Approche côté client

Si votre site n'a pas d'enregistrement ou si vous ne voulez pas demander à vos utilisateurs leur fuseau horaire ou si vous voulez simplement utiliser le fuseau horaire du système de l'utilisateur, alors vous pouvez utiliser JavaScript.

Je vous suggère de créer une aide personnalisée qui s'imprimera à chaque fois de manière appropriée afin que vous puissiez créer une fonction JavaScript générique pour convertir les valeurs.

def format_time(time, timezone)
  time = time.to_time
  content_tag(:span, I18n.l(time, format: :long), data: { timezone: timezone, time: time.iso8601 })
end

Maintenant, créez une fonction JavaScript qui est exécutée lors du chargement du DOM et qui sélectionnera toutes les balises HTML avec le code suivant data-time attribut. Bouclez-les et mettez à jour la valeur à l'intérieur de l'attribut span avec l'heure correcte dans le fuseau horaire donné.

Un exemple simple de jQuery serait

$(function() {
    $("span[data-time]").each(function() {
        // get the value from data-time and format according to data-timezone
        // write the content back into the span tag
    });
});

Je ne vais pas publier le code complet ici, car il existe de nombreux formateurs de temps JavaScript disponibles avec une simple recherche. Voici quelques solutions possibles

23voto

Strika Points 536

Basecamp dispose d'une belle gemme appelée local_time pour le rendu côté client. https://github.com/basecamp/local_time . Il est idéal pour les applications où l'utilisateur n'est pas connecté et il est compatible avec la mise en cache.

0 votes

Notez que cette gemme ne supporte pas l'i18n.

1 votes

Ils ont ajouté le support I18n en août 2017, dans la version 2.0.0.

0 votes

C'est parfait, et cela résout 95% des cas d'utilisation. merci pour le partage !

9voto

John Naegle Points 2180

Vous pouvez l'ajouter au contrôleur de votre application pour convertir toutes les heures dans le fuseau horaire de l'utilisateur :

class ApplicationController < ActionController::Base

  around_filter :user_time_zone, :if => :current_user
  def user_time_zone(&block)
    Time.use_zone(current_user.timezone_name, &block)
  end
end

Il suffit de capturer le fuseau horaire de l'utilisateur.

0 votes

Merci beaucoup ! Si vous voulez utiliser le fuseau horaire du serveur, changez simplement current_user.timezone_name a Rails.application.config.time_zone .

3voto

Richard Luck Points 427

En supposant que la valeur que vous souhaitez afficher provient de la base de données, :ie started_at et est (comme par défaut) stocké en UTC.

Si vous avez le fuseau horaire de l'utilisateur comme décalage, vous pouvez également localiser l'heure en faisant :

started_at.in_time_zone(-2)
=> Mon, 24 Feb 2014 23:07:56 GST -02:00

Qui peuvent ensuite être broyés de toutes sortes de façons pour obtenir les pièces que vous voulez :

started_at.in_time_zone(-2).yesterday
=> Sun, 23 Feb 2014 23:07:56 GST -02:00

started_at.in_time_zone(-2) + 3.days
=> Thu, 27 Feb 2014 23:07:56 GST -02:00

1voto

Trip Points 9846

http://api.rubyonrails.org/classes/Time.html#method-c-use_zone

C'est ce que vous recherchez :

Time.use_zone(@user.timezone) do
  blah blah blah
end

1 votes

Vous devez permettre à votre utilisateur de choisir son fuseau horaire. Je suppose que vous pouvez "renifler" ce genre de choses, mais il est préférable de leur demander, car la plupart du temps, les gens gèrent des actifs depuis d'autres fuseaux horaires que ceux dans lesquels ils vivent. Donc @user est votre utilisateur, et le fuseau horaire est un attribut que vous lui permettez de mettre à jour dans son profil. Ensuite, vous utilisez la méthode use_zone pour instancier cette zone. Sinon, vous pouvez simplement mettre à jour votre environnement pour sauvegarder tous les fuseaux horaires :local

0 votes

La question a été formulée différemment. Forcer l'utilisateur à remplir des formulaires dont tout le monde est capable à partir de manuels.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X