8
votes

Pourquoi cette requête Rails se comporte-t-elle différemment selon le fuseau horaire?

J'ai une requête à temps basée sur les rails qui a un comportement sensible délai impair, même si autant que je sache, j'utilise UTC. En un mot, ces requêtes donnent des réponses différentes: xxx pré>

où la DB contient en réalité un modèle créé en la dernière heure, et le nombre total de modèles est 280. Donc, seule la première requête est correct. p>

Cependant, dans Environnement.rb j'ai: p> xxx pré>

Le fuseau horaire système (comme indiqué par "date") est BST (qui est signalé par "date". GMT + 1) - Il s'agit donc d'une manière d'une manière utile d'être traitée comme UTC et de briser les requêtes. P>

Cela me fait toutes sortes de problèmes, car je dois paramétrer la requête qui passe à des moments différents à une action (qui sont ensuite converties à l'aide de temps.parse ()), et même si j'envoie dans UTC Times , ce «éteint d'une heure» DST DST Crops beaucoup. Même en utilisant '.gmtime ()' () 'ne semble pas toujours le réparer. P>

Évidemment, la différence est causée en quelque sorte par une conversion implicite quelque part à la BST étant traitée de manière incorrecte comme UTC, mais pourquoi? Ne roule pas les horodatails de l'UTC? Le fuseau horaire est-il au courant? J'utilise des rails 2.2.2 P>

Alors qu'est-ce qui se passe ici - et quel est le moyen sûr de programmer autour de lui? P>

Modifier, certaines informations supplémentaires pour montrer ce que font la classe DB et l'heure: P>

>> Model.find(:last).created_at
=> Tue, 11 Aug 2009 20:31:07 UTC +00:00
>> Time.now
=> Tue Aug 11 22:00:18 +0100 2009
>> Time.now.gmtime
=> Tue Aug 11 21:00:22 UTC 2009


0 commentaires

3 Réponses :


13
votes

La classe code> code> n'est pas directement consciente de votre fuseau horaire configuré. Rails 2.1 Ajout d'une bouquet de support de fuseau horaire, mais temps code> agira toujours sur votre fuseau horaire local. C'est pourquoi le temps renvoie une heure de BST.

Ce que vous voulez probablement, c'est interagir avec temps.zone code>. Vous pouvez appeler des méthodes à ce sujet comme vous le feriez la classe de temps elle-même, mais cela le retournera dans le fuseau horaire spécifié. P> xxx pré>

Une autre chose que vous devez faire attention à ce que vous devez faire attention. jamais faire des requêtes sur la base de données où vous comparez des temps, mais assurez-vous d'utiliser l'heure UTC (même si vous avez un fuseau horaire différent spécifié) car les rails stockent toujours UTC dans la base de données. P>

Item.all(:conditions => ["published_at <= ?", Time.now.utc])


3 commentaires

Intéressant ... est le temps.Utc a synonyme de temps.gmtime? Aussi, je reçois >> temps.zone => # >. Je pense que le problème est que, à ma façon de penser "Tue août 11 22:00:18 +0100 2009" et "Tue août 11 21:00:22 UTC 2009" se réfèrent au même temps logique. Je suppose que les rails / ruby ​​ignorent simplement le décalage lors de la construction du SQL.


Je crois que le temps # UTC n'est qu'un alias à temps # gmtime. En outre, le décalage de fuseau horaire est ignoré lorsqu'il s'agit d'un temps normal (temps.now) mais pris en compte lors de l'utilisation du temps.zone.now. Donc, mieux pour toujours utiliser le temps.Zone, alors vous ne devriez pas avoir à appeler "UTC" dessus.


Merci, cela aide beaucoup. Il n'est pas intuitif pour moi que cela fonctionne de cette façon, mais au moins, je comprends ce qui se passe maintenant. J'ai changé le code en conséquence et il semble avoir effacé la question. Une autre chose qui jetait mon code était que 1.Nears n'est pas uniformément divisible par 1.weeks comme je m'attendais à ce que ce soit ... Je faisais une boucle et que je reçois une erreur sans rapport mais similaire à cause de cela.



0
votes

Le fuseau horaire que vous devez définir est britannique, cela traitera automatiquement BST

Time.zone = 'UK'
Time.zone.now
 => Sun, 17 Oct 2010 02:09:54 BST +01:00


2 commentaires

Je crois que cela devrait maintenant être temps.zone = "London"


Oui cela serait maintenant à Londres



0
votes
start_date_format = DateTime.strptime(@start_date, date_format)
start_date_format_with_hour = 
DateTime.strptime((start_date_format.to_i + timezone_offset*60*60).to_s,'%s').strftime(date_format)

end_date_format = DateTime.strptime(@end_date, date_format)
end_date_format_with_hour = DateTime.strptime((end_date_format.to_i + timezone_offset*60*60).to_s,'%s').strftime(date_format)

@filters_date = "invoices.created_at >= ? AND invoices.created_at < ?", start_date_format_with_hour, end_date_format_with_hour

1 commentaires

Il suffit de laisser tomber un morceau de code est rarement utile. S'il vous plaît expliquer un peu ce que le code fait.