Index: django/db/models/fields/__init__.py
===================================================================
--- django/db/models/fields/__init__.py	(revision 6638)
+++ django/db/models/fields/__init__.py	(working copy)
@@ -686,6 +686,63 @@
         defaults.update(kwargs)
         return super(DecimalField, self).formfield(**defaults)
 
+class DurationProxy(object):
+    def __init__(self, field):
+        self.field_name = field.name
+
+    def __get__(self, instance=None, owner=None):
+        if instance is None:
+            raise AttributeError, "%s can only be accessed from %s instances." % (self.field_name, owner.__name__)
+        if self.field_name not in instance.__dict__:
+            return None
+        return instance.__dict__[self.field_name]
+
+    def __set__(self, instance, value):
+        if not isinstance(value, datetime.timedelta):
+            value = datetime.timedelta(seconds=float(value))
+        instance.__dict__[self.field_name] = value
+
+class DurationField(Field):
+    def __init__(self, *args, **kwargs):
+        super(DurationField, self).__init__(*args, **kwargs)
+        self.max_digits, self.decimal_places = 20, 6
+
+    def get_internal_type(self):
+        return "DecimalField"
+
+    def contribute_to_class(self, cls, name):
+        super(DurationField, self).contribute_to_class(cls, name)
+        setattr(cls, name, DurationProxy(self))
+
+    def get_db_prep_save(self, value):
+        print 'DurationField.get_db_prep_save'
+        if value is None:
+            return None
+        return str(value.days * 24 * 3600 + value.seconds + float(value.microseconds) / 1000000)
+
+    def to_python(self, value):
+        if isinstance(value, datetime.timedelta):
+            return value
+        try:
+            return datetime.timedelta(seconds=float(value))
+        except (TypeError, ValueError):
+            raise validators.ValidationError('This value must be a real number.')
+        except OverflowError:
+            raise validators.ValidationError('The maximum allowed value is %s' % datetime.timedelta.max)
+
+    def flatten_data(self, follow, obj=None):
+        print 'DurationField.flatten_data'
+        val = self._get_val_from_obj(obj)
+        if val is None or val is '':
+            return ''
+        return {self.name: self.get_db_prep_save(val)}
+
+    def formfield(self, form_class=forms.DurationField, **kwargs):
+        return super(DurationField, self).formfield(form_class, **kwargs)
+
+    def get_manipulator_field_objs(self):
+        return [curry(oldforms.DecimalField, max_digits=self.max_digits, decimal_places=self.decimal_places)]
+
 class EmailField(CharField):
     def __init__(self, *args, **kwargs):
         kwargs['max_length'] = kwargs.get('max_length', 75)
Index: django/newforms/fields.py
===================================================================
--- django/newforms/fields.py	(revision 6638)
+++ django/newforms/fields.py	(working copy)
@@ -20,7 +20,7 @@
 from django.utils.encoding import StrAndUnicode, smart_unicode
 
 from util import ErrorList, ValidationError
-from widgets import TextInput, PasswordInput, HiddenInput, MultipleHiddenInput, FileInput, CheckboxInput, Select, NullBooleanSelect, SelectMultiple, DateTimeInput
+from widgets import TextInput, PasswordInput, HiddenInput, MultipleHiddenInput, FileInput, CheckboxInput, Select, NullBooleanSelect, SelectMultiple, DateTimeInput, DurationWidget
 
 
 __all__ = (
@@ -31,7 +31,7 @@
     'RegexField', 'EmailField', 'FileField', 'ImageField', 'URLField',
     'BooleanField', 'NullBooleanField', 'ChoiceField', 'MultipleChoiceField',
     'ComboField', 'MultiValueField', 'FloatField', 'DecimalField',
-    'SplitDateTimeField', 'IPAddressField',
+    'SplitDateTimeField', 'IPAddressField', 'DurationField',
 )
 
 # These values, if given to to_python(), will trigger the self.required check.
@@ -753,3 +753,30 @@
 
     def __init__(self, *args, **kwargs):
         super(IPAddressField, self).__init__(ipv4_re, *args, **kwargs)
+
+class DurationField(MultiValueField):
+    widget = DurationWidget
+
+    def __init__(self, *args, **kwargs):
+        errors = self.default_error_messages.copy()
+        fields = (
+            IntegerField(max_value=999999999, min_value=-999999999),
+            IntegerField(label='Hours', max_value=23, min_value=0),
+            IntegerField(label='Minutes', max_value=59, min_value=0),
+            IntegerField(label='Seconds', max_value=59, min_value=0),
+            IntegerField(label='Microseconds', max_value=999999, min_value=0),
+        )
+        super(DurationField, self).__init__(fields, *args, **kwargs)
+
+    def compress(self, data_list):
+        if data_list == [None] * 5:
+            raise ValidationError(gettext(u'This field is required.'))
+        if data_list:
+            return datetime.timedelta(
+                days=data_list[0] or 0,
+                hours=data_list[1] or 0,
+                minutes=data_list[2] or 0,
+                seconds=data_list[3] or 0,
+                microseconds=data_list[4] or 0,
+            )
+        return None
Index: django/newforms/widgets.py
===================================================================
--- django/newforms/widgets.py	(revision 6638)
+++ django/newforms/widgets.py	(working copy)
@@ -22,6 +22,7 @@
     'FileInput', 'DateTimeInput', 'Textarea', 'CheckboxInput',
     'Select', 'NullBooleanSelect', 'SelectMultiple', 'RadioSelect',
     'CheckboxSelectMultiple', 'MultiWidget', 'SplitDateTimeWidget',
+    'DurationWidget',
 )
 
 class Widget(object):
@@ -450,3 +451,25 @@
         if value:
             return [value.date(), value.time().replace(microsecond=0)]
         return [None, None]
+
+class DurationWidget(MultiWidget):
+    def __init__(self, attrs=None):
+        attrs = attrs or {}
+        widgets = (
+            TextInput(attrs=dict(attrs, size=4, maxlength=10, title='Days')),
+            TextInput(attrs=dict(attrs, size=1, maxlength=2, title='Hours')),
+            TextInput(attrs=dict(attrs, size=1, maxlength=2, title='Minutes')),
+            TextInput(attrs=dict(attrs, size=1, maxlength=2, title='Seconds')),
+            TextInput(attrs=dict(attrs, size=5, maxlength=6, title='Microseconds')),
+        )
+        super(DurationWidget, self).__init__(widgets, attrs)
+
+    def decompress(self, value):
+        if value:
+            hours, seconds = divmod(value.seconds, 3600)
+            minutes, seconds = divmod(seconds, 60)
+            return [value.days, hours, minutes, seconds, value.microseconds]
+        return [None, None, None, None, None]
+
+    def format_output(self, rendered_widgets):
+        return u'%s days, %s : %s : %s . %s' % tuple(rendered_widgets)
Index: docs/model-api.txt
===================================================================
--- docs/model-api.txt	(revision 6638)
+++ docs/model-api.txt	(working copy)
@@ -218,6 +218,17 @@
 
 The admin represents this as an ``<input type="text">`` (a single-line input).
 
+``DurationField``
+~~~~~~~~~~~~~~~~~
+
+**New in Django development version**
+
+A span of time, represented in Python by a ``timedelta`` instance.
+
+The admin represents this as an ``<input type="text">`` (a single-line input),
+with its value representing the number of seconds in the duration. Fractional
+values are allowed, with a millisecond precision.
+
 ``EmailField``
 ~~~~~~~~~~~~~~
 
Index: docs/newforms.txt
===================================================================
--- docs/newforms.txt	(revision 6638)
+++ docs/newforms.txt	(working copy)
@@ -1275,6 +1275,23 @@
 permitted in the value, whilst ``decimal_places`` is the maximum number of
 decimal places permitted.
 
+``DurationField``
+~~~~~~~~~~~~~~~~~
+
+**New in Django development version**
+
+    * Default widget: ``DurationWidget``
+    * Empty value: ``None``
+    * Normalizes to: A Python ``datetime.timedelta`` object
+    * Validates that the given value is a length of time, such as 24 hours in a
+      day, 60 minutes in an hour, and 60 seconds in a minute.
+
+A span of time, represented in Python by a ``timedelta`` instance.
+
+The admin represents this as an ``<input type="text">`` (a single-line input),
+with its value representing the number of seconds in the duration. Fractional
+values are allowed, with a millisecond precision.
+
 ``EmailField``
 ~~~~~~~~~~~~~~
 
@@ -1618,10 +1635,12 @@
     ``MultiWidget``               Wrapper around multiple other widgets
     ``SplitDateTimeWidget``       Wrapper around two ``TextInput`` widgets:
                                   one for the Date, and one for the Time.
+    ``DurationWidget``            A set of 5 ``TextInput`` widgets arranged
+                                  as ``[   ] days, [ ]:[ ]:[ ].[    ]``
     ============================  ===========================================
 
-**New in Django development version:** The ``DateTimeInput`` has been added
-since the last release.
+**New in Django development version:** The ``DateTimeInput`` and
+``DurationWidget`` have been added since the last release.
 
 Specifying widgets
 ------------------
