[PATCH 1 of 3] date: refactor timezone parsing

Matt Mackall mpm at selenic.com
Thu Jul 28 15:56:26 EDT 2016


# HG changeset patch
# User Matt Mackall <mpm at selenic.com>
# Date 1469650459 18000
#      Wed Jul 27 15:14:19 2016 -0500
# Branch stable
# Node ID 1bb3f5c0dd89c542e914ff5de02e5872a2816a8f
# Parent  387bdd53c77e9f61bd7b0d491717440f7f57563a
date: refactor timezone parsing

We want to be able to accept ISO 8601 style timezones that don't
include a space separator, so we change the timezone parsing function
to accept a full date string and return both the offset and the
non-timezone portion.

diff -r 387bdd53c77e -r 1bb3f5c0dd89 mercurial/templater.py
--- a/mercurial/templater.py	Mon Jul 25 12:00:55 2016 -0700
+++ b/mercurial/templater.py	Wed Jul 27 15:14:19 2016 -0500
@@ -670,7 +670,9 @@
         tzoffset = None
         tz = evalfuncarg(context, mapping, args[1])
         if isinstance(tz, str):
-            tzoffset = util.parsetimezone(tz)
+            tzoffset, remainder = util.parsetimezone(tz)
+            if remainder:
+                tzoffset = None
         if tzoffset is None:
             try:
                 tzoffset = int(tz)
diff -r 387bdd53c77e -r 1bb3f5c0dd89 mercurial/util.py
--- a/mercurial/util.py	Mon Jul 25 12:00:55 2016 -0700
+++ b/mercurial/util.py	Wed Jul 27 15:14:19 2016 -0500
@@ -1746,24 +1746,27 @@
     """turn (timestamp, tzoff) tuple into iso 8631 date."""
     return datestr(date, format='%Y-%m-%d')
 
-def parsetimezone(tz):
-    """parse a timezone string and return an offset integer"""
-    if tz[0] in "+-" and len(tz) == 5 and tz[1:].isdigit():
-        sign = (tz[0] == "+") and 1 or -1
-        hours = int(tz[1:3])
-        minutes = int(tz[3:5])
-        return -sign * (hours * 60 + minutes) * 60
-    if tz == "GMT" or tz == "UTC":
-        return 0
-    return None
+def parsetimezone(s):
+    """find a trailing timezone, if any, in string, and return a
+       (offset, remainder) pair"""
+
+    if s.endswith("GMT") or s.endswith("UTC"):
+        return 0, s[:-3].rstrip()
+
+    # Unix-style timezones [+-]hhmm
+    if len(s) >= 5 and s[-5] in "+-" and s[-4:].isdigit():
+        sign = (s[-5] == "+") and 1 or -1
+        hours = int(s[-4:-2])
+        minutes = int(s[-2:])
+        return -sign * (hours * 60 + minutes) * 60, s[:-5].rstrip()
+
+    return None, s
 
 def strdate(string, format, defaults=[]):
     """parse a localized time string and return a (unixtime, offset) tuple.
     if the string cannot be parsed, ValueError is raised."""
     # NOTE: unixtime = localunixtime + offset
-    offset, date = parsetimezone(string.split()[-1]), string
-    if offset is not None:
-        date = " ".join(string.split()[:-1])
+    offset, date = parsetimezone(string)
 
     # add missing elements from defaults
     usenow = False # default to using biased defaults
diff -r 387bdd53c77e -r 1bb3f5c0dd89 tests/test-command-template.t
--- a/tests/test-command-template.t	Mon Jul 25 12:00:55 2016 -0700
+++ b/tests/test-command-template.t	Wed Jul 27 15:14:19 2016 -0500
@@ -3253,6 +3253,9 @@
   1970-01-01 09:00 +0900
   $ TZ=JST-09 hg log -r0 -T '{localdate(date, "UTC")|isodate}\n'
   1970-01-01 00:00 +0000
+  $ TZ=JST-09 hg log -r0 -T '{localdate(date, "blahUTC")|isodate}\n'
+  hg: parse error: localdate expects a timezone
+  [255]
   $ TZ=JST-09 hg log -r0 -T '{localdate(date, "+0200")|isodate}\n'
   1970-01-01 02:00 +0200
   $ TZ=JST-09 hg log -r0 -T '{localdate(date, "0")|isodate}\n'


More information about the Mercurial-devel mailing list