Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

263
Views
Rails / MySQL: ¿Cómo consultar un registro por su marca de tiempo completa 'created_at'?

Quiero poder encontrar un registro de User por su marca de tiempo created_at (que en este caso es: 2020-08-07 11:30:28.5934908 ).

Pero el resultado es este:

 User.where(created_at: '2020-08-07 11:30:28.5934908').first => nil

La razón por la que este registro de usuario (existente) no se encuentra parece hacerse evidente en la consulta de MySQL que generó Rails:

User Load (0.4ms) SELECT `users`.* FROM `users` WHERE `users`.`created_at` = '2020-08-07 11:30:28.593490' ORDER BY `users`.`id` ASC LIMIT 1

... donde, por alguna razón, el último dígito 8 se elimina de la marca de tiempo 2020-08-07 11:30:28.5934908 utilizada en la consulta MySQL.

¿Cuál es el problema aquí? ¿Rails acorta la marca de tiempo en la consulta? ¿O MySQL hace esto? ¿Cómo puedo solucionar esto?

over 4 years ago · Santiago Trujillo
3 answers
Answer question

0

Según sus comentarios, creo que el principal problema está en la conversión del tiempo preciso en microsegundos a Float. Float (aunque en Ruby internamente es un Double) no tiene suficiente precisión para representar completamente todas las fechas/horas con una precisión de microsegundos, como se documenta en la clase Time (aunque curiosamente hablan de "nanosegundos"). Tal conversión solo intenta encontrar la representación más cercana posible en Float. Redondear el número flotante resultante a 6 dígitos puede funcionar, pero no estoy seguro de que funcione siempre...

Suponga que el tiempo real almacenado en DB es 2020-08-07 11:30:28.593491 . Como habrás notado, esto se convierte en Float de forma imprecisa:

 >> Time.parse('2020-08-07 11:30:28.593491').to_f => 1596792628.5934908

El método garantizado sería utilizar un número racional en su lugar, es decir, to_r :

 >> Time.parse('2020-08-07 11:30:28.593491').to_r => (1596792628593491/1000000)

Para reconstruir el Tiempo a partir del número racional, puede usar Time.at :

 >> Time.at(Rational(1596792628593491, 1000000)).usec => 593491

Tenga en cuenta que los microsegundos se conservan completamente aquí.

Por lo tanto, almacenar un created_at time con precisión y usarlo más tarde para buscar un registro implica usar una variable de número racional en lugar de Float:

 >> user_created_at = User.first.created_at.to_r => (1596792628593491/1000000) >> User.where(created_at: Time.at(user_created_at)).first == User.first => true

Un enfoque alternativo podría ser almacenar los segundos enteros desde Epoch ( User.first.created_at.to_i ) y la fracción de nanosegundos ( User.first.created_at.usec ) por separado en dos variables. También se pueden usar en Time.at para reconstruir el tiempo atrás.

Como nota al margen, esto también se ha discutido en una edición de Rails con una conclusión similar.

over 4 years ago · Santiago Trujillo Report

0

Esta no es una respuesta directa a su pregunta, sino una especie de solución. Podría consultar la columna created_at en un delta de tiempo muy pequeño como este.

 User.where(created_at: '2020-08-07 11:30:28.593490'...'2020-08-07 11:30:28.593491')
over 4 years ago · Santiago Trujillo Report

0

Según el comentario de @BoraMa (¡gracias!), MySQL created_at timestamp debe tener solo 6 dígitos. Por lo tanto, la consulta de trabajo se vería así:

 User.where(created_at: '2020-08-07 11:30:28.5934908'.round(6)).first
over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!