master
branch of Django REST framework.The implementation of datetime serialization in ISO-8601 format is not consistent in the codebase.
In https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/fields.py#L1094 microseconds are included in the serialized value
In https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/utils/encoders.py#L30 only milliseconds are
I would expect a consistent implementation.
N/A
Currently some clients of my API require dates with millisecond precision and cannot handle microseconds. I achieved this by setting 'DATETIME_FORMAT' to None in the settings for DRF 3.3. Upgrading to 3.4 breaks this behavior. Is there an easy way to get the previous behavior? I can't figure out how to specify a datetime format string that gives me the ECMA-262 format. Thanks.
@georgejlee I use a custom renderer to work around this:
import datetime
from rest_framework.renderers import JSONRenderer
from rest_framework.utils.encoders import JSONEncoder
class MilliSecondEncoder(JSONEncoder):
def default(self, obj):
if isinstance(obj, datetime.datetime):
representation = obj.isoformat()
if obj.microsecond:
representation = representation[:23] + representation[26:]
if representation.endswith('+00:00'):
representation = representation[:-6] + 'Z'
return representation
else:
return super().default(obj)
class JSONRenderer(JSONRenderer):
encoder_class = MilliSecondEncoder
Hmm, changing DEFAULT_RENDERER_CLASSES to custom renderer did not affect the rendering of my viewsets. Had to set renderer_class explicitly, strange.
In case anyone else stumbles across this while trying to configure DRF to use a custom encoder via encoder_class
for datetime
. The issue that kept the solution in https://github.com/encode/django-rest-framework/issues/4255#issuecomment-234560555 from working for me was DRF will use its built-in encoder unless either the field's DateTimeField
has its format
kwarg set to None
OR, if you don't specify DateTimeField
serializers, then you need to set REST_FRAMEWORK
's config for DEFAULT_FORMAT: None
in your settings.py
. Only then will the custom encoder
be used.
The reason is, the serializer field(s) (or default field renderer) will be used to format the Response
before the custom Renderer
is used to render the datetime
. So the datetime field will already be a string and the default JSONEncoder won't invoke the custom encoder, since the default Python types are handled by the encoder so the custom encoder's default
method won't be called.
Most helpful comment
@georgejlee I use a custom renderer to work around this:
Hmm, changing DEFAULT_RENDERER_CLASSES to custom renderer did not affect the rendering of my viewsets. Had to set renderer_class explicitly, strange.