diff --git a/django/forms/models.py b/django/forms/models.py
index 7ca1ab5..7a33ab8 100644
--- a/django/forms/models.py
+++ b/django/forms/models.py
@@ -315,6 +315,61 @@ class BaseModelForm(BaseForm):
                 for field_name in unique_check:
                     bad_fields.add(field_name)
 
+        # we do a second round of checks to see if we need to do validation for
+        # any unique_for_<date/year/moth>
+        unique_checks = []
+        for name, field in self.fields.items():
+            try:
+                f = self.instance._meta.get_field_by_name(name)[0]
+            except FieldDoesNotExist:
+                # This is an extra field that's not on the ModelForm, ignore it
+                continue
+            if not isinstance(f, ModelField):
+                # This is an extra field that happens to have a name that matches,
+                # for example, a related object accessor for this model.  So
+                # get_field_by_name found it, but it is not a Field so do not proceed
+                # to use it as if it were.
+                continue
+            if self.cleaned_data.get(name) is None:
+                continue
+            if f.unique_for_date and self.cleaned_data.get(f.unique_for_date) is not None:
+                unique_checks.append(('date', name, f.unique_for_date))
+            if f.unique_for_year and self.cleaned_data.get(f.unique_for_year) is not None:
+                unique_checks.append(('year', name, f.unique_for_year))
+            if f.unique_for_month and self.cleaned_data.get(f.unique_for_month) is not None:
+                unique_checks.append(('month', name, f.unique_for_month))
+
+        for lookup_type, field, unique_for in unique_checks:
+            lookup_kwargs = {}
+            # there's a ticket to add a date lookup, we can remove this special
+            # case if that makes it's way in
+            if lookup_type == 'date':
+                date = self.cleaned_data[unique_for]
+                lookup_kwargs['%s__day' % unique_for] = date.day
+                lookup_kwargs['%s__month' % unique_for] = date.month
+                lookup_kwargs['%s__year' % unique_for] = date.year
+            else:
+                lookup_kwargs['%s__%s' % (unique_for, lookup_type)] = getattr(self.cleaned_data[unique_for], lookup_type)
+            lookup_kwargs[field] = self.cleaned_data[field]
+
+            qs = self.instance.__class__._default_manager.filter(**lookup_kwargs)
+            # Exclude the current object from the query if we are editing an
+            # instance (as opposed to creating a new one)
+            if self.instance.pk is not None:
+                qs = qs.exclude(pk=self.instance.pk)
+
+            # This cute trick with extra/values is the most efficient way to
+            # tell if a particular query returns any results.
+            if qs.extra(select={'a': 1}).values('a').order_by():
+                self._errors[field] = ErrorList([
+                    _(u"%(field_name)s must be unique for %(date_field)s %(lookup)s.") % {
+                        'field_name': unicode(self.fields[field].label),
+                        'date_field': unicode(self.fields[unique_for].label),
+                        'lookup': lookup_type,
+                    }
+                ])
+                bad_fields.add(field)
+
         for field_name in bad_fields:
             del self.cleaned_data[field_name]
         if form_errors:
diff --git a/tests/modeltests/model_forms/models.py b/tests/modeltests/model_forms/models.py
index 992bb90..d5353ae 100644
--- a/tests/modeltests/model_forms/models.py
+++ b/tests/modeltests/model_forms/models.py
@@ -189,6 +189,15 @@ class ExplicitPK(models.Model):
     def __unicode__(self):
         return self.key
 
+class Post(models.Model):
+    title = models.CharField(max_length=50, unique_for_date='posted', blank=True)
+    slug = models.CharField(max_length=50, unique_for_year='posted', blank=True)
+    subtitle = models.CharField(max_length=50, unique_for_month='posted', blank=True)
+    posted = models.DateField()
+
+    def __unicode__(self):
+        return self.name
+
 __test__ = {'API_TESTS': """
 >>> from django import forms
 >>> from django.forms.models import ModelForm, model_to_dict
@@ -1472,6 +1481,38 @@ ValidationError: [u'Select a valid choice. z is not one of the available choices
 <tr><th><label for="id_description">Description:</label></th><td><input type="text" name="description" id="id_description" /></td></tr>
 <tr><th><label for="id_url">The URL:</label></th><td><input id="id_url" type="text" name="url" maxlength="40" /></td></tr>
 
+### validation on unique_for_date
+
+>>> p = Post.objects.create(title="Django 1.0 is released", slug="Django 1.0", subtitle="Finally", posted=datetime.date(2008, 9, 3))
+>>> class PostForm(ModelForm):
+...     class Meta:
+...         model = Post
+
+>>> f = PostForm({'title': "Django 1.0 is released", 'posted': '2008-09-03'})
+>>> f.is_valid()
+False
+>>> f.errors
+{'title': [u'Title must be unique for Posted date.']}
+>>> f = PostForm({'title': "Work on Django 1.1 begins", 'posted': '2008-09-03'})
+>>> f.is_valid()
+True
+>>> f = PostForm({'title': "Django 1.0 is released", 'posted': '2008-09-04'})
+>>> f.is_valid()
+True
+>>> f = PostForm({'slug': "Django 1.0", 'posted': '2008-01-01'})
+>>> f.is_valid()
+False
+>>> f.errors
+{'slug': [u'Slug must be unique for Posted year.']}
+>>> f = PostForm({'subtitle': "Finally", 'posted': '2008-09-30'})
+>>> f.is_valid()
+False
+>>> f.errors
+{'subtitle': [u'Subtitle must be unique for Posted month.']}
+>>> f = PostForm({'subtitle': "Finally", "title": "Django 1.0 is released", "slug": "Django 1.0", 'posted': '2008-09-03'}, instance=p)
+>>> f.is_valid()
+True
+
 # Clean up
 >>> import shutil
 >>> shutil.rmtree(temp_storage_dir)
