Geek Logbook

Tech sea log book

Handling Python datetime Objects in Amazon DynamoDB

When developing data pipelines or applications that store time-based records in Amazon DynamoDB, developers frequently encounter serialization errors when working with Python’s datetime objects. Understanding how to properly store temporal data in DynamoDB is essential to avoid runtime issues and to enable meaningful queries.

The Problem

DynamoDB, as a NoSQL database, supports a limited set of data types: String (S), Number (N), Binary (B), Boolean (BOOL), Null (NULL), List (L), Map (M), and Set (SS, NS, BS). It does not support a native datetime type.

This becomes problematic when using boto3, the AWS SDK for Python. Attempting to insert a Python datetime.datetime object directly into a DynamoDB table using the put_item() method will raise a TypeError:

Unsupported type "<class 'datetime.datetime'>"

This is a common issue when timestamps are tracked for auditing, logging, or data processing.

The Solution

To work around this limitation, the datetime object must be converted into a supported data type before it is stored in the DynamoDB table.

1. Convert to ISO 8601 String Format

The most common approach is to convert the datetime object to an ISO 8601 formatted string. This format is both human-readable and suitable for lexicographical sorting, which aligns with DynamoDB’s sorting behavior for String types.

from datetime import datetime
dt = datetime.utcnow()
dt_iso = dt.isoformat()  # e.g., '2025-07-10T04:24:32.123456+00:00'

This value can then be stored in a field such as created_at:

table.put_item(Item={
    "id": "123",
    "created_at": dt_iso,
})

2. Convert to UNIX Timestamp (Epoch)

If numeric comparison or range filtering is required (e.g., “records in the last 7 days”), converting the datetime to a UNIX timestamp is more appropriate:

timestamp = int(dt.timestamp())  # e.g., 1752102272

This value can be stored as a Number in DynamoDB:

table.put_item(Item={
    "id": "123",
    "created_at_epoch": timestamp,
})

3. Use Both Formats (Recommended)

For maximum flexibility, it is often beneficial to store both the ISO string and the epoch value:

table.put_item(Item={
    "id": "123",
    "created_at": dt.isoformat(),
    "created_at_epoch": int(dt.timestamp()),
})

This allows developers to display human-readable timestamps in UIs or logs while also enabling performant numeric queries and comparisons.

Best Practices

  • Always validate the type before inserting into DynamoDB to avoid runtime errors.
  • Use ISO 8601 for ordering and readability when querying with sort keys.
  • Use UNIX timestamps when precise interval queries or arithmetic comparisons are required.
  • Avoid timezone-naïve datetime values. Always ensure that datetime objects are timezone-aware (e.g., using UTC).

Conclusion

DynamoDB does not natively support datetime objects, but this limitation can be effectively managed by serializing the date into supported formats before persistence. By adopting a consistent strategy for date handling, developers can avoid common errors and design systems that are both efficient and maintainable.

Tags: