Search code examples
pythondjangodatetimedjango-rest-frameworkdjango-timezone

how to serialize time with timezone in django-rest-framework's serializer?


I have a Django model:

class Clinic(models.Model):

    NAME_MAX_LENGTH = 150
    name = models.CharField(max_length=NAME_MAX_LENGTH,blank=False,null=False)
    start_at = models.DateTimeField(blank=False,default=timezone.now)

the client sends the start_at field as a time field with timezone like

{
 start_at : "12:40:10+04:30"
} 

I want to convert this time field into the DateTimeField with the current date as the date and then save it into the database as a timezone-aware DateTimeField.

I want to serialize this field and extract timezone info from the input and then create my DateTimeField object. How can I do this in rest_framework serializer?


Solution

  • You can create a custom serializer field for this :

    import datetime
    
    from django.utils import timezone
    
    from rest_framework import serializers
    from rest_framework.fields import Field
    
    
    class TimeWithTimezoneField(Field):
    
        default_error_messages = {
            'invalid': 'Time has wrong format, expecting %H:%M:%S%z.',
        }
    
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
    
        def to_internal_value(self, value):
            value_with_date = datetime.datetime.now().strftime('%Y-%m-%d') + ' ' + value
            try:
                parsed = datetime.datetime.strptime(value_with_date, '%Y-%m-%d %H:%M:%S%z')
            except (ValueError, TypeError) as e:
                pass
            else:
                return parsed
            self.fail('invalid')
    
        def to_representation(self, value):
            if not value:
                return None
    
            if isinstance(value, str):
                return value
    
            return timezone.make_naive(value, timezone.utc).strftime("%H:%M:%S+00:00")
    
    
    class ClinicSerializer(serializers.ModelSerializer):
    
        start_at = TimeWithTimezoneField()
    
        class Meta:
            model = Clinic
            fields = [
                'id',
                'name',
                'start_at',
            ]
    
    

    With your example, start_at: 12:40:10+04:30 will be stored as a timezone aware datetime (in UTC : 08:40:10+00:00)