1

Closed

DateTimes are not being deserialized correctly

description

Hi,

When using BSON this library does not deserialize UTC DateTimes correctly.

The problem is specifically with the combination of BSON , Daylight Savings Times, and UTC dates.
When Daylight Savings is active (Summer time), the library incorrectly adds another hour to the UTC times.
Since the DST changeover on Sunday our Application is now broken.

I have compared this behaving with the MongoDB BSON serializer, and its behavior is correct.

Please see the code below.

Kind Regards,
Gordon



using System;
namespace DST
{
class Program
{  
    static void Main()
    {
        Console.SetWindowSize(80, 50);

        var beforeDst = new DateTime(2013, 2, 01, 12, 0, 0, DateTimeKind.Utc);
        var afterDst = new DateTime(2013, 4, 01, 12, 0, 0, DateTimeKind.Utc);

        Run(new JsonNetSerializer(), "Before Daylight Savings Time Changeover", beforeDst);
        Run(new JsonNetSerializer(), "After Daylight Savings Time Changeover", afterDst);

        Console.WriteLine("*******************************************************************************");
        Console.WriteLine(Environment.NewLine + Environment.NewLine + Environment.NewLine);

        Run(new MongoDbSerializer(), "Before Daylight Savings Time Changeover", beforeDst);
        Run(new MongoDbSerializer(), "After Daylight Savings Time Changeover", afterDst);

        Console.ReadLine();
    }

    private static void Run(ISerializer serializer, string title, DateTime dateToUse)
    { 
        var originalMessage = new Message { SentAt = dateToUse };
        var serializedBytes = serializer.Serialize(originalMessage);
        var deserializedMessage = serializer.Deserialize<Message>(serializedBytes);

        Display(title, originalMessage, deserializedMessage, serializer.GetType().ToString());
    }

    private static void Display(string title, Message originalMessage, Message deserializedMessage, string serializerName)
    {
        title = title + " - " + serializerName;
        Console.WriteLine(title + Environment.NewLine.PadRight(title.Length + 2, '-'));
        Console.WriteLine("Was a match:\t{0}", deserializedMessage.SentAt == originalMessage.SentAt);
        Console.WriteLine("Original Time:\t{0:HH:mm}\t\t{0:o}", originalMessage.SentAt);
        Console.WriteLine("New Time:\t{0:HH:mm}\t\t{0:o}", deserializedMessage.SentAt);
        Console.WriteLine(Environment.NewLine + Environment.NewLine + Environment.NewLine);
    } 
}



public class Message
{
    public DateTime SentAt { get; set; }
}



internal interface ISerializer
{
    byte[] Serialize(object objectToSerialize);
    T Deserialize<T>(byte[] serializedObject);
}


//Using Json.Net v4.5.11 via NuGet (Newtonsoft.Json)
internal class JsonNetSerializer : ISerializer
{
    private readonly Newtonsoft.Json.JsonSerializer _serializer = new Newtonsoft.Json.JsonSerializer();

    public byte[] Serialize(object objectToSerialize)
    {
        using (var memoryStream = new System.IO.MemoryStream())
        {
            using (var writer = new Newtonsoft.Json.Bson.BsonWriter(memoryStream))
            {
                _serializer.Serialize(writer, objectToSerialize);
                return memoryStream.ToArray();
            }
        }
    }

    public T Deserialize<T>(byte[] serializedObject)
    {
        using (var memoryStream = new System.IO.MemoryStream(serializedObject))
        {
            using (var reader = new Newtonsoft.Json.Bson.BsonReader(memoryStream))
            {
                return _serializer.Deserialize<T>(reader);
            }
        }
    }
}


//Using Official MongoDb C# Drive v1.8.0 (via NuGet)
internal class MongoDbSerializer : ISerializer
{
    public byte[] Serialize(object objectToSerialize)
    {
        using (var ms = new System.IO.MemoryStream())
        {
            var buffer = new MongoDB.Bson.IO.BsonBuffer();
            using (var writer = new MongoDB.Bson.IO.BsonBinaryWriter(ms, buffer, MongoDB.Bson.IO.BsonBinaryWriterSettings.Defaults))
            {
                MongoDB.Bson.Serialization.BsonSerializer.Serialize(writer, objectToSerialize);
                buffer.Position = 0;
                return buffer.ReadBytes(buffer.Length);
            }
        }
    }

    public T Deserialize<T>(byte[] serializedObject)
    {
        return MongoDB.Bson.Serialization.BsonSerializer.Deserialize<T>(serializedObject);
    }
}
}

file attachments

Closed Apr 6, 2013 at 9:30 AM by JamesNK
Set DateTimeKindHandling to DateTimeKind.Utc on BsonReader

comments