Based on your comments I think that the main problem is in the conversion of the microseconds-precise time to Float. Float (even though in ruby internally a Double) does not have enough accuracy to fully represent all dates / times with microseconds precision, as is documented in the Time class (although they speak about “nanoseconds”, interestingly). Such conversion then only tries to find the nearest possible representation in Float. Rounding the resulting float number back to 6 digits may work but I’m not sure it’s guaranteed to always work…
Suppose that the real time stored in DB is 2020-08-07 11:30:28.593491. As you’ve noticed, this converts to Float imprecisely:
>> Time.parse('2020-08-07 11:30:28.593491').to_f
=> 1596792628.5934908
The guaranteed method would be to use a Rational number instead, i.e. to_r:
>> Time.parse('2020-08-07 11:30:28.593491').to_r
=> (1596792628593491/1000000)
To reconstruct the Time back from the rational number, you can use Time.at:
>> Time.at(Rational(1596792628593491, 1000000)).usec
=> 593491
Note that the microseconds are fully preserved here.
So, storing a created_at time precisely and using it later to search for a record involves using a Rational number variable instead of 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
An alternative approach might be to store both the integer seconds since Epoch (User.first.created_at.to_i) and the nanoseconds fraction (User.first.created_at.usec) separately in two variables. They can be the used in Time.at, too, to reconstruct the time back.
As a sidenote, this has also been discussed in a Rails issue with a similar conclusion.