1

I am sending the UTC Datetime from my C# winform app to MongoDb 3.4.5, but it is stored as local time in MongoDb. When I get the data from Mongo it returns me the UTC time.

My problem here is why the datetime is stored in local in MongoDb in-spite of sending UTC Datetime from UI. I want UTC time to be stored in MongoDb. Below is the code snippet:

public void InsertInMongo()
    {
        var client = new MongoClient("mongodb://localhost:27017");
        var db = client.GetDatabase("Test");
        var col = db.GetCollection<TestData>("TestData");

        var data = new TestData(123,DateTime.UtcNow);
        col.InsertOne(data);

        var fromMongo = col.Find(Builders<TestData>.Filter.Empty).ToList();

    }
}

class TestData
{
    public TestData(int num, DateTime date)
    {
        TestNumber = num;
        TestDate = date;
    }
    [BsonId]
    [BsonElement("_id")]
    [BsonRepresentation(BsonType.ObjectId)]
    [BsonIgnoreIfDefault]
    public string Id { get; private set; }
    public int TestNumber { get; set; }

    public DateTime TestDate { get; set; }
}
}

Stored Data in MongoDb

How can I resolve this? I am newbie in Mongo with C#.

halfer
  • 19,824
  • 17
  • 99
  • 186
  • check https://stackoverflow.com/a/39074431/6448640 –  Aug 12 '17 at 19:33
  • @Ashikirsha Thank you so much for the link, I saw the accepted answer. It looks great. I am so sorry but I am newbie in this, I am not sure how do I map my date field with this "MyMongoDBDateTimeSerializer" as per the answer in the post? – Abhishek_Chourasia Aug 12 '17 at 19:44
  • @Ashikirsha I added `[BsonDateTimeOptions(Kind = DateTimeKind.Utc)] public DateTime TestDate { get; set; }` But it is still the same! – Abhishek_Chourasia Aug 12 '17 at 19:48
  • As mentioned in the most voted answer, you need to create your custom serializing format then call it before inserting or querying data: something like `BsonSerializer.RegisterSerializer(typeof(DateTime), new YourDateTimeSerializer());` - HTH ;). – shA.t Aug 13 '17 at 06:06
  • @shA.t I tried the above but it did not work. Do you have any sample for me how to implement it. – Abhishek_Chourasia Aug 13 '17 at 14:03

4 Answers4

2

You need to declare your custom DateTimeSerializer like this:

public class BsonUtcDateTimeSerializer : DateTimeSerializer
{
    public override DateTime Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
    {
        return new DateTime(base.Deserialize(context, args).Ticks, DateTimeKind.Unspecified);
    }

    public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, DateTime value)
    {
        var utcValue = new DateTime(value.Ticks, DateTimeKind.Utc);
        base.Serialize(context, args, utcValue);
    }
}

Then you need to register if after creating connection; something like this:

var server = new MongoClient("mongodb://127.0.0.1");
var database = server.GetDatabase("Test");
var collection = database.GetCollection<MyObject>("MyObject");

BsonSerializer.RegisterSerializer(typeof(DateTime), new BsonUtcDateTimeSerializer());

Edit:

BSON Date is a 64-bit integer that represents the number of milliseconds since the Unix epoch (Jan 1, 1970). This results in a representable date range of about 290 million years into the past and future.
The official BSON specification refers to the BSON Date type as the UTC datetime.

So, dates in MongoDB are in UTC milliseconds, then your application that brows data from MongoDB show them with localized format.

  • Local Date Time

    MongoDB stores times in UTC by default, and will convert any local time representations into this form. Applications that must operate or report on some unmodified local time value may store the time zone alongside the UTC timestamp, and compute the original local time in their application logic.

shA.t
  • 16,580
  • 5
  • 54
  • 111
  • Thank you for the sample. I am sorry but still the date is stored in Local format in Mongo and when I retrieve it, it comes in UTC. I want to store it in UTC format also. – Abhishek_Chourasia Aug 15 '17 at 12:47
  • I didn't test this, but check it again that I change `Deserialize` to use `DateTimeKind.Utc` ;). – shA.t Aug 15 '17 at 13:21
  • Thanks again! It is still the same. The date is saved as local in Mongo and I get it in UTC format. I want to send it in UTC to data base. I am initializing like below: `var data = new TestData(123,DateTime.UtcNow);` – Abhishek_Chourasia Aug 15 '17 at 13:27
  • Omg! Note that ***MongoDB stores all datetime as Utc***, but applications have an option date show them as local time ;). – shA.t Aug 15 '17 at 13:33
  • 1
    So what am I doing wrong? :) I can see datetime in MongoDB as my local datetime. I am converting it to local at application level after fetching it from MongoDb. But why am I not able to store see UTC in MongoDb. – Abhishek_Chourasia Aug 15 '17 at 13:35
  • I edit my answer by adding info about how dates store in MongoDB. – shA.t Aug 15 '17 at 13:41
  • 1
    @Abhishek_Chourasia is this issue solved? I'm facing exact same issue..mongodb storing local date in db but while retrieving getting UTC date.. Did your resolve this issue? – kaluva Mar 23 '18 at 07:40
2

MongoDB provides an attribute which automatically does the trick.

[BsonDateTimeOptions(Kind = DateTimeKind.Local)]

so you just need to add this attribute on your TestDate property

mathpaquette
  • 406
  • 4
  • 16
0

I think you are going to have to convert back to a specific time zone. You need to determine the offset between your UTC time and what you get from mongo. If there is no offset then Mongo is storing it as UTC as well, which I bet is happening. I doubt, for example, you will find it regional such as EST. Once you establish the time zone info you can then convert from one zone to another using the TimeZoneInfo object or something similiar, however, you need to know the time zone you want to convert to.

Ross Bush
  • 14,648
  • 2
  • 32
  • 55
0

So, this is the case with mongo DB UI, Compass always shows the stored data in local date format of user but this is not the case with Robo3T or mongoDB shell. MongoDB always stores the date in UTC format unless explicitly specified to store it in local.