Index: django/db/models/fields/__init__.py
===================================================================
--- django/db/models/fields/__init__.py	(revision 10734)
+++ django/db/models/fields/__init__.py	(working copy)
@@ -636,6 +636,54 @@
         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 value and not isinstance(value, datetime.timedelta):
+            value = datetime.timedelta(microseconds=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):
+        if value is None:
+            return None
+        if not isinstance(value, datetime.timedelta):
+            value = datetime.timedelta(microseconds=value)
+        return connection.ops.value_to_db_decimal(value.days * 24 * 3600 * 1000000 + value.seconds * 1000000 + value.microseconds, 20, 0) # max value 86399999999999999999 microseconds
+
+    def to_python(self, value):
+        if isinstance(value, datetime.timedelta):
+            return value
+        try:
+            return datetime.timedelta(microseconds=float(value))
+        except (TypeError, ValueError):
+            raise exceptions.ValidationError('The value must be an integer.')
+        except OverflowError:
+            raise exceptions.ValidationError('The maximum allowed value is %s' % datetime.timedelta.max)
+
+    def formfield(self, form_class=forms.DurationField, **kwargs):
+        return super(DurationField, self).formfield(form_class, **kwargs)
+
 class EmailField(CharField):
     def __init__(self, *args, **kwargs):
         kwargs['max_length'] = kwargs.get('max_length', 75)
Index: django/forms/fields.py
===================================================================
--- django/forms/fields.py	(revision 10734)
+++ django/forms/fields.py	(working copy)
@@ -26,6 +26,7 @@
 import django.core.exceptions
 from django.utils.translation import ugettext_lazy as _
 from django.utils.encoding import smart_unicode, smart_str
+from django.utils.datastructures import SortedDict
 
 from util import ErrorList, ValidationError
 from widgets import TextInput, PasswordInput, HiddenInput, MultipleHiddenInput, FileInput, CheckboxInput, Select, NullBooleanSelect, SelectMultiple, DateInput, DateTimeInput, TimeInput, SplitDateTimeWidget, SplitHiddenDateTimeWidget
@@ -40,7 +41,7 @@
     'BooleanField', 'NullBooleanField', 'ChoiceField', 'MultipleChoiceField',
     'ComboField', 'MultiValueField', 'FloatField', 'DecimalField',
     'SplitDateTimeField', 'IPAddressField', 'FilePathField', 'SlugField',
-    'TypedChoiceField'
+    'TypedChoiceField', 'DurationField',
 )
 
 # These values, if given to to_python(), will trigger the self.required check.
@@ -885,6 +886,79 @@
             return datetime.datetime.combine(*data_list)
         return None
 
+class DurationField(Field):
+    default_error_messages = {
+        'invalid': _(u'Enter a valid duration.'),
+        'min_value': _(u'Ensure this value is greater than or equal to %(min)s.'),
+        'max_value': _(u'Ensure this value is less than or equal to %(max)s.'),
+    }
+    values_in_microseconds = SortedDict((
+        ('y', 31556925993600), # 52.177457 * (7*24*60*60*1000*1000)
+        ('m', 2629743828768), # 4.34812141 * (7*24*60*60*1000*1000)
+        ('w', 604800000000), # 7*24*60*60*1000*1000
+        ('d', 86400000000), # 24*60*60*1000*1000
+        ('h', 3600000000), # 60*60*1000*1000
+        ('min', 60000000), # 60*1000*1000
+        ('s', 1000000), # 1000*1000
+        ('ms', 1000),
+        ('mis', 1),
+    ))
+
+    def __init__(self, min_value=None, max_value=None, *args, **kwargs):
+        super(DurationField, self).__init__(*args, **kwargs)
+        self.min_value, self.max_value = min_value, max_value
+
+    def to_timedelta(self, value):
+        """
+        Takes an Unicode value and converts it to a datetime.timedelta object.
+        1y 7m 6w 3d 18h 30min 23s 10ms 150mis => 
+         1 year 7 months 6 weeks 3 days 18 hours 30 minutes 23 seconds 10 milliseconds 150 microseconds
+         => datetime.timedelta(624, 6155, 805126)
+        """
+        if not value:
+            return datetime.timedelta(microseconds=0)
+
+        pairs = []
+        for b in value.lower().split():
+            for index, char in enumerate(b):
+                if not char.isdigit():
+                    pairs.append((b[:index], b[index:])) #digits, letters
+                    break
+        if not pairs:
+            raise ValidationError(self.error_messages['invalid'])
+
+        microseconds = 0
+        for digits, chars in pairs:
+            if not digits or not chars:
+                raise ValidationError(self.error_messages['invalid'])
+            microseconds += int(digits) * self.values_in_microseconds[chars]
+
+        return datetime.timedelta(microseconds=microseconds)
+
+    def from_timedelta(self, value):
+        if not value:
+            return u"0 sec"
+        vals = []
+        mis = value.days * 24 * 3600 * 1000000 + value.seconds * 1000000 + value.microseconds
+        for k in self.values_in_microseconds:
+            if mis >= self.values_in_microseconds[k]:
+                diff, mis = divmod(mis, self.values_in_microseconds[k])
+                vals.append("%d%s" % (diff, k))
+        return u" ".join(vals)
+
+    def clean(self, value):
+        "Validates max_value and min_value. Returns a datetime.timedelta object."
+        value = self.to_timedelta(value)
+
+        if self.max_value is not None and value > self.max_value:
+            raise ValidationError(self.error_messages['max_value'] % {'max': self.max_value})
+
+        if self.min_value is not None and value < self.min_value:
+            raise ValidationError(self.error_messages['min_value'] % {'min': self.min_value})
+
+        return value
+
+
 ipv4_re = re.compile(r'^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$')
 
 class IPAddressField(RegexField):
