PyMongo: How to save datetime with timezone

Updated: February 8, 2024 By: Guest Contributor Post a comment

Overview

Saving dates and times in a MongoDB database using PyMongo is a common task for many developers. However, dealing with timezones can add complexity to this seemingly simple task. This tutorial will guide you through the process of saving datetime objects with timezones in MongoDB using PyMongo, from basic to more advanced techniques. Along the way, we’ll include multiple code examples to demonstrate each concept.

Before we dive into the examples, ensure that you have MongoDB and PyMongo installed. If you haven’t installed PyMongo yet, you can do so using pip:

pip install pymongo

Understanding Timezone in PyMongo

MongoDB stores dates in UTC by default and does not keep track of the original timezone. This means it’s up to the client application to manage timezones. Python’s datetime module and the pytz library can be used together to handle timezones effectively.

Basic Example: Saving a Naive Datetime

from datetime import datetime
import pymongo
from pymongo import MongoClient

# Connect to MongoDB
client = MongoClient('mongodb://localhost:27017/')

# Select the database
db = client['mydatabase']

# Select the collection
collection = db['mycollection']

# Create a naive datetime object (no timezone)
date_without_timezone = datetime.now()

# Insert document
collection.insert_one({"date": date_without_timezone})

This code snippet shows how to store a naive datetime object—i.e., a datetime without timezone information. MongoDB stores this datetime in UTC by default. To reliably work with timezones, we must use aware datetime objects.

Using PyTZ to Create Aware Datetime Objects

import pytz
from datetime import datetime
import pymongo
from pymongo import MongoClient

# Connect to MongoDB
client = MongoClient('mongodb://localhost:27017/')

# Select the database
db = client['mydatabase']

# Select the collection
collection = db['mycollection']

# Create an aware datetime object using pytz
timezone_new_york = pytz.timezone('America/New_York')
date_with_timezone = datetime.now(timezone_new_york)

# Insert document
collection.insert_one({"date": date_with_timezone})

By using the pytz library, we can create datetime objects that are aware of their timezone. When these aware datetime objects are stored in MongoDB, the timezone information is not saved, but the time is adjusted to UTC based on the given timezone.

Handling Timezones on Retrieval

from datetime import datetime
import pytz
import pymongo
from pymongo import MongoClient

# Connect to MongoDB
client = MongoClient('mongodb://localhost:27017/')

# Select the database
db = client['mydatabase']

# Select the collection
collection = db['mycollection']

# Retrieve a document
document = collection.find_one()

# Convert the stored UTC datetime back to the original timezone
original_timezone = pytz.timezone('America/New_York')
retrieved_datetime = document['date'].replace(tzinfo=pytz.utc).astimezone(original_timezone)

# Print the datetime with timezone
print(retrieved_datetime)

This snippet demonstrates how to convert a UTC datetime retrieved from MongoDB back to its original timezone. It’s important to explicitly replace the tzinfo of the retrieved datetime with UTC before converting it to the desired timezone. This ensures accuracy in the conversion process.

Advanced Techniques

While the MongoDB server stores all datetimes in UTC, your application might need to work with multiple timezones. The following example demonstrates saving and retrieving datetime objects with dynamic timezones.

from datetime import datetime
import pytz
import pymongo
from pymongo import MongoClient

client = MongoClient('mongodb://localhost:27017/')

db = client['mydatabase']
collection = db['mycollection']

timezones = ['America/New_York', 'Europe/London', 'Asia/Tokyo']
for tz in timezones:
    timezone = pytz.timezone(tz)
    date_with_timezone = datetime.now(timezone)
    collection.insert_one({"date": date_with_timezone, "timezone": tz})

for document in collection.find():
    original_timezone = pytz.timezone(document['timezone'])
    retrieved_datetime = document['date'].replace(tzinfo=pytz.utc).astimezone(original_timezone)
    print(f"Original timezone: {document['timezone']}, Converted datetime: {retrieved_datetime}")

This advanced technique involves storing the name of the timezone along with the datetime object. This approach makes it straightforward to retrieve the datetime in its original timezone, regardless of the timezone stored.

Conclusion

Dealing with timezones in MongoDB using PyMongo involves understanding how MongoDB handles datetimes and effectively using Python’s datetime and pytz libraries to work with timezone-aware datetime objects. By incorporating these strategies into your applications, you can ensure accurate and reliable storage and retrieval of datetime information with respect to timezones.