2009-03-11 6 views
6

J'ai une application de rails où je stocke created_at en tant que datetime (standard). Je suis en train de créer un formulaire de recherche et je trouve que je dois utiliser find_by_sql pour faire des sous-requêtes complexes. Le formulaire a une plage de dates (pas de temps) pour rechercher des éléments dans le champ created_at.Comment correctement convertir ou interroger la plage de dates pour Rails/MySQL DateTime Colonne

Le problème que je trouve que si je passe juste la chaîne de date pour la plage de requête ...

... status_changes.created_at between '2009-01-24' and '2009-03-12' ... 

Je reviens des documents qui ont une date created_at de 2009-01-23 17: 10:39 -0800 car il est stocké dans la base de données en tant que 2009-01-24 01:10:39 (UTC)

Comment puis-je résoudre ce problème afin que le résultat ne renvoie pas l'enregistrement en question?

Il semble que je soit besoin de convertir la plage de dates UTC à être spécifique ou dire à find_by_sql recherche en fonction de fuseau horaire au lieu de lire la colonne comme ... utc

Des preneurs?

John

Répondre

4

Je sais que cela est une question ancienne, mais en réponse à Rationalise la requête sur CONVERT_TZ:

À moins que les tables de fuseau horaire nommées mySQL ne soient chargées (ce qui est peu probable sur une installation vanille), vous devez entrer des fuseaux horaires comme décalage par rapport à l'UTC.

CONVERT_TZ(status_changes.created_at, '+00:00', '+08:00') between '2009-01-24' and '2009-03-12') 
+0

Merci Jordan. Je ne suis pas sûr de pouvoir le tester de sitôt, mais votre réponse semble plausible. – Streamline

1

MySQL a une fonction qui prend une CONVERT_TZ datetime et il convertit d'un fuseau horaire à l'autre. Vous pouvez créer votre requête pour convertir la valeur stockée (UTC) en votre fuseau horaire local (PST).

CONVERT_TZ(status_changes.created_at,'UTC',?) between ? and ?, 'PST, '2009-01-24', '2009-03-10' 
7

Si vous n'utilisez pas find_by_sql, mais plutôt d'utiliser un find avec une clause :conditions qui nous laissent Rails faire des substitutions, il convertit tout automatiquement.

Model.find :all, 
    :conditions => ["created_at between ? and ?", start_date, end_date] 

pire des cas, si Rails est confondu par les dates, vous pouvez les convertir en temps et il devrait jouer bien:

Model.find :all, 
    :conditions => ["created_at between ? and ?", 
        start_date.to_time, end_date.to_time] 
0

J'ai essayé la réponse de Ian, mais cela n'a pas vraiment fonctionné. Rails gère correctement le fuseau horaire lorsque les enregistrements sont sauvegardés et chargés, mais ne semble pas faire la même chose pour les paramètres de requête. Notez que l'application sur laquelle je travaille est dans Rails 2.1.1, donc les choses se sont peut-être améliorées depuis.

Avec un petit ajustement, j'ai réussi à faire fonctionner la solution de Ian: Obtenir la valeur du temps dans le fuseau horaire UTC en utilisant la méthode getutc, puis passer en paramètre. Cela ne devrait pas non plus causer de dommages dans les versions ultérieures de Rails qui peuvent gérer correctement la zone des paramètres de temps, puisque l'heure UTC n'est pas modifiée par getutc, juste le fuseau horaire.

0

Parce que Rails stocke les dates UTC dans la base de données vous devez utiliser la méthode utc sur Time ou DateTime

savoir

Model.find :all, 
    :conditions => ["created_at between ? and ?", start_date.utc, end_date.utc] 
+0

Voir http://marklunds.com/articles/one/402 pour plus d'informations – paulodeon

12

La façon ActiveRecord moderne de faire est:

Model.where(time_field: date1..date2) 
-1
Model.where(:from => "2012-01-01".to_date.."2012-06-30".to_date) 

a fonctionné pour moi (: à partir de la base de données est le champ de type 'date')

Questions connexes