Nous construisons une application Rails qui doit afficher des dates (et plus important encore, les calculer) dans plusieurs fuseaux fusionnées.
Quelqu'un peut-il me diriger vers comment travailler avec les horaires d'utilisation des rails 2.3 (.5 ou .8 ) p>
L'article le plus inclusifique que j'ai vu détailler la manière dont les zones de temps d'utilisateur sont censées fonctionner sont ici: http://wiki.rubyonrails.org/howtos/time-zones ... Bien que cela ne soit pas clair lorsque cela a été écrit ou pour quelle version des rails. Spécifiquement, il stipule que: p>
"TIME.ZONE - Le fuseau horaire réellement utilisé à des fins d'affichage. Ceci peut être réglé manuellement pour remplacer config.time_zone sur une base de demande." P>
clés termes étant "affichage" et "par requête". p>
localement sur ma machine, c'est vrai. Cependant, sur la production, ni ne sont vraies. La définition du temps.Zone persiste au-delà de la fin de la demande (à toutes les demandes suivantes) et affecte également la manière dont AR enregistre à la base de données (traitant essentiellement n'importe quelle date, comme s'il était déjà en UCC, même si ce n'est pas), ce qui sauve des valeurs complètement inappropriées. . P>
Nous gérons Ruby Enterprise Edition sur la production avec passager. Si tel est mon problème, devons-nous passer à Jruby ou autre chose? P>
Pour illustrer le problème, je pose actuellement les actions suivantes dans mon applicationController: P>
Processing ApplicationController#test (for 98.202.196.203 at 2010-12-24 22:15:50) [GET] TIME.ZONE#<ActiveSupport::TimeZone:0x2c57a68 @tzinfo=#<TZInfo::DataTimezone: Etc/UTC>, @name="UTC", @utc_offset=0> nil Fri Dec 24 22:15:50 UTC 2010 Fri Dec 24 22:00:00 UTC 2010 Fri Dec 24 22:00:00 UTC 2010 Fri, 24 Dec 2010 22:00:00 UTC +00:00 Fri Dec 24 22:00:00 UTC 2010 Fri, 24 Dec 2010 22:00:00 UTC +00:00 Completed in 21ms (View: 0, DB: 4) | 200 OK [http://www.dealsthatmatter.com/test] Processing ApplicationController#test2 (for 98.202.196.203 at 2010-12-24 22:15:53) [GET] TIME.ZONE#<ActiveSupport::TimeZone:0x2c580a8 @tzinfo=#<TZInfo::DataTimezone: America/Denver>, @name="Mountain Time (US & Canada)", @utc_offset=-25200> nil Completed in 143ms (View: 1, DB: 3) | 200 OK [http://www.dealsthatmatter.com/test2] Processing ApplicationController#test (for 98.202.196.203 at 2010-12-24 22:15:59) [GET] TIME.ZONE#<ActiveSupport::TimeZone:0x2c580a8 @tzinfo=#<TZInfo::DataTimezone: America/Denver>, @name="Mountain Time (US & Canada)", @utc_offset=-25200> nil Fri Dec 24 22:15:59 UTC 2010 Fri Dec 24 22:00:00 UTC 2010 Fri Dec 24 22:00:00 UTC 2010 Fri, 24 Dec 2010 15:00:00 MST -07:00 Fri Dec 24 22:00:00 UTC 2010 Fri, 24 Dec 2010 15:00:00 MST -07:00 Completed in 20ms (View: 0, DB: 4) | 200 OK [http://www.dealsthatmatter.com/test] Processing ApplicationController#test3 (for 98.202.196.203 at 2010-12-24 22:16:03) [GET] TIME.ZONE#<ActiveSupport::TimeZone:0x2c57a68 @tzinfo=#<TZInfo::DataTimezone: Etc/UTC>, @name="UTC", @utc_offset=0> nil Completed in 17ms (View: 0, DB: 2) | 200 OK [http://www.dealsthatmatter.com/test3] Processing ApplicationController#test (for 98.202.196.203 at 2010-12-24 22:16:04) [GET] TIME.ZONE#<ActiveSupport::TimeZone:0x2c57a68 @tzinfo=#<TZInfo::DataTimezone: Etc/UTC>, @name="UTC", @utc_offset=0> nil Fri Dec 24 22:16:05 UTC 2010 Fri Dec 24 22:00:00 UTC 2010 Fri Dec 24 22:00:00 UTC 2010 Fri, 24 Dec 2010 22:00:00 UTC +00:00 Fri Dec 24 22:00:00 UTC 2010 Fri, 24 Dec 2010 22:00:00 UTC +00:00 Completed in 151ms (View: 0, DB: 4) | 200 OK [http://www.dealsthatmatter.com/test]
3 Réponses :
J'ai eu ce problème lorsque je construisais un système de billetterie de support. Ma solution était la suivante. P>
Définissez le fuseau horaire de DateTime SQL et Activerecord sur UTC. P>
Définissez le format de votre temps souhaité dans la configuration de votre application. P>
Faites une classe CSS pour la façon dont vous souhaitez que le CSS de votre date de regarder. Faire le nom unique. PAR EXEMPLE. Utcdate p>
Écrire JavaScript pour rechercher la page pour les classes de date nommées DOM (UTCDate ci-dessus). Étant donné que JavaScript est exécuté par l'utilisateur final, il remplacera la valeur avec ce que la machine locale est réglée sur. Dans le cas où vous avez une erreur d'analyse, quittez l'heure en UTC. Regardez ici pour JavaScript pertinent P>
L'avantage de cette solution est votre application ne dispose pas d'un sélecteur de fuseau horaire stupide comme tant de forums. Il diminue également la charge de la charge du serveur et la taille de la base de code (puisque vous n'avez pas à stocker ou gérer aucune information sur les zones de temps de client) pour gérer une tâche importante mais difficile. P>
Après une recherche exhaustive, il est maintenant complètement clair que le temps.Zone est cassé dans la plupart des versions des rails (y compris 2.3 et 3). Cette fonctionnalité utilise un hachage de fil central pour stocker la valeur définie (qui est censé être du fil de sécurité, et n'est pas) et finit par modifier le comportement pour toutes les demandes suivantes. De plus, contrairement à la documentation, le réglage du temps.ZONE modifie le comportement ActiveRecord et enregistre les temps de date dans la nouvelle zone, au lieu de celui spécifié dans la configuration (qui est généralement UTC).
jusqu'à ce que les rails obtiennent cela, nous avons choisi de travailler avec Timezones manuellement, qui peuvent être accessibles via la méthode par défaut non documentée: P>
module ActiveSupport #:nodoc:
module CoreExtensions #:nodoc:
module Time #:nodoc:
module ZoneCalculations
def self.included(base) #:nodoc:
base.class_eval do
alias_method_chain :change, :zone
end
end
def change_zone(new_zone)
new_zone = ::Time.__send__(:get_zone, new_zone)
return self if new_zone.name == zone
new_zone.local(year,month,day,hour,min,sec,usec)
end
def change_with_zone(options)
result = change_without_zone(options)
options[:zone] ? result.change_zone(options[:zone]) : result
end
end
end
end
class TimeWithZone
def change_zone(new_zone)
time.change_zone(new_zone)
end
def change(options)
time.change(options)
end
end
end
class Time
include ActiveSupport::CoreExtensions::Time::ZoneCalculations
end
Convenu - Timezones étant cassé dans des rails 2.3. * M'a mordu sur le cul plus d'une fois
Vous avez raison dans ce rails ne réinitialise pas automatiquement le fuseau horaire par demande. L'auteur Wiki donne un exemple dans lequel le fuseau horaire est défini dans un filtre avant, il ne subit donc jamais le problème des zones de temps "fuites" entre les demandes (car le fuseau horaire est configuré correctement avant la demande). L'exemple utilisé dans la documentation RDOC pour Changer le fuseau horaire ne demande pas local, il est en fil local. Les rails stockent le fuseau horaire sélectionné dans le thread de courant (voir Je pense que la bonne façon d'utiliser des fuseaux horaires dans votre scénario consiste à utiliser Timezone.zone = code> est similaire. Je pense donc que c'est un problème de documentation. fil.current. [: Time_zone] code>), pas dans la demande actuelle. Comme le même thread gère plusieurs demandes, les modifications apportées au temps.Zone sont persistantes entre les demandes. P> temps.utilisateur code >: P> def my_action
Time.zone # 'UTC'
Time.use_zone('Mountain Time (US & Canada)') do
Time.zone # 'Mountain Time (US & Canada)'
end
Time.zone # 'UTC'
end
C'est la bonne réponse. Et si vous souhaitez envelopper une action complète des rails dans un fuseau horaire, utilisez un roturel autour de un fichier avant_filter.