JamesNK / Newtonsoft.Json.Bson

Json.NET BSON adds support for reading and writing BSON to Json.NET
MIT License
55 stars 23 forks source link

Unable to handle high precision of DateTime and DateTimeOffset #25

Closed glennawatson closed 5 years ago

glennawatson commented 5 years ago

Do you want to request a feature or report a bug? bug The precision of the DateTime and DateTimeOffset serialization seems to loose precision while in BSON.

What is the current behavior?

When I store and retrieve a DateTime or a DateTimeOffset object, I expect it to store the microseconds all the way to 7 decimal places. Otherwise this causes issues in our production systems.

If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem

Here's a test method to demonstrate the point. If you put a breakpoint on the "Assert", you can see the two timestamps are different.

    public class ItemData
    {
        public DateTime CreationTime { get; set; }
        public DateTime? UpdateTime { get; set; }
        public DateTimeOffset? TimeSinceLastPublish { get; set; }
        public DateTimeOffset DueDate { get; set; }
    }

        [Test]
        public void Serialize()
        {
            ItemData c = new ItemData
            {
                CreationTime = DateTime.Now,
                UpdateTime = null,
                DueDate = DateTimeOffset.Now + TimeSpan.FromHours(2),
                TimeSinceLastPublish = null,
            };

            MemoryStream ms = new MemoryStream();
            JsonSerializer serializer = new JsonSerializer();

            // serialize product to BSON
            BsonDataWriter writer = new BsonDataWriter(ms);
            serializer.Serialize(writer, c);

            ms.Position = 0;
            BsonDataReader reader = new BsonDataReader(ms);

            ItemData test = serializer.Deserialize<ItemData>(reader);

            Assert.AreEqual(c.UpdateTime, test.UpdateTime);
            Assert.AreEqual(c.DueDate, test.DueDate);
        }

What is the expected behavior?

Both timestamp results should be exactly the same up to the microseconds (7 decimal places)

What is the actual behavior? For example in the above unit test, it only keeps 3 digits of the precision. This is not an issue with the standard JSON processor.

Message:   Expected: 2018-12-26 18:59:19.2126799-08:00
  But was:  2018-12-26 18:59:19.212-08:00

What is the motivation / use case for changing the behavior?

We are getting a number of bugs based on resolution of DateTime in our product Akavache https://github.com/reactiveui/akavache.

We came up with a hacky solution in the following PR https://github.com/reactiveui/Akavache/pull/448 but ideally would want a proper fix. Our fix would likely not be compatible with other BSON reader/writers since we use the .NET DateTime tick.

Which versions of Newtonsoft.Json.BSON are you using? 1.0.2 Windows 10 C# Framework .Net Core 2.1

JamesNK commented 5 years ago

This isn't a bug. The BSON spec stores dates to a millisecond precision.

What you could do is have a JsonConverter that writes dates as a BSON string instead. It is less efficient but you wouldn't lose precision.

glennawatson commented 5 years ago

Thanks @JamesNK -- makes sense, we will keep the solution we have then.