diff --git a/lib/mongo/util/bson.rb b/lib/mongo/util/bson.rb index 023136c..241e02e 100644 --- a/lib/mongo/util/bson.rb +++ b/lib/mongo/util/bson.rb @@ -248,8 +248,10 @@ class BSON end def deserialize_date_data(buf) - millisecs = buf.get_long() - Time.at(millisecs.to_f / 1000.0).utc # at() takes fractional seconds + unsigned = buf.get_long() + # see note for deserialize_number_long_data below + milliseconds = unsigned >= 2 ** 64 / 2 ? unsigned - 2**64 : unsigned + Time.at(milliseconds.to_f / 1000.0).utc # at() takes fractional seconds end def deserialize_boolean_data(buf) diff --git a/test/test_bson.rb b/test/test_bson.rb index 30af1b1..a947f3c 100644 --- a/test/test_bson.rb +++ b/test/test_bson.rb @@ -124,6 +124,14 @@ class BSONTest < Test::Unit::TestCase assert doc2['date'].utc? end + def test_date_before_epoch + doc = {'date' => Time.utc(1600)} + @b.serialize(doc) + doc2 = @b.deserialize + # Mongo only stores up to the millisecond + assert_in_delta doc['date'], doc2['date'], 0.001 + end + def test_dbref oid = ObjectID.new doc = {} diff --git a/test/test_collection.rb b/test/test_collection.rb index 79e5e18..0180652 100644 --- a/test/test_collection.rb +++ b/test/test_collection.rb @@ -182,6 +182,11 @@ class TestCollection < Test::Unit::TestCase assert c.closed? end + def test_saving_dates_pre_epoch + @@test.save({'date' => Time.utc(1600)}) + assert_in_delta Time.utc(1600), @@test.find_one()["date"], 0.001 + end + def test_save_symbol_find_string @@test.save(:foo => :mike)