aboutsummaryrefslogtreecommitdiffstats
path: root/rest_framework
diff options
context:
space:
mode:
authorTom Christie2013-03-06 12:19:39 +0000
committerTom Christie2013-03-06 12:19:39 +0000
commit1106596c80218569a56ff5ea04d759e3d0c541dd (patch)
treeabef8464aad8d551113243b430b436ce4449fee2 /rest_framework
parent4f7b028a0a983b79ebca63b2ba48ce97e7a06175 (diff)
downloaddjango-rest-framework-1106596c80218569a56ff5ea04d759e3d0c541dd.tar.bz2
Clean ups to datetime formatting
Diffstat (limited to 'rest_framework')
-rw-r--r--rest_framework/__init__.py2
-rw-r--r--rest_framework/fields.py88
-rw-r--r--rest_framework/settings.py14
-rw-r--r--rest_framework/tests/fields.py26
-rw-r--r--rest_framework/utils/dates.py14
5 files changed, 83 insertions, 61 deletions
diff --git a/rest_framework/__init__.py b/rest_framework/__init__.py
index d26bb6bf..14ab7ff0 100644
--- a/rest_framework/__init__.py
+++ b/rest_framework/__init__.py
@@ -6,4 +6,4 @@ VERSION = __version__ # synonym
HTTP_HEADER_ENCODING = 'iso-8859-1'
# Default input and output format
-ISO8601 = 'iso-8601' \ No newline at end of file
+ISO_8601 = 'iso-8601'
diff --git a/rest_framework/fields.py b/rest_framework/fields.py
index e65f0307..fe555ee5 100644
--- a/rest_framework/fields.py
+++ b/rest_framework/fields.py
@@ -14,13 +14,12 @@ from django.forms import widgets
from django.utils.encoding import is_protected_type
from django.utils.translation import ugettext_lazy as _
-from rest_framework import ISO8601
+from rest_framework import ISO_8601
from rest_framework.compat import timezone, parse_date, parse_datetime, parse_time
from rest_framework.compat import BytesIO
from rest_framework.compat import six
from rest_framework.compat import smart_text
from rest_framework.settings import api_settings
-from rest_framework.utils.dates import get_readable_date_format
def is_simple_callable(obj):
@@ -52,6 +51,46 @@ def get_component(obj, attr_name):
return val
+def readable_datetime_formats(formats):
+ format = ', '.join(formats).replace(ISO_8601, 'YYYY-MM-DDThh:mm[:ss[.uuuuuu]][+HHMM|-HHMM|Z]')
+ return humanize_strptime(format)
+
+
+def readable_date_formats(formats):
+ format = ', '.join(formats).replace(ISO_8601, 'YYYY[-MM[-DD]]')
+ return humanize_strptime(format)
+
+
+def readable_time_formats(formats):
+ format = ', '.join(formats).replace(ISO_8601, 'hh:mm[:ss[.uuuuuu]]')
+ return humanize_strptime(format)
+
+
+def humanize_strptime(format_string):
+ # Note that we're missing some of the locale specific mappings that
+ # don't really make sense.
+ mapping = {
+ "%Y": "YYYY",
+ "%y": "YY",
+ "%m": "MM",
+ "%b": "[Jan-Dec]",
+ "%B": "[January-December]",
+ "%d": "DD",
+ "%H": "hh",
+ "%I": "hh", # Requires '%p' to differentiate from '%H'.
+ "%M": "mm",
+ "%S": "ss",
+ "%f": "uuuuuu",
+ "%a": "[Mon-Sun]",
+ "%A": "[Monday-Sunday]",
+ "%p": "[AM|PM]",
+ "%z": "[+HHMM|-HHMM]"
+ }
+ for key, val in mapping.items():
+ format_string = format_string.replace(key, val)
+ return format_string
+
+
class Field(object):
read_only = True
creation_counter = 0
@@ -453,11 +492,11 @@ class DateField(WritableField):
}
empty = None
input_formats = api_settings.DATE_INPUT_FORMATS
- output_format = api_settings.DATE_OUTPUT_FORMAT
+ format = api_settings.DATE_FORMAT
- def __init__(self, input_formats=None, output_format=None, *args, **kwargs):
+ def __init__(self, input_formats=None, format=None, *args, **kwargs):
self.input_formats = input_formats if input_formats is not None else self.input_formats
- self.output_format = output_format if output_format is not None else self.output_format
+ self.format = format if format is not None else self.format
super(DateField, self).__init__(*args, **kwargs)
def from_native(self, value):
@@ -475,7 +514,7 @@ class DateField(WritableField):
return value
for format in self.input_formats:
- if format.lower() == ISO8601:
+ if format.lower() == ISO_8601:
try:
parsed = parse_date(value)
except (ValueError, TypeError):
@@ -491,16 +530,15 @@ class DateField(WritableField):
else:
return parsed.date()
- date_input_formats = '; '.join(self.input_formats).replace(ISO8601, 'YYYY-MM-DD')
- msg = self.error_messages['invalid'] % get_readable_date_format(date_input_formats)
+ msg = self.error_messages['invalid'] % readable_date_formats(self.input_formats)
raise ValidationError(msg)
def to_native(self, value):
if isinstance(value, datetime.datetime):
value = value.date()
- if self.output_format.lower() == ISO8601:
+ if self.format.lower() == ISO_8601:
return value.isoformat()
- return value.strftime(self.output_format)
+ return value.strftime(self.format)
class DateTimeField(WritableField):
@@ -513,11 +551,11 @@ class DateTimeField(WritableField):
}
empty = None
input_formats = api_settings.DATETIME_INPUT_FORMATS
- output_format = api_settings.DATETIME_OUTPUT_FORMAT
+ format = api_settings.DATETIME_FORMAT
- def __init__(self, input_formats=None, output_format=None, *args, **kwargs):
+ def __init__(self, input_formats=None, format=None, *args, **kwargs):
self.input_formats = input_formats if input_formats is not None else self.input_formats
- self.output_format = output_format if output_format is not None else self.output_format
+ self.format = format if format is not None else self.format
super(DateTimeField, self).__init__(*args, **kwargs)
def from_native(self, value):
@@ -541,7 +579,7 @@ class DateTimeField(WritableField):
return value
for format in self.input_formats:
- if format.lower() == ISO8601:
+ if format.lower() == ISO_8601:
try:
parsed = parse_datetime(value)
except (ValueError, TypeError):
@@ -557,14 +595,13 @@ class DateTimeField(WritableField):
else:
return parsed
- datetime_input_formats = '; '.join(self.input_formats).replace(ISO8601, 'YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]')
- msg = self.error_messages['invalid'] % get_readable_date_format(datetime_input_formats)
+ msg = self.error_messages['invalid'] % readable_datetime_formats(self.input_formats)
raise ValidationError(msg)
def to_native(self, value):
- if self.output_format.lower() == ISO8601:
+ if self.format.lower() == ISO_8601:
return value.isoformat()
- return value.strftime(self.output_format)
+ return value.strftime(self.format)
class TimeField(WritableField):
@@ -577,11 +614,11 @@ class TimeField(WritableField):
}
empty = None
input_formats = api_settings.TIME_INPUT_FORMATS
- output_format = api_settings.TIME_OUTPUT_FORMAT
+ format = api_settings.TIME_FORMAT
- def __init__(self, input_formats=None, output_format=None, *args, **kwargs):
+ def __init__(self, input_formats=None, format=None, *args, **kwargs):
self.input_formats = input_formats if input_formats is not None else self.input_formats
- self.output_format = output_format if output_format is not None else self.output_format
+ self.format = format if format is not None else self.format
super(TimeField, self).__init__(*args, **kwargs)
def from_native(self, value):
@@ -592,7 +629,7 @@ class TimeField(WritableField):
return value
for format in self.input_formats:
- if format.lower() == ISO8601:
+ if format.lower() == ISO_8601:
try:
parsed = parse_time(value)
except (ValueError, TypeError):
@@ -608,16 +645,15 @@ class TimeField(WritableField):
else:
return parsed.time()
- time_input_formats = '; '.join(self.input_formats).replace(ISO8601, 'HH:MM[:ss[.uuuuuu]]')
- msg = self.error_messages['invalid'] % get_readable_date_format(time_input_formats)
+ msg = self.error_messages['invalid'] % readable_time_formats(self.input_formats)
raise ValidationError(msg)
def to_native(self, value):
if isinstance(value, datetime.datetime):
value = value.time()
- if self.output_format.lower() == ISO8601:
+ if self.format.lower() == ISO_8601:
return value.isoformat()
- return value.strftime(self.output_format)
+ return value.strftime(self.format)
class IntegerField(WritableField):
diff --git a/rest_framework/settings.py b/rest_framework/settings.py
index 02d751e1..eede0c5a 100644
--- a/rest_framework/settings.py
+++ b/rest_framework/settings.py
@@ -22,7 +22,7 @@ from __future__ import unicode_literals
from django.conf import settings
from django.utils import importlib
-from rest_framework import ISO8601
+from rest_framework import ISO_8601
from rest_framework.compat import six
@@ -82,19 +82,19 @@ DEFAULTS = {
# Input and output formats
'DATE_INPUT_FORMATS': (
- ISO8601,
+ ISO_8601,
),
- 'DATE_OUTPUT_FORMAT': ISO8601,
+ 'DATE_FORMAT': ISO_8601,
'DATETIME_INPUT_FORMATS': (
- ISO8601,
+ ISO_8601,
),
- 'DATETIME_OUTPUT_FORMAT': ISO8601,
+ 'DATETIME_FORMAT': ISO_8601,
'TIME_INPUT_FORMATS': (
- ISO8601,
+ ISO_8601,
),
- 'TIME_OUTPUT_FORMAT': ISO8601,
+ 'TIME_FORMAT': ISO_8601,
}
diff --git a/rest_framework/tests/fields.py b/rest_framework/tests/fields.py
index 17ef2f2c..28f18ed8 100644
--- a/rest_framework/tests/fields.py
+++ b/rest_framework/tests/fields.py
@@ -59,7 +59,7 @@ class BasicFieldTests(TestCase):
PK fields other than AutoField fields should not be read_only by default.
"""
serializer = CharPrimaryKeyModelSerializer()
- self.assertEquals(serializer.fields['id'].read_only, False)
+ self.assertEqual(serializer.fields['id'].read_only, False)
class DateFieldTest(TestCase):
@@ -134,7 +134,7 @@ class DateFieldTest(TestCase):
try:
f.from_native('1984-13-31')
except validators.ValidationError as e:
- self.assertEqual(e.messages, ["Date has wrong format. Use one of these formats instead: YYYY-MM-DD"])
+ self.assertEqual(e.messages, ["Date has wrong format. Use one of these formats instead: YYYY[-MM[-DD]]"])
else:
self.fail("ValidationError was not properly raised")
@@ -147,7 +147,7 @@ class DateFieldTest(TestCase):
try:
f.from_native('1984 -- 31')
except validators.ValidationError as e:
- self.assertEqual(e.messages, ["Date has wrong format. Use one of these formats instead: YYYY-MM-DD"])
+ self.assertEqual(e.messages, ["Date has wrong format. Use one of these formats instead: YYYY[-MM[-DD]]"])
else:
self.fail("ValidationError was not properly raised")
@@ -165,7 +165,7 @@ class DateFieldTest(TestCase):
"""
Make sure to_native() returns correct custom format.
"""
- f = serializers.DateField(output_format="%Y - %m.%d")
+ f = serializers.DateField(format="%Y - %m.%d")
result_1 = f.to_native(datetime.date(1984, 7, 31))
@@ -221,7 +221,7 @@ class DateTimeFieldTest(TestCase):
try:
f.from_native('1984-07-31 04:31:59')
except validators.ValidationError as e:
- self.assertEqual(e.messages, ["Datetime has wrong format. Use one of these formats instead: YYYY -- HH:MM"])
+ self.assertEqual(e.messages, ["Datetime has wrong format. Use one of these formats instead: YYYY -- hh:mm"])
else:
self.fail("ValidationError was not properly raised")
@@ -253,7 +253,7 @@ class DateTimeFieldTest(TestCase):
f.from_native('04:61:59')
except validators.ValidationError as e:
self.assertEqual(e.messages, ["Datetime has wrong format. Use one of these formats instead: "
- "YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]"])
+ "YYYY-MM-DDThh:mm[:ss[.uuuuuu]][+HHMM|-HHMM|Z]"])
else:
self.fail("ValidationError was not properly raised")
@@ -267,7 +267,7 @@ class DateTimeFieldTest(TestCase):
f.from_native('04 -- 31')
except validators.ValidationError as e:
self.assertEqual(e.messages, ["Datetime has wrong format. Use one of these formats instead: "
- "YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]"])
+ "YYYY-MM-DDThh:mm[:ss[.uuuuuu]][+HHMM|-HHMM|Z]"])
else:
self.fail("ValidationError was not properly raised")
@@ -291,7 +291,7 @@ class DateTimeFieldTest(TestCase):
"""
Make sure to_native() returns correct custom format.
"""
- f = serializers.DateTimeField(output_format="%Y - %H:%M")
+ f = serializers.DateTimeField(format="%Y - %H:%M")
result_1 = f.to_native(datetime.datetime(1984, 7, 31))
result_2 = f.to_native(datetime.datetime(1984, 7, 31, 4, 31))
@@ -353,7 +353,7 @@ class TimeFieldTest(TestCase):
try:
f.from_native('04:31:59')
except validators.ValidationError as e:
- self.assertEqual(e.messages, ["Time has wrong format. Use one of these formats instead: HH -- MM"])
+ self.assertEqual(e.messages, ["Time has wrong format. Use one of these formats instead: hh -- mm"])
else:
self.fail("ValidationError was not properly raised")
@@ -385,7 +385,7 @@ class TimeFieldTest(TestCase):
f.from_native('04:61:59')
except validators.ValidationError as e:
self.assertEqual(e.messages, ["Time has wrong format. Use one of these formats instead: "
- "HH:MM[:ss[.uuuuuu]]"])
+ "hh:mm[:ss[.uuuuuu]]"])
else:
self.fail("ValidationError was not properly raised")
@@ -399,7 +399,7 @@ class TimeFieldTest(TestCase):
f.from_native('04 -- 31')
except validators.ValidationError as e:
self.assertEqual(e.messages, ["Time has wrong format. Use one of these formats instead: "
- "HH:MM[:ss[.uuuuuu]]"])
+ "hh:mm[:ss[.uuuuuu]]"])
else:
self.fail("ValidationError was not properly raised")
@@ -420,11 +420,11 @@ class TimeFieldTest(TestCase):
"""
Make sure to_native() returns correct custom format.
"""
- f = serializers.TimeField(output_format="%H - %S [%f]")
+ f = serializers.TimeField(format="%H - %S [%f]")
result_1 = f.to_native(datetime.time(4, 31))
result_2 = f.to_native(datetime.time(4, 31, 59))
result_3 = f.to_native(datetime.time(4, 31, 59, 200))
self.assertEqual('04 - 00 [000000]', result_1)
self.assertEqual('04 - 59 [000000]', result_2)
- self.assertEqual('04 - 59 [000200]', result_3) \ No newline at end of file
+ self.assertEqual('04 - 59 [000200]', result_3)
diff --git a/rest_framework/utils/dates.py b/rest_framework/utils/dates.py
deleted file mode 100644
index f094f72d..00000000
--- a/rest_framework/utils/dates.py
+++ /dev/null
@@ -1,14 +0,0 @@
-def get_readable_date_format(date_format):
- mapping = [("%Y", "YYYY"),
- ("%y", "YY"),
- ("%m", "MM"),
- ("%b", "[Jan through Dec]"),
- ("%B", "[January through December]"),
- ("%d", "DD"),
- ("%H", "HH"),
- ("%M", "MM"),
- ("%S", "SS"),
- ("%f", "uuuuuu")]
- for k, v in mapping:
- date_format = date_format.replace(k, v)
- return date_format \ No newline at end of file