Created
August 12, 2020 13:25
-
-
Save arkanister/e45a91c1d77bc4ed40e57d14c7644cb2 to your computer and use it in GitHub Desktop.
TimeStamp Field For Django Rest Framework
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import datetime | |
from django.conf import settings | |
from django.utils import timezone | |
from django.utils.translation import ugettext_lazy as _ | |
from rest_framework import serializers, compat | |
class TimestampField(serializers.Field): | |
default_error_messages = { | |
'invalid': _('Datetime has wrong format. Use one of these formats instead: {format}.'), | |
'date': _('Expected a datetime but got a date.'), | |
'make_aware': _('Invalid datetime for the timezone "{timezone}".'), | |
'overflow': _('Datetime value out of range.') | |
} | |
def __init__(self, default_timezone=None, *args, **kwargs): | |
self._timezone = default_timezone | |
super().__init__(*args, **kwargs) | |
@property | |
def timezone(self): | |
if not settings.USE_TZ: | |
return None | |
return self._timezone or timezone.get_current_timezone() | |
def enforce_timezone(self, value): | |
""" | |
When `self.timezone` is `None`, always return naive datetimes. | |
When `self.timezone` is not `None`, always return aware datetimes. | |
""" | |
field_timezone = self.timezone | |
if field_timezone is not None: | |
if timezone.is_aware(value): | |
try: | |
return value.astimezone(field_timezone) | |
except OverflowError: | |
self.fail('overflow') | |
try: | |
return timezone.make_aware(value, field_timezone) | |
except compat.InvalidTimeError: | |
self.fail('make_aware', timezone=field_timezone) | |
elif (field_timezone is None) and timezone.is_aware(value): | |
return timezone.make_naive(value, timezone.utc) | |
return value | |
def to_internal_value(self, value): | |
if not value: | |
return None | |
if isinstance(value, datetime.date) and not isinstance(value, datetime.datetime): | |
self.fail('date') | |
if isinstance(value, datetime.datetime): | |
return self.enforce_timezone(value) | |
try: | |
value = float(value) | |
except (TypeError, ValueError): | |
self.fail('invalid') | |
dt_value = None | |
for value in [value, value / 1e3]: | |
try: | |
dt_value = datetime.datetime.utcfromtimestamp(value) | |
except (TypeError, ValueError): | |
continue | |
else: | |
break | |
if not dt_value: | |
self.fail('invalid') | |
return self.enforce_timezone(dt_value) | |
def to_representation(self, value): | |
if not value: | |
return None | |
value = self.enforce_timezone(value) | |
return datetime.datetime.timestamp(value) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment