### Eclipse Workspace Patch 1.0
#P Django trunk
Index: django/db/models/sql/where.py
===================================================================
--- django/db/models/sql/where.py	(revision 11447)
+++ django/db/models/sql/where.py	(working copy)
@@ -176,7 +176,7 @@
                 return ('%s IN %s' % (field_sql, extra), params)
             return ('%s IN (%s)' % (field_sql, ', '.join(['%s'] * len(params))),
                     params)
-        elif lookup_type in ('range', 'year'):
+        elif lookup_type in ('range', 'year', 'date'):
             return ('%s BETWEEN %%s and %%s' % field_sql, params)
         elif lookup_type in ('month', 'day', 'week_day'):
             return ('%s = %%s' % connection.ops.date_extract_sql(lookup_type, field_sql),
Index: django/db/models/sql/constants.py
===================================================================
--- django/db/models/sql/constants.py	(revision 11447)
+++ django/db/models/sql/constants.py	(working copy)
@@ -4,8 +4,8 @@
 QUERY_TERMS = dict([(x, None) for x in (
     'exact', 'iexact', 'contains', 'icontains', 'gt', 'gte', 'lt', 'lte', 'in',
     'startswith', 'istartswith', 'endswith', 'iendswith', 'range', 'year',
-    'month', 'day', 'week_day', 'isnull', 'search', 'regex', 'iregex',
-    )])
+    'month', 'day', 'week_day', 'date', 'isnull', 'search', 'regex', 'iregex', 
+)])
 
 # Size of each "chunk" for get_iterator calls.
 # Larger values are slightly faster at the expense of more storage space.
Index: django/db/models/fields/__init__.py
===================================================================
--- django/db/models/fields/__init__.py	(revision 11447)
+++ django/db/models/fields/__init__.py	(working copy)
@@ -220,6 +220,9 @@
             return ["%%%s" % connection.ops.prep_for_like_query(value)]
         elif lookup_type == 'isnull':
             return []
+        elif lookup_type == 'date':
+            return self.get_db_prep_lookup('range', (datetime.datetime.combine(value, datetime.time.min),
+                                                     datetime.datetime.combine(value, datetime.time.max)))
         elif lookup_type == 'year':
             try:
                 value = int(value)
Index: tests/modeltests/lookup/models.py
===================================================================
--- tests/modeltests/lookup/models.py	(revision 11447)
+++ tests/modeltests/lookup/models.py	(working copy)
@@ -16,6 +16,11 @@
     def __unicode__(self):
         return self.headline
 
+class Comment(models.Model):
+    article = models.ForeignKey(Article)
+    comment = models.TextField()
+    date = models.DateTimeField()
+
 __test__ = {'API_TESTS': r"""
 # Create a couple of Articles.
 >>> from datetime import datetime
@@ -173,7 +178,7 @@
 >>> Article.objects.extra(select={'id_plus_one': 'id + 1'}).values('id', 'id_plus_two')
 Traceback (most recent call last):
     ...
-FieldError: Cannot resolve keyword 'id_plus_two' into field. Choices are: headline, id, id_plus_one, pub_date
+FieldError: Cannot resolve keyword 'id_plus_two' into field. Choices are: comment, headline, id, id_plus_one, pub_date
 
 # If you don't specify field names to values(), all are returned.
 >>> list(Article.objects.filter(id=5).values()) == [{'id': 5, 'headline': 'Article 5', 'pub_date': datetime(2005, 8, 1, 9, 0)}]
@@ -293,7 +298,7 @@
 >>> Article.objects.filter(pub_date_year='2005').count()
 Traceback (most recent call last):
     ...
-FieldError: Cannot resolve keyword 'pub_date_year' into field. Choices are: headline, id, pub_date
+FieldError: Cannot resolve keyword 'pub_date_year' into field. Choices are: comment, headline, id, pub_date
 
 >>> Article.objects.filter(headline__starts='Article')
 Traceback (most recent call last):
@@ -390,10 +395,33 @@
 [<Article: bar>, <Article: barfoobaz>, <Article: bazbaRFOO>, <Article: foobar>, <Article: foobarbaz>]
 """
 
-
 if settings.DATABASE_ENGINE != 'mysql':
     __test__['API_TESTS'] += r"""
 # grouping and backreferences
 >>> Article.objects.filter(headline__regex=r'b(.).*b\1')
 [<Article: barfoobaz>, <Article: bazbaRFOO>, <Article: foobarbaz>]
 """
+
+__test__['API_TESTS'] += r"""
+# The __date lookup tests for datetime equality without the time
+>>> def create_datelookup_article(title, d):
+...     Article.objects.create(pub_date=d, headline="datelookup %s" % title)
+>>> create_datelookup_article(1, datetime(2008, 11, 14))
+>>> create_datelookup_article(2, datetime(2008, 11, 14, 23, 59, 59))
+>>> create_datelookup_article(3, datetime(2008, 11, 15))
+>>> articles = Article.objects.filter(headline__startswith='datelookup')
+
+>>> for i in xrange(4):
+...     day = datetime(2008, 11, (13+i), i)
+...     print '%s: %s' % (day.date(), articles.filter(pub_date__date=day))
+2008-11-13: []
+2008-11-14: [<Article: datelookup 2>, <Article: datelookup 1>]
+2008-11-15: [<Article: datelookup 3>]
+2008-11-16: []
+
+# Test that the __date lookup doesn't swallow date fields.
+>>> comment = articles[0].comment_set.create(comment='test', date=datetime(2008, 11, 16))
+>>> print articles.filter(comment__date=datetime(2008, 11, 16))
+[<Article: datelookup 3>]
+"""
+
Index: docs/ref/models/querysets.txt
===================================================================
--- docs/ref/models/querysets.txt	(revision 11447)
+++ docs/ref/models/querysets.txt	(working copy)
@@ -1402,6 +1402,20 @@
 You can use ``range`` anywhere you can use ``BETWEEN`` in SQL -- for dates,
 numbers and even characters.
 
+date
+~~~~
+
+Tests datetime fields for date equality, disregarding time.
+
+Example::
+
+    yesterday = datetime.date.today() - datetime.timedelta(1)
+    Entry.objects.filter(pub_datetime__date = yesterday)
+
+SQL equivalent::
+
+    SELECT ... WHERE pub_datetime BETWEEN '2008-11-12 00:00:00' AND '2008-11-12 23:59:59';
+
 year
 ~~~~
 
