This commit is contained in:
Ryan P Kilby 2017-09-20 10:05:20 +00:00 committed by GitHub
commit ad6dee2e2f
3 changed files with 63 additions and 5 deletions

View File

@ -1,4 +1,5 @@
# Optional packages which may be used with REST framework. # Optional packages which may be used with REST framework.
pytz==2017.2
markdown==2.6.4 markdown==2.6.4
django-guardian==1.4.8 django-guardian==1.4.8
django-filter==1.0.4 django-filter==1.0.4

View File

@ -1125,7 +1125,9 @@ class DateTimeField(Field):
""" """
field_timezone = getattr(self, 'timezone', self.default_timezone()) field_timezone = getattr(self, 'timezone', self.default_timezone())
if (field_timezone is not None) and not timezone.is_aware(value): if field_timezone is not None:
if timezone.is_aware(value):
return value.astimezone(field_timezone)
try: try:
return timezone.make_aware(value, field_timezone) return timezone.make_aware(value, field_timezone)
except InvalidTimeError: except InvalidTimeError:
@ -1135,7 +1137,7 @@ class DateTimeField(Field):
return value return value
def default_timezone(self): def default_timezone(self):
return timezone.get_default_timezone() if settings.USE_TZ else None return timezone.get_current_timezone() if settings.USE_TZ else None
def to_internal_value(self, value): def to_internal_value(self, value):
input_formats = getattr(self, 'input_formats', api_settings.DATETIME_INPUT_FORMATS) input_formats = getattr(self, 'input_formats', api_settings.DATETIME_INPUT_FORMATS)
@ -1174,6 +1176,7 @@ class DateTimeField(Field):
return value return value
if output_format.lower() == ISO_8601: if output_format.lower() == ISO_8601:
value = self.enforce_timezone(value)
value = value.isoformat() value = value.isoformat()
if value.endswith('+00:00'): if value.endswith('+00:00'):
value = value[:-6] + 'Z' value = value[:-6] + 'Z'

View File

@ -10,12 +10,17 @@ import pytest
from django.http import QueryDict from django.http import QueryDict
from django.test import TestCase, override_settings from django.test import TestCase, override_settings
from django.utils import six from django.utils import six
from django.utils.timezone import utc from django.utils.timezone import activate, deactivate, utc
import rest_framework import rest_framework
from rest_framework import compat, serializers from rest_framework import compat, serializers
from rest_framework.fields import is_simple_callable from rest_framework.fields import is_simple_callable
try:
import pytz
except ImportError:
pytz = None
try: try:
import typings import typings
except ImportError: except ImportError:
@ -1168,7 +1173,7 @@ class TestDateTimeField(FieldValues):
datetime.date(2001, 1, 1): ['Expected a datetime but got a date.'], datetime.date(2001, 1, 1): ['Expected a datetime but got a date.'],
} }
outputs = { outputs = {
datetime.datetime(2001, 1, 1, 13, 00): '2001-01-01T13:00:00', datetime.datetime(2001, 1, 1, 13, 00): '2001-01-01T13:00:00Z',
datetime.datetime(2001, 1, 1, 13, 00, tzinfo=utc): '2001-01-01T13:00:00Z', datetime.datetime(2001, 1, 1, 13, 00, tzinfo=utc): '2001-01-01T13:00:00Z',
'2001-01-01T00:00:00': '2001-01-01T00:00:00', '2001-01-01T00:00:00': '2001-01-01T00:00:00',
six.text_type('2016-01-10T00:00:00'): '2016-01-10T00:00:00', six.text_type('2016-01-10T00:00:00'): '2016-01-10T00:00:00',
@ -1230,10 +1235,59 @@ class TestNaiveDateTimeField(FieldValues):
'2001-01-01 13:00': datetime.datetime(2001, 1, 1, 13, 00), '2001-01-01 13:00': datetime.datetime(2001, 1, 1, 13, 00),
} }
invalid_inputs = {} invalid_inputs = {}
outputs = {} outputs = {
datetime.datetime(2001, 1, 1, 13, 00): '2001-01-01T13:00:00',
datetime.datetime(2001, 1, 1, 13, 00, tzinfo=utc): '2001-01-01T13:00:00',
}
field = serializers.DateTimeField(default_timezone=None) field = serializers.DateTimeField(default_timezone=None)
@pytest.mark.skipif(pytz is None, reason='pytz not installed')
class TestTZWithDateTimeField(FieldValues):
"""
Valid and invalid values for `DateTimeField` when not using UTC as the timezone.
"""
@classmethod
def setup_class(cls):
# use class setup method, as class-level attribute will still be evaluated even if test is skipped
kolkata = pytz.timezone('Asia/Kolkata')
cls.valid_inputs = {
'2016-12-19T10:00:00': kolkata.localize(datetime.datetime(2016, 12, 19, 10)),
'2016-12-19T10:00:00+05:30': kolkata.localize(datetime.datetime(2016, 12, 19, 10)),
datetime.datetime(2016, 12, 19, 10): kolkata.localize(datetime.datetime(2016, 12, 19, 10)),
}
cls.invalid_inputs = {}
cls.outputs = {
datetime.datetime(2016, 12, 19, 10): '2016-12-19T10:00:00+05:30',
datetime.datetime(2016, 12, 19, 4, 30, tzinfo=utc): '2016-12-19T10:00:00+05:30',
}
cls.field = serializers.DateTimeField(default_timezone=kolkata)
@pytest.mark.skipif(pytz is None, reason='pytz not installed')
@override_settings(TIME_ZONE='UTC', USE_TZ=True)
class TestDefaultTZDateTimeField(TestCase):
"""
Test the current/default timezone handling in `DateTimeField`.
"""
@classmethod
def setup_class(cls):
cls.field = serializers.DateTimeField()
cls.kolkata = pytz.timezone('Asia/Kolkata')
def test_default_timezone(self):
assert self.field.default_timezone() == utc
def test_current_timezone(self):
assert self.field.default_timezone() == utc
activate(self.kolkata)
assert self.field.default_timezone() == self.kolkata
deactivate()
assert self.field.default_timezone() == utc
class TestNaiveDayLightSavingTimeTimeZoneDateTimeField(FieldValues): class TestNaiveDayLightSavingTimeTimeZoneDateTimeField(FieldValues):
""" """
Invalid values for `DateTimeField` with datetime in DST shift (non-existing or ambiguous) and timezone with DST. Invalid values for `DateTimeField` with datetime in DST shift (non-existing or ambiguous) and timezone with DST.