Django’s JSON encoder rounds datetime
s down to the nearest millisecond
Django provides a custom DjangoJSONEncoder
class that can
encode datetime.date
, datetime.datetime
, decimal.Decimal
and uuid.UUID
types.
Beware though: this class serializes datetime.datetime
instances to
millisecond precision only. Since Python’s datetime.datetime
type supports
microsecond precision, the serialisation process can change the datetime’s
value.
Watch:
>>> import datetime
>>> import json
>>> from django.core.serializers.json import DjangoJSONEncoder
>>>
>>> # Create a datetime with sub-millisecond precision.
>>> dt = datetime.datetime(2022, 12, 1, 14, 0, 0, 1234)
>>> dt.isoformat()
"2022-12-01T14:00:00.001234"
>>>
>>> # Serialize the datetime using Django's encoder.
>>> print(json.dumps(dt, cls=DjangoJSONEncoder))
"2022-12-01T14:00:00.001"
As the above snippet illustrates, serialising a datetime.datetime
effectively
rounds it down to the nearest millisecond.
Why?
This rounding is deliberate.

It’s done to ensure serialized datetime
strings conform with the ECMAScript
262 language specification which mandates millisecond precision.
Ultimately, this is because the JavaScript Date
object only
supports millisecond precision.
Broken tests
This is a gotcha that can effect tests that compare datetime
values that get
serialized and deserialized (which is how I stumbled upon it).
If you need to perform the same rounding in Python code, use something like:
rounded_dt = dt.replace(microsecond=dt.microsecond // 1000 * 1000)