12
votes

Rails date du temps et des luminaires

J'ai eu le luminaire suivant:

p> xxx pré>

J'ai essayé la demande suivante: p> xxx pré>

réponse: P>

Links.where("Date(created_at) = ?", Date.today)


2 commentaires

Laissez-moi être plus claire, ma question est la suivante: pourquoi ma requête fonctionne-t-elle lorsque je mets .to_date dans le luminaire et non quand je ne le mettez pas.


Je envisagerais de passer à des valeurs prévisibles au lieu de dynamique. Quelques exemples: Github.com/Rails/Rails/blob / ...


4 Réponses :


1
votes

Je spéculerais que c'est en raison de la différence de temps entre lorsque le luminaire a été créé et lorsque la requête a été appelée.

Il y a 5 jours + 0.00025 MS> Il y a 5 jours

Je ne suis pas sûr de quelle est la précision pour les denttimes, mais c'est la seule possibilité que je puisse penser. Lorsque vous l'avez converti sur une date, vous avez supprimé les informations de temps étranger et rendu les deux égaux.


2 commentaires

Ce n'est pas un problème de fuseau horaire depuis les derniers liens d'exemple.where ("date (créée_at) =?", Date.today) fonctionne bien


Je ne dis pas que c'est un problème de fuseau horaire. Il y a un petit délai entre lorsque la dateTime a été insérée comme un luminaire (nous dirons 12/05/2010 12: 00: 00.0000) vs quand il était comparé (12/05/2010 12: 00: 00.0005). C'est la différence de temps que je parlais.



0
votes

La différence entre vos deux cas est que lorsque vous appelez to_date , vous perdez la valeur de l'heure, et le résultat final est donc un créé_at horodatage défini sur minuit de cette journée. Vous évitez également la traduction du fuseau horaire de timewithzone . Franchement, nous n'avons pas assez d'informations pour conjecturer ce qui se passe au-delà de cela. Pour voir exactement ce qui se passe, votre meilleur pari est de regarder les requêtes de votre log / test.log - Si vous ne voyez pas les requêtes, vous pouvez les activer en réglant log_level à : débogage dans config / environnements / test.rb . N'hésitez pas à copier et collez les requêtes SQL ici.

@ibz soulève également un bon point: en utilisant .To_s (: db) est une bonne idée, car le fichier de fixation ERB est évalué à une chaîne, puis lisez comme YAML, ce qui peut provoquer Quelques problèmes avec la coulée de valeurs aux chaînes. Utilisation de .TO_S (: dB) corrigera ce problème, mais pour éviter cela à l'avenir (et gagnez un tas de fonctionnalités supplémentaires), je recommanderais d'utiliser usine_girl au lieu de luminaires.

Ces types de problèmes sont courants lorsqu'ils traitent des dates de test - en particulier si vous essayez d'interroger par l'égalité de deux dates ou des horodatages. Pour résoudre ces problèmes, je recommande de choisir des dates / temps fixes arbitraires dans le passé au lieu de faire 5.days.ago ou si vous avez besoin d'utiliser des dates / temps dynamiques, utilisez le gemme TIMECOP pour contrôler / geler l'heure dans vos tests.


1 commentaires

Ma question était plus "pourquoi travaille-t-elle" que "pourquoi ne travaille-t-il pas"



23
votes

Dans les appareils, vous devez avoir:

Links.where("created_at = ?", ...


8 commentaires

to_s (: dB) est le moyen d'aller ici, je me suis dirigé moi-même.


5.day.ago == 5.day.ago.to_date => Faux est clair pour moi, mais ce n'est pas le problème ici, mes points étaient qu'il fonctionne quand je mets .to_date


Dans votre luminaire, vous casserez 5day.ago (de type ActiveSupport :: timewithzone ) à date . Tout ce qui est sauvegardé dans la base de données, diffuse ultérieurement dans date dans votre requête avec la date (créée_at) = ... . date ne se soucie pas de l'heure ou du fuseau horaire de votre application Rails. Infirmer rails Console et comparez les résultats que vous avez entré 5.day.ago , 5.day.ago.to_date , 5 .day.ago.to_s (: dB) avoir quelque chose empirique à regarder. Vous verrez différentes valeurs .


Encore une fois, il est clair pour moi que la date et l'heure ou DateTime ont des valeurs différentes. Mais ici "Created_AT" est une date d'heure, que je jette à ce jour, en ignorant ainsi les attributs de temps. Donc, je devrais être capable de comparer avec une date


Utilisation de .TO_Date dans votre appareil Vous enregistrez une représentation d'une date obj dans la base de données. Plus tard, la requête obtient cette représentation d'un objet de date et de la comparer avec succès avec 5.day.ago.to_date qui est à nouveau un objet de date.


Ce n'est pas vrai - la comparaison se produit dans la base de données, de sorte quel type de rails d'objets les représente est hors de propos. En outre, en utilisant la date () dans un clause ne modifie pas le type d'objet Rails retournements, car un clause ne change pas Les valeurs renvoyées par la clause .


Utilisation de .TO_Date dans les luminaires est pertinent sur la manière dont les données sont enregistrées dans la base de données, alors comment elle est ultérieure par rapport à la base de données. Je suis d'accord avec vous, en utilisant la date () dans une clause où la clause ne modifie pas le type de retours d'objet Revers.


to_s (: dB) est le plus important des informations ici!



1
votes

créé_at est un champ DateTime et 5.days.ago renvoie efficacement un objet DateTime. Cet objet aura le même temps défini comme au moment où il est appelé, par exemple. Sam, 23 août 2014 10:30: 37 , et c'est ce qui est mis dans la base de données.

Dans votre cas de défaillance, lorsque vous appelez 5.day.ago à nouveau plus tard (même dans la même exécution), le nouveau temps sera probablement différent, par exemple. Sam, 23 août 2014 10:30: 38 . Par conséquent, vous pouvez voir qu'ils ne sont pas égaux et vous n'obtiendrez pas de matchs.

Lorsque vous appendez .to_date , vous obtenez un objet de date, qui n'a pas de composant temporel. Lorsque cela est persisté à la base de données ou utilisé dans votre requête, il sera toujours considéré comme une période de 00:00:00 (minuit). Par conséquent, la date et l'heure correspondront, (tant que vous n'essayez pas d'exécuter les appareils et la requête exactement à minuit)


0 commentaires