Dealing with MongoDB DateTime in ASP.NET Core

MongoDB is one of the popular NoSQL databases available today. You can use MongoDB database in your ASP.NET Core applications using MongoDB.Driver NuGet package. I discussed the basics of MongoDB including CRUD operations here and here. Document databases such as MongoDB store data as JSON documents. Although JSON supports basic data types such as string, number, and boolean JSON doesn't support DateTime. So, date-time values are stored as string. In this article we will discuss a few things that you need to take into account while storing date-time values.

To work with the following code you can create a new ASP.NET Core web application or a console application. For the sake of simplicity I am going to use a .NET Core console application.

Once you create the application make sure to add the NuGet package for MongoDB.Driver. This NuGet package allows you to connect with the MongoDB server and perform the database operations.

Also, run the MongoDB server using mongod.exe before you run the application. For example, you could run the server using the following command:

> mongod.exe --dbpath .\Data

Then create a POCO that maps to the JSON / BSON document you want to store in the MongoDB database. Consider the following Employee class that I am going to use:

public class Employee
{
    [BsonId]
    public ObjectId Id { get; set; }

    [BsonElement]
    public string Name { get; set; }

    [BsonElement]
    public DateTime HireDate { get; set; }
}

The Id property acts as the ObjectId of the document. Name and HireDate properties are decorated with [BsonElement] attribute so they are serialized and de-serialized as a part of the JSON document.

DateTime is stored in UTC by default

By default, MongoDB stores DateTime value in UTC format. That means whatever value you assign to the HireDate property will be converted to its UTC value and then stored in the database. Naturally, what you assign to HireDate and what you retrieve after saving to database might be different values. Let's see this in action. Consider the following code:

Employee emp = new Employee();
emp.Id = new ObjectId();
emp.Name = "Nancy Davolio";
emp.HireDate = DateTime.Now;
Console.WriteLine(emp.HireDate);

MongoClient client = new MongoClient();
IMongoDatabase db = client.GetDatabase("TestDb");
IMongoCollection<Employee> employees = 
db.GetCollection<Employee>("Employees");

employees.InsertOne(emp);

Employee emp2 = employees.Find
(e => e.Id == emp.Id).SingleOrDefault();

Console.WriteLine(emp2.HireDate);
Console.ReadLine();

The code creates a new Employee object and assigns Id, Name, and HireDate properties. Notice that the HireDate is assigned to the current date and time value. The value assigned to the HireDate is outputted on the console for checking.

Then the code creates a MongoClient object. A database named TestDb is created along with Employees collection. The InsertOne() method of employees IMongoCollection adds the supplied Employee document to the database.

The code then retrieves the same Employee from the database based on its ObjectId and outputs the HireDate on the console.

A sample output from the application is as follows:

> 5/17/2019 8:43:20 AM
> 5/17/2019 3:13:20 AM

As you can see the two time values are different because the first value is the local DateTime whereas the second value is UTC DateTime.

Obviously, this can lead to confusion in your application. Luckily there is an easy way to handle the situation.

Storing local time

Suppose you don't want MongoDB to store UTC DateTime to the database. You prefer to store the local DateTime as it is into the database. You can accomplish this task as follows:

[BsonElement]
[BsonDateTimeOptions(Kind = DateTimeKind.Local)]
public DateTime HireDate { get; set; }

The HireDate property is now decorated with [BsonDateTimeOptions] attribute. Moreover, this attribute sets the Kind property to DateTimeKind.Local. This tells MongoDB driver to treat the property as a local DateTime value. So, while saving the document UTC conversion won't happen and while retrieving the same DateTime will be obtained.

After making the change run the application again to confirm the behavior.

> 5/17/2019 8:51:41 AM
> 5/17/2019 8:51:41 AM

As you can see, now both the values are same and they indicate client's local DateTime.

Storing UTC explicitly

In the preceding example you indicated you choice of storing values as local DateTime using the DateTimeKind.Local option. You can also store the values explicitly in UTC by setting the Kind property to DateTimeKind.Utc.

[BsonElement]
[BsonDateTimeOptions(Kind = DateTimeKind.Utc)]
public DateTime HireDate { get; set; }

However, if you decide to do so the value assigned to HireDate must be a UTC value. Consider the following code.

Employee emp = new Employee();
emp.Id = new ObjectId();
emp.Name = "Nancy Davolio";
emp.HireDate = DateTime.Now.ToUniversalTime();
Console.WriteLine(emp.HireDate);

The HireDate is now obtained by using the ToUniversalTime() method.

This time the sample output is:

> 5/17/2019 3:35:39 AM
> 5/17/2019 3:35:39 AM

As you can see, both the values are same but this time they are UTC values.

Storing only date

At times you want to store only the Date part of the DateTime. In that case you can instruct MongoDB that you want to store only date as follows:

[BsonElement]
[BsonDateTimeOptions(DateOnly = true)]
public DateTime HireDate { get; set; }

The DateOnly property of [BsonDateTimeOptions] attribute is set to true indicating that only date part is to be persisted. Also ensure that only date is being assigned to HireDate.

Employee emp = new Employee();
emp.Id = new ObjectId();
emp.Name = "Nancy Davolio";
emp.HireDate = DateTime.Now.Date;
Console.WriteLine(emp.HireDate);

A sample run of the application produces this output.

> 5/17/2019 12:00:00 AM
> 5/17/2019 12:00:00 AM

As you can see, the time part is now 12:00:00 AM indicating that only date part is considered.

That's it for now! Keep coding!!


Bipin Joshi is a software consultant, trainer, author, and yoga mentor having 24+ years of experience in software development, consulting, and training. He conducts instructor-led online training courses in ASP.NET Core, ASP.NET MVC, and Design Patterns for individuals and small groups. He is a published author and has authored or co-authored books for Apress and Wrox press. Having embraced the Yoga way of life he also teaches Ajapa Yoga to interested individuals. To know more about him click here.

Get article updates : Facebook  Twitter  LinkedIn

Posted On : 20 May 2019


Tags : ASP.NET ASP.NET Core Data Access .NET Framework C#


Subscribe to our newsletter

Get monthly email updates about new articles, tutorials, code samples, and how-tos getting added to our knowledge base.

  

Receive Weekly Updates