bug 450695 - Pushlog date query should accept ISO dates without minutes/seconds
authorTed Mielczarek <ted.mielczarek@gmail.com>
Mon, 24 Nov 2008 10:22:40 -0500
changeset 54 e955a1f05004
parent 53 959e0ddb4133
child 55 6db4ef76c839
push id28
push usertmielczarek@mozilla.com
push dateMon, 24 Nov 2008 15:22:49 +0000
bugs450695
bug 450695 - Pushlog date query should accept ISO dates without minutes/seconds
pushlog-feed.py
runtests.py
--- a/pushlog-feed.py
+++ b/pushlog-feed.py
@@ -144,17 +144,17 @@ class PushlogQuery:
             except sqlite.OperationalError:
                 # likely just an empty db, so return an empty result
                 pass
 
     def description(self):
         if self.querystart == QueryType.COUNT and not self.userquery and not self.changesetquery:
             return ''
         bits = []
-        isotime = lambda x: datetime.utcfromtimestamp(x).isoformat(' ')
+        isotime = lambda x: datetime.fromtimestamp(x).isoformat(' ')
         if self.querystart == QueryType.DATE:
             bits.append('after %s' % isotime(self.querystart_value))
         elif self.querystart == QueryType.CHANGESET:
             bits.append('after changeset %s' % self.querystart_value)
         elif self.querystart == QueryType.PUSHID:
             bits.append('after push ID %s' % self.querystart_value)
 
         if self.queryend == QueryType.DATE:
@@ -182,19 +182,28 @@ def localdate(ts):
         offset = time.altzone
     return (ts, offset)
 
 def doParseDate(datestring):
     """Given a date string, try to parse it as an ISO 8601 date.
     If that fails, try parsing it with the parsedatetime module,
     which can handle relative dates in natural language."""
     datestring = datestring.strip()
-    try:
-        date = time.strptime(datestring, "%Y-%m-%d %H:%M:%S")
-    except ValueError:
+    # This is sort of awful. Match YYYY-MM-DD hh:mm:ss, with the time parts all being optional
+    m = re.match("^(?P<year>\d\d\d\d)-(?P<month>\d\d)-(?P<day>\d\d)(?: (?P<hour>\d\d)(?::(?P<minute>\d\d)(?::(?P<second>\d\d))?)?)?$", datestring)
+    if m:
+        date = (int(m.group("year")), int(m.group("month")), int(m.group("day")),
+                m.group("hour") and int(m.group("hour")) or 0,
+                m.group("minute") and int(m.group("minute")) or 0,
+                m.group("second") and int(m.group("second")) or 0,
+                0, # weekday
+                0, # yearday
+                -1) # isdst
+    else:
+        # fall back to parsedatetime
         date, x = cal.parse(datestring)
     return time.mktime(date)
 
 def pushlogSetup(repo, req):
     """Given a repository object and a hgweb request object,
     build a PushlogQuery object and populate it with data from the request.
     The returned query object will have its query already run, and
     its entries member can be read."""
--- a/runtests.py
+++ b/runtests.py
@@ -225,16 +225,28 @@ class TestPushlog(unittest.TestCase):
         self.assertEqual(testjson, expectedjson, "json-pushes did not yield expected json data!")
 
     def testmultichangesetquery(self):
         """Query for two changesets at once."""
         testjson = loadjsonurl("http://localhost:8000/json-pushes?changeset=91826025c77c&changeset=a79451771352")
         expectedjson = loadjsonfile("testdata/test-repo-multi-changeset-query.json")
         self.assertEqual(testjson, expectedjson, "json-pushes did not yield expected json data!")
 
+    def testdateparsing(self):
+        """Test that we can parse partial dates, missing seconds, minutes, hours."""
+        testjson = loadjsonurl("http://localhost:8000/json-pushes?startdate=2008-11-20%2010:52:25&enddate=2008-11-20%2010:53:00")
+        expectedjson = loadjsonurl("http://localhost:8000/json-pushes?startdate=2008-11-20%2010:52:25&enddate=2008-11-20%2010:53")
+        self.assertEqual(testjson, expectedjson, "Failed to parse date with missing seconds")
+        testjson = loadjsonurl("http://localhost:8000/json-pushes?startdate=2008-11-20%2010:52:25&enddate=2008-11-20%2011:00:00")
+        expectedjson = loadjsonurl("http://localhost:8000/json-pushes?startdate=2008-11-20%2010:52:25&enddate=2008-11-20%2011")
+        self.assertEqual(testjson, expectedjson, "Failed to parse date with missing seconds and minutes")
+        testjson = loadjsonurl("http://localhost:8000/json-pushes?startdate=2008-11-20%2010:52:25&enddate=2008-11-21%2000:00:00")
+        expectedjson = loadjsonurl("http://localhost:8000/json-pushes?startdate=2008-11-20%2010:52:25&enddate=2008-11-21")
+        self.assertEqual(testjson, expectedjson, "Failed to parse date with missing seconds, minutes, hours")
+
 class TestPushlogUserQueries(unittest.TestCase):
     hgwebprocess = None
     repodir = ''
 
     def setUp(self):
         "Untar the test repo and add the pushlog extension to it."
         # unpack the test repo
         repoarchive = os.path.join(mydir, "testdata/test-repo-users.tar.bz2")