diff --git a/rest_framework/fields.py b/rest_framework/fields.py index 3ca7d682e..b8e2e1b2b 100644 --- a/rest_framework/fields.py +++ b/rest_framework/fields.py @@ -13,6 +13,7 @@ from django.core.exceptions import ValidationError as DjangoValidationError from django.core.exceptions import ObjectDoesNotExist from django.core.validators import RegexValidator, ip_address_validators from django.forms import ImageField as DjangoImageField +from django.forms.utils import from_current_timezone from django.utils import six, timezone from django.utils.dateparse import parse_date, parse_datetime, parse_time from django.utils.encoding import is_protected_type, smart_text @@ -903,7 +904,12 @@ class DateTimeField(Field): When `self.default_timezone` is not `None`, always return aware datetimes. """ if (self.default_timezone is not None) and not timezone.is_aware(value): - return timezone.make_aware(value, self.default_timezone) + # If a timezone is active, we want to use it, but if not we want to use the timezone + # specified for this field over the system's default timezone. + if hasattr(timezone._active, 'value'): + return from_current_timezone(value) + else: + return timezone.make_aware(value, self.default_timezone) elif (self.default_timezone is None) and timezone.is_aware(value): return timezone.make_naive(value, timezone.UTC()) return value diff --git a/tests/test_fields.py b/tests/test_fields.py index 76e6d9d60..b3dad35e2 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -4,6 +4,7 @@ from decimal import Decimal import django import pytest +from django.test.utils import override_settings from django.utils import timezone import rest_framework @@ -848,6 +849,40 @@ class TestNoOutputFormatDateField(FieldValues): field = serializers.DateField(format=None) +class FakeTimezone(datetime.tzinfo): + + def __repr__(self): + return "" + + def utcoffset(self, dt): + return datetime.timedelta(1) + + def tzname(self, dt): + return "FakeTimezone" + + def dst(self, dt): + return datetime.timedelta(1) + + +class TestAwareDateTimeField: + + @override_settings(USE_TZ=True) + def test_with_timezone_active(self): + naive_now = timezone.make_naive(timezone.now()) + timezone.activate(FakeTimezone()) + field = serializers.DateTimeField(default_timezone=timezone.UTC()) + aware_now = field.enforce_timezone(naive_now) + assert aware_now.tzname() == 'FakeTimezone' + timezone.deactivate() + + @override_settings(USE_TZ=True) + def test_without_timezone_active(self): + naive_now = timezone.make_naive(timezone.now()) + field = serializers.DateTimeField(default_timezone=timezone.UTC()) + aware_now = field.enforce_timezone(naive_now) + assert aware_now.tzname() == 'UTC' + + class TestDateTimeField(FieldValues): """ Valid and invalid values for `DateTimeField`.