-
Type: Bug
-
Resolution: Fixed
-
Priority: Major - P3
-
Affects Version/s: None
-
Component/s: BSON
-
None
-
Fully Compatible
As of bson 4.8.0 `Time#to_f` is used to serialize Time, which is not sufficient and may lead into unexpected behaviour:
IEEE 754 double is not accurate enough to represent the exact number of nanoseconds since the Epoch.
Here's simple example:
time = Time.utc(2020, 4, 20, 23, 59, 59, Rational(999_999_999, 1000)) # => 2020-04-20 23:59:59 UTC Time.at(time.to_f).utc # => 2020-04-21 00:00:00 UTC
The problem can be seen on bson v4.8.0:
BSON::VERSION # => "4.8.0" time = Time.utc(2020, 4, 20, 23, 59, 59, Rational(999_999_999, 1000)) # => 2020-04-20 23:59:59 UTC time.to_r # => (1587427199999999999/1000000000) Time.from_bson(time.to_bson) # => 2020-04-21 00:00:00 UTC Time.from_bson(time.to_bson).to_r # => (1587427200/1)
Now, here's how bson-4.7.1 behaved:
BSON::VERSION
# => "4.7.1"
time = Time.utc(2020, 4, 20, 23, 59, 59, Rational(999_999_999, 1000))
# => 2020-04-20 23:59:59 UTC
time.to_r
# => (1587427199999999999/1000000000)
Time.from_bson(time.to_bson)
# => 2020-04-20 23:59:59 UTC
Time.from_bson(time.to_bson).to_r
# => (1587427199999/1000)
In other words we were losing some precision before, but at least we were in the same day. The problem shines in Rails environment, where one might write query like this:
SomeModel.where("created_at" => { "$gte" => date.beginning_of_day, "$lte" => date.end_of_day })
- is duplicated by
-
RUBY-2067 When serializing times to extended json, limit precision to milliseconds
- Closed
- is related to
-
PYTHON-1603 datetime microseconds are rounded instead of truncated
- Closed
-
RUBY-2151 BSON Time Objects
- Closed
-
DRIVERS-937 Require that sub-millisecond precision times are rounded down to nearest millisecond when serializing
- Backlog
- related to
-
RUBY-2216 GridFS incorrectly rounds sub-millisecond times
- Backlog
- links to