changeset 13212:5d0a30fad7de stable

date: fix matching of underspecified date ranges (backport of 91bc001a592f to stable)
author Matt Mackall <mpm@selenic.com>
date Wed, 29 Dec 2010 14:19:31 -0600
parents 650314ed845d
children 3eee7b42d17e 5bcb6c9d16db
files mercurial/util.py tests/test-doctest.py
diffstat 2 files changed, 40 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/util.py	Mon Dec 27 01:12:31 2010 +0100
+++ b/mercurial/util.py	Wed Dec 29 14:19:31 2010 -0600
@@ -1077,11 +1077,16 @@
         date = " ".join(string.split()[:-1])
 
     # add missing elements from defaults
-    for part in defaults:
+    usenow = False # default to using biased defaults
+    for part in ("S", "M", "HI", "d", "mb", "yY"): # decreasing specificity
         found = [True for p in part if ("%"+p) in format]
         if not found:
-            date += "@" + defaults[part]
+            date += "@" + defaults[part][usenow]
             format += "@%" + part[0]
+        else:
+            # We've found a specific time element, less specific time
+            # elements are relative to today
+            usenow = True
 
     timetuple = time.strptime(date, format)
     localunixtime = int(calendar.timegm(timetuple))
@@ -1093,8 +1098,8 @@
         unixtime = localunixtime + offset
     return unixtime, offset
 
-def parsedate(date, formats=None, defaults=None):
-    """parse a localized date/time string and return a (unixtime, offset) tuple.
+def parsedate(date, formats=None, bias={}):
+    """parse a localized date/time and return a (unixtime, offset) tuple.
 
     The date may be a "unixtime offset" string or in one of the specified
     formats. If the date already is a (unixtime, offset) tuple, it is returned.
@@ -1110,15 +1115,22 @@
         when, offset = map(int, date.split(' '))
     except ValueError:
         # fill out defaults
-        if not defaults:
-            defaults = {}
         now = makedate()
+        defaults = {}
+        nowmap = {}
         for part in "d mb yY HI M S".split():
-            if part not in defaults:
+            # this piece is for rounding the specific end of unknowns
+            b = bias.get(part)
+            if b is None:
                 if part[0] in "HMS":
-                    defaults[part] = "00"
+                    b = "00"
                 else:
-                    defaults[part] = datestr(now, "%" + part[0])
+                    b = "0"
+
+            # this piece is for matching the generic end to today's date
+            n = datestr(now, "%" + part[0])
+
+            defaults[part] = (b, n)
 
         for format in formats:
             try:
@@ -1152,6 +1164,22 @@
 
     '>{date}' on or after a given date
 
+    >>> p1 = parsedate("10:29:59")
+    >>> p2 = parsedate("10:30:00")
+    >>> p3 = parsedate("10:30:59")
+    >>> p4 = parsedate("10:31:00")
+    >>> p5 = parsedate("Sep 15 10:30:00 1999")
+    >>> f = matchdate("10:30")
+    >>> f(p1[0])
+    False
+    >>> f(p2[0])
+    True
+    >>> f(p3[0])
+    True
+    >>> f(p4[0])
+    False
+    >>> f(p5[0])
+    False
     """
 
     def lower(date):
--- a/tests/test-doctest.py	Mon Dec 27 01:12:31 2010 +0100
+++ b/tests/test-doctest.py	Wed Dec 29 14:19:31 2010 -0600
@@ -16,5 +16,8 @@
 import mercurial.url
 doctest.testmod(mercurial.url)
 
+import mercurial.util
+doctest.testmod(mercurial.util)
+
 import hgext.convert.cvsps
 doctest.testmod(hgext.convert.cvsps)