Index: django/utils/timesince.py
===================================================================
--- django/utils/timesince.py	(revision 3008)
+++ django/utils/timesince.py	(working copy)
@@ -47,10 +47,11 @@
             s += ', %d %s' % (count2, name2(count2))
     return s
 
-def timeuntil(d):
+def timeuntil(d, now=None):
     """
     Like timesince, but returns a string measuring the time until
     the given time.
     """
-    now = datetime.datetime.now()
+    if now == None:
+        now = datetime.datetime.now()
     return timesince(now, d)
Index: django/template/defaultfilters.py
===================================================================
--- django/template/defaultfilters.py	(revision 3008)
+++ django/template/defaultfilters.py	(working copy)
@@ -341,11 +341,24 @@
         arg = settings.TIME_FORMAT
     return time_format(value, arg)
 
-def timesince(value):
+def timesince(value, arg=None):
     'Formats a date as the time since that date (i.e. "4 days, 6 hours")'
     from django.utils.timesince import timesince
-    return timesince(value)
+    if arg:
+        return timesince(arg, value)
+    else:
+        return timesince(value)
 
+def timeuntil(value, arg=None):
+    'Formats a date as the time until that date (i.e. "4 days, 6 hours")'
+    from django.utils.timesince import timesince
+    from datetime import datetime
+    if arg:
+        return timesince(value, arg)
+    else:
+        return timesince(value, datetime.now())
+
+
 ###################
 # LOGIC           #
 ###################
@@ -479,6 +492,7 @@
 register.filter(striptags)
 register.filter(time)
 register.filter(timesince)
+register.filter(timeuntil)
 register.filter(title)
 register.filter(truncatewords)
 register.filter(unordered_list)
Index: tests/othertests/templates.py
===================================================================
--- tests/othertests/templates.py	(revision 3008)
+++ tests/othertests/templates.py	(working copy)
@@ -4,7 +4,7 @@
 from django import template
 from django.template import loader
 from django.utils.translation import activate, deactivate, install
-from datetime import datetime
+from datetime import datetime, timedelta
 import traceback
 
 #################################
@@ -57,6 +57,9 @@
     def method(self):
         return "OtherClass.method"
 
+# NOW used by timesince tag tests.
+NOW = datetime.now()
+
 # SYNTAX --
 # 'template_name': ('template contents', 'context dict', 'expected string output' or Exception class)
 TEMPLATE_TESTS = {
@@ -449,6 +452,24 @@
     'now02' : ('{% now "j "n" Y"%}', {}, template.TemplateSyntaxError),
 #    'now03' : ('{% now "j \"n\" Y"%}', {}, str(datetime.now().day) + '"' + str(datetime.now().month) + '"' + str(datetime.now().year)),
 #    'now04' : ('{% now "j \nn\n Y"%}', {}, str(datetime.now().day) + '\n' + str(datetime.now().month) + '\n' + str(datetime.now().year))
+
+    ### TIMESINCE TAG ##################################################
+    # Default compare with datetime.now()
+    'timesince01' : ('{{ a|timesince }}', {'a':datetime.now()}, '0 minutes'),
+    'timesince02' : ('{{ a|timesince }}', {'a':(datetime.now() - timedelta(days=1))}, '1 day'),
+
+    # Compare to a given parameter
+    'timesince03' : ('{{ a|timesince:b }}', {'a':NOW + timedelta(days=2), 'b':NOW + timedelta(days=1)}, '1 day'),
+    'timesince04' : ('{{ a|timesince:b }}', {'a':NOW + timedelta(days=2), 'b':NOW + timedelta(days=2)}, '0 minutes'),
+
+    ### TIMEUNTIL TAG ##################################################
+    # Default compare with datetime.now()
+    'timeuntil01' : ('{{ a|timeuntil }}', {'a':datetime.now()}, '0 minutes'),
+    'timeuntil02' : ('{{ a|timeuntil }}', {'a':(datetime.now() - timedelta(days=1))}, '1 day'),
+
+    # Compare to a given parameter
+    'timeuntil03' : ('{{ a|timeuntil:b }}', {'a':NOW - timedelta(days=2), 'b':NOW - timedelta(days=1)}, '1 day'),
+    'timeuntil04' : ('{{ a|timeuntil:b }}', {'a':NOW - timedelta(days=2), 'b':NOW - timedelta(days=2)}, '0 minutes'),
 }
 
 def test_template_loader(template_name, template_dirs=None):
