Compose Tips: Dates and Dating in MongoDB

Working with dates in MongoDB can be surprisingly nuanced, and knowing how dates are stored can make avoiding pitfalls much easier. Read on as we examine the inner workings of MongoDB dates and show how to choose the right date type for your needs.

At Compose Tips, we like to address the issues that can leave even experienced developers scratching their head. We'll kick off this series by taking a look at how MongoDB stores dates.

What's in a Date?

Dates in MongoDB have a few different representations, and getting the right one can mean the difference between being able to effectively search your data by date range using aggregations and being forced to manage your dates on the client side of your application. Let's take a look at the different ways that MongoDB can store dates.

Internally, MongoDB can store dates as either Strings or as 64-bit integers. If you intend to do any operations using the MongoDB query or aggregate functions, or if you want to index your data by date, you'll likely want to store your dates as integers. If you're using the built-in "Date" data type, or a date wrapped in the ISODate() function, you're also storing your date as an integer.

If you're just looking for a simple way to display dates to a user and aren't concerned with performing operations on those dates, then a String will allow you to use the output from a MongoDB query directly without the need to convert the date into a String. This can be handy for platforms without a convenient or easy Date wrapper, or if you don't want to spend time processing the date on the client side of your application.

Let's walk through each of the potential ways a Date can be represented in MongoDB and discuss the pros and cons of each.

Milliseconds Since the Epoch

One standard way that many databases store dates is as a count of milliseconds since the Epoch, with 0 representing January 1, 1970 at 00:00:00GMT. This is how dates are stored internally in most programming languages.

Storing data as milliseconds since the Epoch makes comparing dates to each other a simple numeric comparison. Developers can also easily modify dates, including adding time frames (such as adding 1 day to a date) by computing the number of milliseconds in a day.

While milliseconds are easy to manipulate programmatically, they're difficult for programmers to conceptualize. It's difficult to tell even what decade a date is in just by looking at the millisecond count, so it needs to be converted into a readable String before most developers will be able to display a date represented in this format.

ISODate()

If you've tried to save a Javascript Date object into MongoDB, you might've noticed that MongoDB automatically wrapped your date with a peculiar function: ISODate().

ISODate("2012-12-19T06:01:17.171Z")

ISODate() is a helper function that's built into to MongoDB and wraps the native JavaScript Date object. When you use the ISODate() constructor from the Mongo shell, it actually returns a JavaScript Date object. So why bother with ISODate()?

ISODate() provides a convenient way to represent a date in MongoDB as a String visually, while still allowing the full use of date queries and indexing. By wrapping the ISO date String in a function, the developer can inspect date objects quickly and visually without having to convert from a Unix timestamp to a time String. We can see this by comparing the following date using the ISODate() constructor:

ISODate("2012-12-19T06:01:17.171Z")

To the corresponding JavaScript Date constructor:

Date(1355897837000)

The ISODate() constructor is clearly easier to read at-a-glance for developers.

One other major benefit is that, while there are many ways to represent dates, the ISODate() uses the standardized ISO format. Your clients don't have to do any guesswork to figure out what format they'll need to store dates in your system.

Probably the biggest downside is that the ISODate() will convert your date to ISO format and, should you need a different date format on the client-side of your applications, you'll have to convert that date on the client side. This can be a concern when processing a lot of records that need to have the dates in a specific format, or when real-time processing of date stamps is a concern.

String Format

The final format we'll take a look at is String format, which stores a date as a simple String in a human-readable format.

Dates stored in String format are very easy to display and don't require any processing to use in visual displays. Also, assuming the date matches a standard format, the date stored in String format will be relatively easy to convert to a date on any platform.

When a date is stored in String format, it can sometimes be difficult to determine what the actual format of the date is in the String. The following example illustrates this issue: does the following date represent the 1st of February 2017 or the 2nd of January 2017?

2017-02-01

This ambiguity can cause major issues if the date is parsed incorrectly. Developers using loosely-typed languages like JavaScript will sometimes accidentally store a time String rather than a date, so sometimes the presence of a String in the date field can indicate a logic error.

Wrapping Up

MongoDB dates can initially cause some frustration for developers just starting out, and understanding the different ways that a date can be stored in MongoDB can help to ease that frustration. In a future article, we'll cover how to manipulate and compute with dates in MongoDB.

If you have any feedback about this or any other Compose article, drop the Compose Articles team a line at articles@compose.com. We're happy to hear from you.

John O'Connor is a code junky, educator, and amateur dad that loves letting the smoke out of gadgets, turning caffeine into code, and writing about it all. Love this article? Head over to John O'Connor’s author page to keep reading.