Patchwork [3,of,7] templater: introduce a wrapper for date tuple (BC)

login
register
mail settings
Submitter Yuya Nishihara
Date June 12, 2018, 2:49 p.m.
Message ID <61e21a5a89d421909c45.1528814945@mimosa>
Download mbox | patch
Permalink /patch/32080/
State Accepted
Headers show

Comments

Yuya Nishihara - June 12, 2018, 2:49 p.m.
# HG changeset patch
# User Yuya Nishihara <yuya@tcha.org>
# Date 1521881642 -32400
#      Sat Mar 24 17:54:02 2018 +0900
# Node ID 61e21a5a89d421909c45718ffc50f72cf83ee4b5
# Parent  5eb83a63ffff10845fb61fef9eda799731b90061
templater: introduce a wrapper for date tuple (BC)

Strictly speaking, this is BC, but I believe the original string format
(str(float(unixtime)) + str(int(tzoffset))) was just plain wrong.
Augie Fackler - June 12, 2018, 9:49 p.m.
On Tue, Jun 12, 2018 at 11:49:05PM +0900, Yuya Nishihara wrote:
> # HG changeset patch
> # User Yuya Nishihara <yuya@tcha.org>
> # Date 1521881642 -32400
> #      Sat Mar 24 17:54:02 2018 +0900
> # Node ID 61e21a5a89d421909c45718ffc50f72cf83ee4b5
> # Parent  5eb83a63ffff10845fb61fef9eda799731b90061
> templater: introduce a wrapper for date tuple (BC)

This appears to break python-hglib:

https://buildbot.mercurial-scm.org/builders/python-hglib/builds/1379/steps/default%20%282.6.9%29/logs/stdio

Any thoughts on how we should proceed?

>
> Strictly speaking, this is BC, but I believe the original string format
> (str(float(unixtime)) + str(int(tzoffset))) was just plain wrong.
>
> diff --git a/mercurial/formatter.py b/mercurial/formatter.py
> --- a/mercurial/formatter.py
> +++ b/mercurial/formatter.py
> @@ -367,7 +367,7 @@ class _templateconverter(object):
>      @staticmethod
>      def formatdate(date, fmt):
>          '''return date tuple'''
> -        return date
> +        return templateutil.date(date)
>      @staticmethod
>      def formatdict(data, key, value, fmt, sep):
>          '''build object that can be evaluated as either plain string or dict'''
> diff --git a/mercurial/templatefuncs.py b/mercurial/templatefuncs.py
> --- a/mercurial/templatefuncs.py
> +++ b/mercurial/templatefuncs.py
> @@ -391,7 +391,7 @@ def localdate(context, mapping, args):
>                  raise error.ParseError(_("localdate expects a timezone"))
>      else:
>          tzoffset = dateutil.makedate()[1]
> -    return (date[0], tzoffset)
> +    return templateutil.date((date[0], tzoffset))
>
>  @templatefunc('max(iterable)')
>  def max_(context, mapping, args, **kwargs):
> @@ -461,6 +461,7 @@ def obsfatedate(context, mapping, args):
>      markers = evalfuncarg(context, mapping, args[0])
>
>      try:
> +        # TODO: maybe this has to be a wrapped list of date wrappers?
>          data = obsutil.markersdates(markers)
>          return templateutil.hybridlist(data, name='date', fmt='%d %d')
>      except (TypeError, KeyError):
> diff --git a/mercurial/templatekw.py b/mercurial/templatekw.py
> --- a/mercurial/templatekw.py
> +++ b/mercurial/templatekw.py
> @@ -240,7 +240,7 @@ def showactivebookmark(context, mapping)
>  def showdate(context, mapping):
>      """Date information. The date when the changeset was committed."""
>      ctx = context.resource(mapping, 'ctx')
> -    return ctx.date()
> +    return templateutil.date(ctx.date())
>
>  @templatekeyword('desc', requires={'ctx'})
>  def showdescription(context, mapping):
> diff --git a/mercurial/templater.py b/mercurial/templater.py
> --- a/mercurial/templater.py
> +++ b/mercurial/templater.py
> @@ -35,8 +35,8 @@ True, False, int, float
>  wrappedbytes, wrappedvalue
>      a wrapper for the above printable types.
>
> -date tuple
> -    a (unixtime, offset) tuple, which produces no meaningful output by itself.
> +date
> +    represents a (unixtime, offset) tuple.
>
>  hybrid
>      represents a list/dict of printable values, which can also be converted
> diff --git a/mercurial/templateutil.py b/mercurial/templateutil.py
> --- a/mercurial/templateutil.py
> +++ b/mercurial/templateutil.py
> @@ -172,10 +172,37 @@ class wrappedvalue(wrapped):
>      def tovalue(self, context, mapping):
>          return self._value
>
> -# stub for representing a date type; may be a real date type that can
> -# provide a readable string value
> -class date(object):
> -    pass
> +class date(wrapped):
> +    """Wrapper for date tuple"""
> +
> +    def __init__(self, value):
> +        # value may be (float, int), but public interface shouldn't support
> +        # floating-point timestamp
> +        self._unixtime, self._tzoffset = map(int, value)
> +
> +    def contains(self, context, mapping, item):
> +        raise error.ParseError(_('date is not iterable'))
> +
> +    def getmember(self, context, mapping, key):
> +        raise error.ParseError(_('date is not a dictionary'))
> +
> +    def getmin(self, context, mapping):
> +        raise error.ParseError(_('date is not iterable'))
> +
> +    def getmax(self, context, mapping):
> +        raise error.ParseError(_('date is not iterable'))
> +
> +    def itermaps(self, context):
> +        raise error.ParseError(_("date is not iterable"))
> +
> +    def join(self, context, mapping, sep):
> +        raise error.ParseError(_("date is not iterable"))
> +
> +    def show(self, context, mapping):
> +        return '%d %d' % (self._unixtime, self._tzoffset)
> +
> +    def tovalue(self, context, mapping):
> +        return (self._unixtime, self._tzoffset)
>
>  class hybrid(wrapped):
>      """Wrapper for list or dict to support legacy template
> @@ -643,6 +670,9 @@ def evaldate(context, mapping, arg, err=
>      return unwrapdate(context, mapping, thing, err)
>
>  def unwrapdate(context, mapping, thing, err=None):
> +    if isinstance(thing, date):
> +        return thing.tovalue(context, mapping)
> +    # TODO: update hgweb to not return bare tuple; then just stringify 'thing'
>      thing = unwrapvalue(context, mapping, thing)
>      try:
>          return dateutil.parsedate(thing)
> diff --git a/tests/test-amend.t b/tests/test-amend.t
> --- a/tests/test-amend.t
> +++ b/tests/test-amend.t
> @@ -107,7 +107,7 @@ Matcher and metadata options
>    $ hg amend -d '2000 1000' -u 'Foo <foo@example.com>' -A C D
>    saved backup bundle to $TESTTMP/repo1/.hg/strip-backup/c7ba14d9075b-b3e76daa-amend.hg (obsstore-off !)
>    $ hg log -r . -T '{node|short} {desc} {files} {author} {date}\n'
> -  14f6c4bcc865 NEWMESSAGE B D Foo <foo@example.com> 2000.01000
> +  14f6c4bcc865 NEWMESSAGE B D Foo <foo@example.com> 2000 1000
>
>  Amend with editor
>
> diff --git a/tests/test-command-template.t b/tests/test-command-template.t
> --- a/tests/test-command-template.t
> +++ b/tests/test-command-template.t
> @@ -1548,33 +1548,33 @@ Keys work:
>    branches--debug:
>    branches--debug:
>    branches--debug:
> -  date: 1577872860.00
> -  date: 1000000.00
> -  date: 1500001.00
> -  date: 1500000.00
> -  date: 1400000.00
> -  date: 1300000.00
> -  date: 1200000.00
> -  date: 1100000.00
> -  date: 1000000.00
> -  date--verbose: 1577872860.00
> -  date--verbose: 1000000.00
> -  date--verbose: 1500001.00
> -  date--verbose: 1500000.00
> -  date--verbose: 1400000.00
> -  date--verbose: 1300000.00
> -  date--verbose: 1200000.00
> -  date--verbose: 1100000.00
> -  date--verbose: 1000000.00
> -  date--debug: 1577872860.00
> -  date--debug: 1000000.00
> -  date--debug: 1500001.00
> -  date--debug: 1500000.00
> -  date--debug: 1400000.00
> -  date--debug: 1300000.00
> -  date--debug: 1200000.00
> -  date--debug: 1100000.00
> -  date--debug: 1000000.00
> +  date: 1577872860 0
> +  date: 1000000 0
> +  date: 1500001 0
> +  date: 1500000 0
> +  date: 1400000 0
> +  date: 1300000 0
> +  date: 1200000 0
> +  date: 1100000 0
> +  date: 1000000 0
> +  date--verbose: 1577872860 0
> +  date--verbose: 1000000 0
> +  date--verbose: 1500001 0
> +  date--verbose: 1500000 0
> +  date--verbose: 1400000 0
> +  date--verbose: 1300000 0
> +  date--verbose: 1200000 0
> +  date--verbose: 1100000 0
> +  date--verbose: 1000000 0
> +  date--debug: 1577872860 0
> +  date--debug: 1000000 0
> +  date--debug: 1500001 0
> +  date--debug: 1500000 0
> +  date--debug: 1400000 0
> +  date--debug: 1300000 0
> +  date--debug: 1200000 0
> +  date--debug: 1100000 0
> +  date--debug: 1000000 0
>    desc: third
>    desc: second
>    desc: merge
> @@ -2291,7 +2291,7 @@ Upper/lower filters:
>    $ hg log -r0 --template '{author|lower}\n'
>    user name <user@hostname>
>    $ hg log -r0 --template '{date|upper}\n'
> -  1000000.00
> +  1000000 0
>
>  Add a commit that does all possible modifications at once
>
> @@ -2806,9 +2806,9 @@ Error on syntax:
>  Behind the scenes, this would throw TypeError without intype=bytes
>
>    $ hg log -l 3 --template '{date|obfuscate}\n'
> -  &#48;&#46;&#48;&#48;
> -  &#48;&#46;&#48;&#48;
> -  &#49;&#53;&#55;&#55;&#56;&#55;&#50;&#56;&#54;&#48;&#46;&#48;&#48;
> +  &#48;&#32;&#48;
> +  &#48;&#32;&#48;
> +  &#49;&#53;&#55;&#55;&#56;&#55;&#50;&#56;&#54;&#48;&#32;&#48;
>
>  Behind the scenes, this will throw a ValueError
>
> @@ -2820,9 +2820,9 @@ Behind the scenes, this will throw a Val
>  Behind the scenes, this would throw AttributeError without intype=bytes
>
>    $ hg log -l 3 --template 'line: {date|escape}\n'
> -  line: 0.00
> -  line: 0.00
> -  line: 1577872860.00
> +  line: 0 0
> +  line: 0 0
> +  line: 1577872860 0
>
>    $ hg log -l 3 --template 'line: {extras|localdate}\n'
>    hg: parse error: localdate expects a date information
> @@ -3293,6 +3293,15 @@ Test min/max of non-iterable:
>    (max first argument should be an iterable)
>    [255]
>
> +  $ hg log -R latesttag -l1 -T '{min(date)}'
> +  hg: parse error: date is not iterable
> +  (min first argument should be an iterable)
> +  [255]
> +  $ hg log -R latesttag -l1 -T '{max(date)}'
> +  hg: parse error: date is not iterable
> +  (max first argument should be an iterable)
> +  [255]
> +
>  Test min/max of empty sequence:
>
>    $ hg debugtemplate '{min("")}'
> @@ -3902,12 +3911,14 @@ Test get function:
>    (get() expects a dict as first argument)
>    [255]
>
> -Test json filter applied to hybrid object:
> +Test json filter applied to wrapped object:
>
>    $ hg log -r0 -T '{files|json}\n'
>    ["a"]
>    $ hg log -r0 -T '{extras|json}\n'
>    {"branch": "default"}
> +  $ hg log -r0 -T '{date|json}\n'
> +  [0, 0]
>
>  Test json filter applied to map result:
>
> @@ -4608,8 +4619,8 @@ Test indent and not adding to empty line
>  Test with non-strings like dates
>
>    $ hg log -T "{indent(date, '   ')}\n" -r 2:3 -R a
> -     1200000.00
> -     1300000.00
> +     1200000 0
> +     1300000 0
>
>  Test broken string escapes:
>
> diff --git a/tests/test-debugbuilddag.t b/tests/test-debugbuilddag.t
> --- a/tests/test-debugbuilddag.t
> +++ b/tests/test-debugbuilddag.t
> @@ -42,29 +42,29 @@ tip
>    000000000000
>  glog
>    $ hg log -G --template '{rev}: {desc} [{branches}] @ {date}\n'
> -  o  11: r11 [] @ 11.00
> +  o  11: r11 [] @ 11 0
>    |
> -  o  10: r10 [] @ 10.00
> +  o  10: r10 [] @ 10 0
>    |
> -  o    9: r9 [] @ 9.00
> +  o    9: r9 [] @ 9 0
>    |\
> -  | o  8: r8 [temp] @ 8.00
> +  | o  8: r8 [temp] @ 8 0
>    | |
> -  | o  7: r7 [temp] @ 7.00
> +  | o  7: r7 [temp] @ 7 0
>    | |
> -  | o  6: r6 [temp] @ 6.00
> +  | o  6: r6 [temp] @ 6 0
>    | |
> -  | o  5: r5 [temp] @ 5.00
> +  | o  5: r5 [temp] @ 5 0
>    | |
> -  o |  4: r4 [] @ 4.00
> +  o |  4: r4 [] @ 4 0
>    | |
> -  o |  3: r3 [] @ 3.00
> +  o |  3: r3 [] @ 3 0
>    | |
> -  o |  2: r2 [] @ 2.00
> +  o |  2: r2 [] @ 2 0
>    |/
> -  o  1: r1 [] @ 1.00
> +  o  1: r1 [] @ 1 0
>    |
> -  o  0: r0 [] @ 0.00
> +  o  0: r0 [] @ 0 0
>
>
>  overwritten files, starting on a non-default branch
> @@ -88,29 +88,29 @@ tip
>    000000000000
>  glog
>    $ hg log -G --template '{rev}: {desc} [{branches}] @ {date}\n'
> -  o  11: r11 [] @ 11.00
> +  o  11: r11 [] @ 11 0
>    |
> -  o  10: r10 [] @ 10.00
> +  o  10: r10 [] @ 10 0
>    |
> -  o    9: r9 [] @ 9.00
> +  o    9: r9 [] @ 9 0
>    |\
> -  | o  8: r8 [temp] @ 8.00
> +  | o  8: r8 [temp] @ 8 0
>    | |
> -  | o  7: r7 [temp] @ 7.00
> +  | o  7: r7 [temp] @ 7 0
>    | |
> -  | o  6: r6 [temp] @ 6.00
> +  | o  6: r6 [temp] @ 6 0
>    | |
> -  | o  5: r5 [temp] @ 5.00
> +  | o  5: r5 [temp] @ 5 0
>    | |
> -  o |  4: r4 [] @ 4.00
> +  o |  4: r4 [] @ 4 0
>    | |
> -  o |  3: r3 [] @ 3.00
> +  o |  3: r3 [] @ 3 0
>    | |
> -  o |  2: r2 [] @ 2.00
> +  o |  2: r2 [] @ 2 0
>    |/
> -  o  1: r1 [] @ 1.00
> +  o  1: r1 [] @ 1 0
>    |
> -  o  0: r0 [start] @ 0.00
> +  o  0: r0 [start] @ 0 0
>
>  glog of
>    $ hg log -G --template '{rev}: {desc} [{branches}]\n' of
> @@ -164,29 +164,29 @@ tip
>    000000000000
>  glog
>    $ hg log -G --template '{rev}: {desc} [{branches}] @ {date}\n'
> -  o  11: r11 [] @ 11.00
> +  o  11: r11 [] @ 11 0
>    |
> -  o  10: r10 [] @ 10.00
> +  o  10: r10 [] @ 10 0
>    |
> -  o    9: r9 [] @ 9.00
> +  o    9: r9 [] @ 9 0
>    |\
> -  | o  8: r8 [temp] @ 8.00
> +  | o  8: r8 [temp] @ 8 0
>    | |
> -  | o  7: r7 [temp] @ 7.00
> +  | o  7: r7 [temp] @ 7 0
>    | |
> -  | o  6: r6 [temp] @ 6.00
> +  | o  6: r6 [temp] @ 6 0
>    | |
> -  | o  5: r5 [temp] @ 5.00
> +  | o  5: r5 [temp] @ 5 0
>    | |
> -  o |  4: r4 [] @ 4.00
> +  o |  4: r4 [] @ 4 0
>    | |
> -  o |  3: r3 [] @ 3.00
> +  o |  3: r3 [] @ 3 0
>    | |
> -  o |  2: r2 [] @ 2.00
> +  o |  2: r2 [] @ 2 0
>    |/
> -  o  1: r1 [] @ 1.00
> +  o  1: r1 [] @ 1 0
>    |
> -  o  0: r0 [] @ 0.00
> +  o  0: r0 [] @ 0 0
>
>  glog mf
>    $ hg log -G --template '{rev}: {desc} [{branches}]\n' mf
> diff --git a/tests/test-mq-header-date.t b/tests/test-mq-header-date.t
> --- a/tests/test-mq-header-date.t
> +++ b/tests/test-mq-header-date.t
> @@ -202,7 +202,7 @@
>    ==== qnew -d
>    Date: 3 0
>
> -  0: 758bd2596a39 [mq]: 1.patch - test - 3.00
> +  0: 758bd2596a39 [mq]: 1.patch - test - 3 0
>    ==== qref
>    adding 1
>    Date: 3 0
> @@ -212,7 +212,7 @@
>    +++ b/1
>    @@ -0,0 +1,1 @@
>    +1
> -  0: 8c640e9949a8 [mq]: 1.patch - test - 3.00
> +  0: 8c640e9949a8 [mq]: 1.patch - test - 3 0
>    ==== qref -d
>    Date: 4 0
>
> @@ -221,7 +221,7 @@
>    +++ b/1
>    @@ -0,0 +1,1 @@
>    +1
> -  0: 4a67dfeea974 [mq]: 1.patch - test - 4.00
> +  0: 4a67dfeea974 [mq]: 1.patch - test - 4 0
>    ==== qnew
>    adding 2
>    diff -r ... 2
> @@ -248,8 +248,8 @@
>
>    Three
>
> -  1: 2a9ef0bdefba Three - test - 6.00
> -  0: 4a67dfeea974 [mq]: 1.patch - test - 4.00
> +  1: 2a9ef0bdefba Three - test - 6 0
> +  0: 4a67dfeea974 [mq]: 1.patch - test - 4 0
>    ==== qref
>    adding 3
>    Date: 6 0
> @@ -261,8 +261,8 @@
>    +++ b/3
>    @@ -0,0 +1,1 @@
>    +3
> -  1: 7f19ad9eea7b Three - test - 6.00
> -  0: 4a67dfeea974 [mq]: 1.patch - test - 4.00
> +  1: 7f19ad9eea7b Three - test - 6 0
> +  0: 4a67dfeea974 [mq]: 1.patch - test - 4 0
>    ==== qref -m
>    Date: 6 0
>
> @@ -273,8 +273,8 @@
>    +++ b/3
>    @@ -0,0 +1,1 @@
>    +3
> -  1: 7ff7377793e3 Drei - test - 6.00
> -  0: 4a67dfeea974 [mq]: 1.patch - test - 4.00
> +  1: 7ff7377793e3 Drei - test - 6 0
> +  0: 4a67dfeea974 [mq]: 1.patch - test - 4 0
>    ==== qref -d
>    Date: 7 0
>
> @@ -285,8 +285,8 @@
>    +++ b/3
>    @@ -0,0 +1,1 @@
>    +3
> -  1: d89d3144f518 Drei - test - 7.00
> -  0: 4a67dfeea974 [mq]: 1.patch - test - 4.00
> +  1: d89d3144f518 Drei - test - 7 0
> +  0: 4a67dfeea974 [mq]: 1.patch - test - 4 0
>    ==== qref -d -m
>    Date: 8 0
>
> @@ -297,8 +297,8 @@
>    +++ b/3
>    @@ -0,0 +1,1 @@
>    +3
> -  1: b1b6b0fe0e6d Three (again) - test - 8.00
> -  0: 4a67dfeea974 [mq]: 1.patch - test - 4.00
> +  1: b1b6b0fe0e6d Three (again) - test - 8 0
> +  0: 4a67dfeea974 [mq]: 1.patch - test - 4 0
>    ==== qnew -m
>    adding 4
>    Four
> @@ -331,9 +331,9 @@
>    now at: 3.patch
>    # HG changeset patch
>    # Date 10 0
> -  2: d16a272220d2 imported patch 5.patch - test - 10.00
> -  1: b1b6b0fe0e6d Three (again) - test - 8.00
> -  0: 4a67dfeea974 [mq]: 1.patch - test - 4.00
> +  2: d16a272220d2 imported patch 5.patch - test - 10 0
> +  1: b1b6b0fe0e6d Three (again) - test - 8 0
> +  0: 4a67dfeea974 [mq]: 1.patch - test - 4 0
>    ==== hg qref
>    adding 5
>    # HG changeset patch
> @@ -345,9 +345,9 @@
>    +++ b/5
>    @@ -0,0 +1,1 @@
>    +5
> -  2: 5dbf69c07df9 [mq]: 5.patch - test - 10.00
> -  1: b1b6b0fe0e6d Three (again) - test - 8.00
> -  0: 4a67dfeea974 [mq]: 1.patch - test - 4.00
> +  2: 5dbf69c07df9 [mq]: 5.patch - test - 10 0
> +  1: b1b6b0fe0e6d Three (again) - test - 8 0
> +  0: 4a67dfeea974 [mq]: 1.patch - test - 4 0
>    ==== hg qref -d
>    # HG changeset patch
>    # Date 11 0
> @@ -358,9 +358,9 @@
>    +++ b/5
>    @@ -0,0 +1,1 @@
>    +5
> -  2: 049de6af0c1d [mq]: 5.patch - test - 11.00
> -  1: b1b6b0fe0e6d Three (again) - test - 8.00
> -  0: 4a67dfeea974 [mq]: 1.patch - test - 4.00
> +  2: 049de6af0c1d [mq]: 5.patch - test - 11 0
> +  1: b1b6b0fe0e6d Three (again) - test - 8 0
> +  0: 4a67dfeea974 [mq]: 1.patch - test - 4 0
>    ==== qnew with plain header
>    popping 6.patch
>    now at: 5.patch
> @@ -380,10 +380,10 @@
>    +++ b/6
>    @@ -0,0 +1,1 @@
>    +6
> -  3: 038c46b02a56 [mq]: 6.patch - test - 12.00
> -  2: 049de6af0c1d [mq]: 5.patch - test - 11.00
> -  1: b1b6b0fe0e6d Three (again) - test - 8.00
> -  0: 4a67dfeea974 [mq]: 1.patch - test - 4.00
> +  3: 038c46b02a56 [mq]: 6.patch - test - 12 0
> +  2: 049de6af0c1d [mq]: 5.patch - test - 11 0
> +  1: b1b6b0fe0e6d Three (again) - test - 8 0
> +  0: 4a67dfeea974 [mq]: 1.patch - test - 4 0
>    ==== hg qref -d
>    Date: 13 0
>
> @@ -392,10 +392,10 @@
>    +++ b/6
>    @@ -0,0 +1,1 @@
>    +6
> -  3: 2785642ea4b4 [mq]: 6.patch - test - 13.00
> -  2: 049de6af0c1d [mq]: 5.patch - test - 11.00
> -  1: b1b6b0fe0e6d Three (again) - test - 8.00
> -  0: 4a67dfeea974 [mq]: 1.patch - test - 4.00
> +  3: 2785642ea4b4 [mq]: 6.patch - test - 13 0
> +  2: 049de6af0c1d [mq]: 5.patch - test - 11 0
> +  1: b1b6b0fe0e6d Three (again) - test - 8 0
> +  0: 4a67dfeea974 [mq]: 1.patch - test - 4 0
>    popping 6.patch
>    now at: 5.patch
>    ==== qnew -u
> @@ -448,10 +448,10 @@
>    +++ b/7
>    @@ -0,0 +1,1 @@
>    +7
> -  3: 4f9d07369cc4 [mq]: 7.patch - john - 13.00
> -  2: 049de6af0c1d [mq]: 5.patch - test - 11.00
> -  1: b1b6b0fe0e6d Three (again) - test - 8.00
> -  0: 4a67dfeea974 [mq]: 1.patch - test - 4.00
> +  3: 4f9d07369cc4 [mq]: 7.patch - john - 13 0
> +  2: 049de6af0c1d [mq]: 5.patch - test - 11 0
> +  1: b1b6b0fe0e6d Three (again) - test - 8 0
> +  0: 4a67dfeea974 [mq]: 1.patch - test - 4 0
>    ==== qnew
>    adding 8
>    diff -r ... 8
> @@ -523,10 +523,10 @@
>    applying 5.patch
>    applying 7.patch
>    now at: 7.patch
> -  3: d26a5b7ffce1 imported patch 7.patch - john - 13.00
> -  2: dda6cf77060a imported patch 5.patch - test - 11.00
> -  1: 25e32d66c8c7 Three (again) - test - 8.00
> -  0: e5011c0211fe imported patch 1.patch - test - 4.00
> +  3: d26a5b7ffce1 imported patch 7.patch - john - 13 0
> +  2: dda6cf77060a imported patch 5.patch - test - 11 0
> +  1: 25e32d66c8c7 Three (again) - test - 8 0
> +  0: e5011c0211fe imported patch 1.patch - test - 4 0
>    $ rm -r sandbox
>
>  ======= hg headers
> @@ -540,7 +540,7 @@
>    # Date 3 0
>    # Parent
>
> -  0: 758bd2596a39 [mq]: 1.patch - test - 3.00
> +  0: 758bd2596a39 [mq]: 1.patch - test - 3 0
>    ==== qref
>    adding 1
>    # HG changeset patch
> @@ -552,7 +552,7 @@
>    +++ b/1
>    @@ -0,0 +1,1 @@
>    +1
> -  0: 8c640e9949a8 [mq]: 1.patch - test - 3.00
> +  0: 8c640e9949a8 [mq]: 1.patch - test - 3 0
>    ==== qref -d
>    # HG changeset patch
>    # Date 4 0
> @@ -563,7 +563,7 @@
>    +++ b/1
>    @@ -0,0 +1,1 @@
>    +1
> -  0: 4a67dfeea974 [mq]: 1.patch - test - 4.00
> +  0: 4a67dfeea974 [mq]: 1.patch - test - 4 0
>    ==== qnew
>    adding 2
>    # HG changeset patch
> @@ -596,8 +596,8 @@
>    # Parent
>    Three
>
> -  1: 2a9ef0bdefba Three - test - 6.00
> -  0: 4a67dfeea974 [mq]: 1.patch - test - 4.00
> +  1: 2a9ef0bdefba Three - test - 6 0
> +  0: 4a67dfeea974 [mq]: 1.patch - test - 4 0
>    ==== qref
>    adding 3
>    # HG changeset patch
> @@ -610,8 +610,8 @@
>    +++ b/3
>    @@ -0,0 +1,1 @@
>    +3
> -  1: 7f19ad9eea7b Three - test - 6.00
> -  0: 4a67dfeea974 [mq]: 1.patch - test - 4.00
> +  1: 7f19ad9eea7b Three - test - 6 0
> +  0: 4a67dfeea974 [mq]: 1.patch - test - 4 0
>    ==== qref -m
>    # HG changeset patch
>    # Date 6 0
> @@ -623,8 +623,8 @@
>    +++ b/3
>    @@ -0,0 +1,1 @@
>    +3
> -  1: 7ff7377793e3 Drei - test - 6.00
> -  0: 4a67dfeea974 [mq]: 1.patch - test - 4.00
> +  1: 7ff7377793e3 Drei - test - 6 0
> +  0: 4a67dfeea974 [mq]: 1.patch - test - 4 0
>    ==== qref -d
>    # HG changeset patch
>    # Date 7 0
> @@ -636,8 +636,8 @@
>    +++ b/3
>    @@ -0,0 +1,1 @@
>    +3
> -  1: d89d3144f518 Drei - test - 7.00
> -  0: 4a67dfeea974 [mq]: 1.patch - test - 4.00
> +  1: d89d3144f518 Drei - test - 7 0
> +  0: 4a67dfeea974 [mq]: 1.patch - test - 4 0
>    ==== qref -d -m
>    # HG changeset patch
>    # Date 8 0
> @@ -649,8 +649,8 @@
>    +++ b/3
>    @@ -0,0 +1,1 @@
>    +3
> -  1: b1b6b0fe0e6d Three (again) - test - 8.00
> -  0: 4a67dfeea974 [mq]: 1.patch - test - 4.00
> +  1: b1b6b0fe0e6d Three (again) - test - 8 0
> +  0: 4a67dfeea974 [mq]: 1.patch - test - 4 0
>    ==== qnew -m
>    adding 4
>    # HG changeset patch
> @@ -686,9 +686,9 @@
>    now at: 3.patch
>    # HG changeset patch
>    # Date 10 0
> -  2: d16a272220d2 imported patch 5.patch - test - 10.00
> -  1: b1b6b0fe0e6d Three (again) - test - 8.00
> -  0: 4a67dfeea974 [mq]: 1.patch - test - 4.00
> +  2: d16a272220d2 imported patch 5.patch - test - 10 0
> +  1: b1b6b0fe0e6d Three (again) - test - 8 0
> +  0: 4a67dfeea974 [mq]: 1.patch - test - 4 0
>    ==== hg qref
>    adding 5
>    # HG changeset patch
> @@ -700,9 +700,9 @@
>    +++ b/5
>    @@ -0,0 +1,1 @@
>    +5
> -  2: 5dbf69c07df9 [mq]: 5.patch - test - 10.00
> -  1: b1b6b0fe0e6d Three (again) - test - 8.00
> -  0: 4a67dfeea974 [mq]: 1.patch - test - 4.00
> +  2: 5dbf69c07df9 [mq]: 5.patch - test - 10 0
> +  1: b1b6b0fe0e6d Three (again) - test - 8 0
> +  0: 4a67dfeea974 [mq]: 1.patch - test - 4 0
>    ==== hg qref -d
>    # HG changeset patch
>    # Date 11 0
> @@ -713,9 +713,9 @@
>    +++ b/5
>    @@ -0,0 +1,1 @@
>    +5
> -  2: 049de6af0c1d [mq]: 5.patch - test - 11.00
> -  1: b1b6b0fe0e6d Three (again) - test - 8.00
> -  0: 4a67dfeea974 [mq]: 1.patch - test - 4.00
> +  2: 049de6af0c1d [mq]: 5.patch - test - 11 0
> +  1: b1b6b0fe0e6d Three (again) - test - 8 0
> +  0: 4a67dfeea974 [mq]: 1.patch - test - 4 0
>    ==== qnew with plain header
>    popping 6.patch
>    now at: 5.patch
> @@ -735,10 +735,10 @@
>    +++ b/6
>    @@ -0,0 +1,1 @@
>    +6
> -  3: 038c46b02a56 [mq]: 6.patch - test - 12.00
> -  2: 049de6af0c1d [mq]: 5.patch - test - 11.00
> -  1: b1b6b0fe0e6d Three (again) - test - 8.00
> -  0: 4a67dfeea974 [mq]: 1.patch - test - 4.00
> +  3: 038c46b02a56 [mq]: 6.patch - test - 12 0
> +  2: 049de6af0c1d [mq]: 5.patch - test - 11 0
> +  1: b1b6b0fe0e6d Three (again) - test - 8 0
> +  0: 4a67dfeea974 [mq]: 1.patch - test - 4 0
>    ==== hg qref -d
>    Date: 13 0
>
> @@ -747,10 +747,10 @@
>    +++ b/6
>    @@ -0,0 +1,1 @@
>    +6
> -  3: 2785642ea4b4 [mq]: 6.patch - test - 13.00
> -  2: 049de6af0c1d [mq]: 5.patch - test - 11.00
> -  1: b1b6b0fe0e6d Three (again) - test - 8.00
> -  0: 4a67dfeea974 [mq]: 1.patch - test - 4.00
> +  3: 2785642ea4b4 [mq]: 6.patch - test - 13 0
> +  2: 049de6af0c1d [mq]: 5.patch - test - 11 0
> +  1: b1b6b0fe0e6d Three (again) - test - 8 0
> +  0: 4a67dfeea974 [mq]: 1.patch - test - 4 0
>    popping 6.patch
>    now at: 5.patch
>    ==== qnew -u
> @@ -811,10 +811,10 @@
>    +++ b/7
>    @@ -0,0 +1,1 @@
>    +7
> -  3: 4f9d07369cc4 [mq]: 7.patch - john - 13.00
> -  2: 049de6af0c1d [mq]: 5.patch - test - 11.00
> -  1: b1b6b0fe0e6d Three (again) - test - 8.00
> -  0: 4a67dfeea974 [mq]: 1.patch - test - 4.00
> +  3: 4f9d07369cc4 [mq]: 7.patch - john - 13 0
> +  2: 049de6af0c1d [mq]: 5.patch - test - 11 0
> +  1: b1b6b0fe0e6d Three (again) - test - 8 0
> +  0: 4a67dfeea974 [mq]: 1.patch - test - 4 0
>    ==== qnew
>    adding 8
>    # HG changeset patch
> @@ -894,8 +894,8 @@
>    applying 5.patch
>    applying 7.patch
>    now at: 7.patch
> -  3: d26a5b7ffce1 imported patch 7.patch - john - 13.00
> -  2: dda6cf77060a imported patch 5.patch - test - 11.00
> -  1: 25e32d66c8c7 Three (again) - test - 8.00
> -  0: e5011c0211fe imported patch 1.patch - test - 4.00
> +  3: d26a5b7ffce1 imported patch 7.patch - john - 13 0
> +  2: dda6cf77060a imported patch 5.patch - test - 11 0
> +  1: 25e32d66c8c7 Three (again) - test - 8 0
> +  0: e5011c0211fe imported patch 1.patch - test - 4 0
>    $ rm -r sandbox
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel@mercurial-scm.org
> https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Yuya Nishihara - June 13, 2018, 12:01 p.m.
On Tue, 12 Jun 2018 17:49:47 -0400, Augie Fackler wrote:
> On Tue, Jun 12, 2018 at 11:49:05PM +0900, Yuya Nishihara wrote:
> > # HG changeset patch
> > # User Yuya Nishihara <yuya@tcha.org>
> > # Date 1521881642 -32400
> > #      Sat Mar 24 17:54:02 2018 +0900
> > # Node ID 61e21a5a89d421909c45718ffc50f72cf83ee4b5
> > # Parent  5eb83a63ffff10845fb61fef9eda799731b90061
> > templater: introduce a wrapper for date tuple (BC)
> 
> This appears to break python-hglib:
> 
> https://buildbot.mercurial-scm.org/builders/python-hglib/builds/1379/steps/default%20%282.6.9%29/logs/stdio
> 
> Any thoughts on how we should proceed?

Ugh. I could fix python-hglib to use {date|hgdate}, but we'd better to restore
the original output format for compatibility with old versions. I'll send a
follow up.

Patch

diff --git a/mercurial/formatter.py b/mercurial/formatter.py
--- a/mercurial/formatter.py
+++ b/mercurial/formatter.py
@@ -367,7 +367,7 @@  class _templateconverter(object):
     @staticmethod
     def formatdate(date, fmt):
         '''return date tuple'''
-        return date
+        return templateutil.date(date)
     @staticmethod
     def formatdict(data, key, value, fmt, sep):
         '''build object that can be evaluated as either plain string or dict'''
diff --git a/mercurial/templatefuncs.py b/mercurial/templatefuncs.py
--- a/mercurial/templatefuncs.py
+++ b/mercurial/templatefuncs.py
@@ -391,7 +391,7 @@  def localdate(context, mapping, args):
                 raise error.ParseError(_("localdate expects a timezone"))
     else:
         tzoffset = dateutil.makedate()[1]
-    return (date[0], tzoffset)
+    return templateutil.date((date[0], tzoffset))
 
 @templatefunc('max(iterable)')
 def max_(context, mapping, args, **kwargs):
@@ -461,6 +461,7 @@  def obsfatedate(context, mapping, args):
     markers = evalfuncarg(context, mapping, args[0])
 
     try:
+        # TODO: maybe this has to be a wrapped list of date wrappers?
         data = obsutil.markersdates(markers)
         return templateutil.hybridlist(data, name='date', fmt='%d %d')
     except (TypeError, KeyError):
diff --git a/mercurial/templatekw.py b/mercurial/templatekw.py
--- a/mercurial/templatekw.py
+++ b/mercurial/templatekw.py
@@ -240,7 +240,7 @@  def showactivebookmark(context, mapping)
 def showdate(context, mapping):
     """Date information. The date when the changeset was committed."""
     ctx = context.resource(mapping, 'ctx')
-    return ctx.date()
+    return templateutil.date(ctx.date())
 
 @templatekeyword('desc', requires={'ctx'})
 def showdescription(context, mapping):
diff --git a/mercurial/templater.py b/mercurial/templater.py
--- a/mercurial/templater.py
+++ b/mercurial/templater.py
@@ -35,8 +35,8 @@  True, False, int, float
 wrappedbytes, wrappedvalue
     a wrapper for the above printable types.
 
-date tuple
-    a (unixtime, offset) tuple, which produces no meaningful output by itself.
+date
+    represents a (unixtime, offset) tuple.
 
 hybrid
     represents a list/dict of printable values, which can also be converted
diff --git a/mercurial/templateutil.py b/mercurial/templateutil.py
--- a/mercurial/templateutil.py
+++ b/mercurial/templateutil.py
@@ -172,10 +172,37 @@  class wrappedvalue(wrapped):
     def tovalue(self, context, mapping):
         return self._value
 
-# stub for representing a date type; may be a real date type that can
-# provide a readable string value
-class date(object):
-    pass
+class date(wrapped):
+    """Wrapper for date tuple"""
+
+    def __init__(self, value):
+        # value may be (float, int), but public interface shouldn't support
+        # floating-point timestamp
+        self._unixtime, self._tzoffset = map(int, value)
+
+    def contains(self, context, mapping, item):
+        raise error.ParseError(_('date is not iterable'))
+
+    def getmember(self, context, mapping, key):
+        raise error.ParseError(_('date is not a dictionary'))
+
+    def getmin(self, context, mapping):
+        raise error.ParseError(_('date is not iterable'))
+
+    def getmax(self, context, mapping):
+        raise error.ParseError(_('date is not iterable'))
+
+    def itermaps(self, context):
+        raise error.ParseError(_("date is not iterable"))
+
+    def join(self, context, mapping, sep):
+        raise error.ParseError(_("date is not iterable"))
+
+    def show(self, context, mapping):
+        return '%d %d' % (self._unixtime, self._tzoffset)
+
+    def tovalue(self, context, mapping):
+        return (self._unixtime, self._tzoffset)
 
 class hybrid(wrapped):
     """Wrapper for list or dict to support legacy template
@@ -643,6 +670,9 @@  def evaldate(context, mapping, arg, err=
     return unwrapdate(context, mapping, thing, err)
 
 def unwrapdate(context, mapping, thing, err=None):
+    if isinstance(thing, date):
+        return thing.tovalue(context, mapping)
+    # TODO: update hgweb to not return bare tuple; then just stringify 'thing'
     thing = unwrapvalue(context, mapping, thing)
     try:
         return dateutil.parsedate(thing)
diff --git a/tests/test-amend.t b/tests/test-amend.t
--- a/tests/test-amend.t
+++ b/tests/test-amend.t
@@ -107,7 +107,7 @@  Matcher and metadata options
   $ hg amend -d '2000 1000' -u 'Foo <foo@example.com>' -A C D
   saved backup bundle to $TESTTMP/repo1/.hg/strip-backup/c7ba14d9075b-b3e76daa-amend.hg (obsstore-off !)
   $ hg log -r . -T '{node|short} {desc} {files} {author} {date}\n'
-  14f6c4bcc865 NEWMESSAGE B D Foo <foo@example.com> 2000.01000
+  14f6c4bcc865 NEWMESSAGE B D Foo <foo@example.com> 2000 1000
 
 Amend with editor
 
diff --git a/tests/test-command-template.t b/tests/test-command-template.t
--- a/tests/test-command-template.t
+++ b/tests/test-command-template.t
@@ -1548,33 +1548,33 @@  Keys work:
   branches--debug: 
   branches--debug: 
   branches--debug: 
-  date: 1577872860.00
-  date: 1000000.00
-  date: 1500001.00
-  date: 1500000.00
-  date: 1400000.00
-  date: 1300000.00
-  date: 1200000.00
-  date: 1100000.00
-  date: 1000000.00
-  date--verbose: 1577872860.00
-  date--verbose: 1000000.00
-  date--verbose: 1500001.00
-  date--verbose: 1500000.00
-  date--verbose: 1400000.00
-  date--verbose: 1300000.00
-  date--verbose: 1200000.00
-  date--verbose: 1100000.00
-  date--verbose: 1000000.00
-  date--debug: 1577872860.00
-  date--debug: 1000000.00
-  date--debug: 1500001.00
-  date--debug: 1500000.00
-  date--debug: 1400000.00
-  date--debug: 1300000.00
-  date--debug: 1200000.00
-  date--debug: 1100000.00
-  date--debug: 1000000.00
+  date: 1577872860 0
+  date: 1000000 0
+  date: 1500001 0
+  date: 1500000 0
+  date: 1400000 0
+  date: 1300000 0
+  date: 1200000 0
+  date: 1100000 0
+  date: 1000000 0
+  date--verbose: 1577872860 0
+  date--verbose: 1000000 0
+  date--verbose: 1500001 0
+  date--verbose: 1500000 0
+  date--verbose: 1400000 0
+  date--verbose: 1300000 0
+  date--verbose: 1200000 0
+  date--verbose: 1100000 0
+  date--verbose: 1000000 0
+  date--debug: 1577872860 0
+  date--debug: 1000000 0
+  date--debug: 1500001 0
+  date--debug: 1500000 0
+  date--debug: 1400000 0
+  date--debug: 1300000 0
+  date--debug: 1200000 0
+  date--debug: 1100000 0
+  date--debug: 1000000 0
   desc: third
   desc: second
   desc: merge
@@ -2291,7 +2291,7 @@  Upper/lower filters:
   $ hg log -r0 --template '{author|lower}\n'
   user name <user@hostname>
   $ hg log -r0 --template '{date|upper}\n'
-  1000000.00
+  1000000 0
 
 Add a commit that does all possible modifications at once
 
@@ -2806,9 +2806,9 @@  Error on syntax:
 Behind the scenes, this would throw TypeError without intype=bytes
 
   $ hg log -l 3 --template '{date|obfuscate}\n'
-  &#48;&#46;&#48;&#48;
-  &#48;&#46;&#48;&#48;
-  &#49;&#53;&#55;&#55;&#56;&#55;&#50;&#56;&#54;&#48;&#46;&#48;&#48;
+  &#48;&#32;&#48;
+  &#48;&#32;&#48;
+  &#49;&#53;&#55;&#55;&#56;&#55;&#50;&#56;&#54;&#48;&#32;&#48;
 
 Behind the scenes, this will throw a ValueError
 
@@ -2820,9 +2820,9 @@  Behind the scenes, this will throw a Val
 Behind the scenes, this would throw AttributeError without intype=bytes
 
   $ hg log -l 3 --template 'line: {date|escape}\n'
-  line: 0.00
-  line: 0.00
-  line: 1577872860.00
+  line: 0 0
+  line: 0 0
+  line: 1577872860 0
 
   $ hg log -l 3 --template 'line: {extras|localdate}\n'
   hg: parse error: localdate expects a date information
@@ -3293,6 +3293,15 @@  Test min/max of non-iterable:
   (max first argument should be an iterable)
   [255]
 
+  $ hg log -R latesttag -l1 -T '{min(date)}'
+  hg: parse error: date is not iterable
+  (min first argument should be an iterable)
+  [255]
+  $ hg log -R latesttag -l1 -T '{max(date)}'
+  hg: parse error: date is not iterable
+  (max first argument should be an iterable)
+  [255]
+
 Test min/max of empty sequence:
 
   $ hg debugtemplate '{min("")}'
@@ -3902,12 +3911,14 @@  Test get function:
   (get() expects a dict as first argument)
   [255]
 
-Test json filter applied to hybrid object:
+Test json filter applied to wrapped object:
 
   $ hg log -r0 -T '{files|json}\n'
   ["a"]
   $ hg log -r0 -T '{extras|json}\n'
   {"branch": "default"}
+  $ hg log -r0 -T '{date|json}\n'
+  [0, 0]
 
 Test json filter applied to map result:
 
@@ -4608,8 +4619,8 @@  Test indent and not adding to empty line
 Test with non-strings like dates
 
   $ hg log -T "{indent(date, '   ')}\n" -r 2:3 -R a
-     1200000.00
-     1300000.00
+     1200000 0
+     1300000 0
 
 Test broken string escapes:
 
diff --git a/tests/test-debugbuilddag.t b/tests/test-debugbuilddag.t
--- a/tests/test-debugbuilddag.t
+++ b/tests/test-debugbuilddag.t
@@ -42,29 +42,29 @@  tip
   000000000000
 glog
   $ hg log -G --template '{rev}: {desc} [{branches}] @ {date}\n'
-  o  11: r11 [] @ 11.00
+  o  11: r11 [] @ 11 0
   |
-  o  10: r10 [] @ 10.00
+  o  10: r10 [] @ 10 0
   |
-  o    9: r9 [] @ 9.00
+  o    9: r9 [] @ 9 0
   |\
-  | o  8: r8 [temp] @ 8.00
+  | o  8: r8 [temp] @ 8 0
   | |
-  | o  7: r7 [temp] @ 7.00
+  | o  7: r7 [temp] @ 7 0
   | |
-  | o  6: r6 [temp] @ 6.00
+  | o  6: r6 [temp] @ 6 0
   | |
-  | o  5: r5 [temp] @ 5.00
+  | o  5: r5 [temp] @ 5 0
   | |
-  o |  4: r4 [] @ 4.00
+  o |  4: r4 [] @ 4 0
   | |
-  o |  3: r3 [] @ 3.00
+  o |  3: r3 [] @ 3 0
   | |
-  o |  2: r2 [] @ 2.00
+  o |  2: r2 [] @ 2 0
   |/
-  o  1: r1 [] @ 1.00
+  o  1: r1 [] @ 1 0
   |
-  o  0: r0 [] @ 0.00
+  o  0: r0 [] @ 0 0
   
 
 overwritten files, starting on a non-default branch
@@ -88,29 +88,29 @@  tip
   000000000000
 glog
   $ hg log -G --template '{rev}: {desc} [{branches}] @ {date}\n'
-  o  11: r11 [] @ 11.00
+  o  11: r11 [] @ 11 0
   |
-  o  10: r10 [] @ 10.00
+  o  10: r10 [] @ 10 0
   |
-  o    9: r9 [] @ 9.00
+  o    9: r9 [] @ 9 0
   |\
-  | o  8: r8 [temp] @ 8.00
+  | o  8: r8 [temp] @ 8 0
   | |
-  | o  7: r7 [temp] @ 7.00
+  | o  7: r7 [temp] @ 7 0
   | |
-  | o  6: r6 [temp] @ 6.00
+  | o  6: r6 [temp] @ 6 0
   | |
-  | o  5: r5 [temp] @ 5.00
+  | o  5: r5 [temp] @ 5 0
   | |
-  o |  4: r4 [] @ 4.00
+  o |  4: r4 [] @ 4 0
   | |
-  o |  3: r3 [] @ 3.00
+  o |  3: r3 [] @ 3 0
   | |
-  o |  2: r2 [] @ 2.00
+  o |  2: r2 [] @ 2 0
   |/
-  o  1: r1 [] @ 1.00
+  o  1: r1 [] @ 1 0
   |
-  o  0: r0 [start] @ 0.00
+  o  0: r0 [start] @ 0 0
   
 glog of
   $ hg log -G --template '{rev}: {desc} [{branches}]\n' of
@@ -164,29 +164,29 @@  tip
   000000000000
 glog
   $ hg log -G --template '{rev}: {desc} [{branches}] @ {date}\n'
-  o  11: r11 [] @ 11.00
+  o  11: r11 [] @ 11 0
   |
-  o  10: r10 [] @ 10.00
+  o  10: r10 [] @ 10 0
   |
-  o    9: r9 [] @ 9.00
+  o    9: r9 [] @ 9 0
   |\
-  | o  8: r8 [temp] @ 8.00
+  | o  8: r8 [temp] @ 8 0
   | |
-  | o  7: r7 [temp] @ 7.00
+  | o  7: r7 [temp] @ 7 0
   | |
-  | o  6: r6 [temp] @ 6.00
+  | o  6: r6 [temp] @ 6 0
   | |
-  | o  5: r5 [temp] @ 5.00
+  | o  5: r5 [temp] @ 5 0
   | |
-  o |  4: r4 [] @ 4.00
+  o |  4: r4 [] @ 4 0
   | |
-  o |  3: r3 [] @ 3.00
+  o |  3: r3 [] @ 3 0
   | |
-  o |  2: r2 [] @ 2.00
+  o |  2: r2 [] @ 2 0
   |/
-  o  1: r1 [] @ 1.00
+  o  1: r1 [] @ 1 0
   |
-  o  0: r0 [] @ 0.00
+  o  0: r0 [] @ 0 0
   
 glog mf
   $ hg log -G --template '{rev}: {desc} [{branches}]\n' mf
diff --git a/tests/test-mq-header-date.t b/tests/test-mq-header-date.t
--- a/tests/test-mq-header-date.t
+++ b/tests/test-mq-header-date.t
@@ -202,7 +202,7 @@ 
   ==== qnew -d
   Date: 3 0
   
-  0: 758bd2596a39 [mq]: 1.patch - test - 3.00
+  0: 758bd2596a39 [mq]: 1.patch - test - 3 0
   ==== qref
   adding 1
   Date: 3 0
@@ -212,7 +212,7 @@ 
   +++ b/1
   @@ -0,0 +1,1 @@
   +1
-  0: 8c640e9949a8 [mq]: 1.patch - test - 3.00
+  0: 8c640e9949a8 [mq]: 1.patch - test - 3 0
   ==== qref -d
   Date: 4 0
   
@@ -221,7 +221,7 @@ 
   +++ b/1
   @@ -0,0 +1,1 @@
   +1
-  0: 4a67dfeea974 [mq]: 1.patch - test - 4.00
+  0: 4a67dfeea974 [mq]: 1.patch - test - 4 0
   ==== qnew
   adding 2
   diff -r ... 2
@@ -248,8 +248,8 @@ 
   
   Three
   
-  1: 2a9ef0bdefba Three - test - 6.00
-  0: 4a67dfeea974 [mq]: 1.patch - test - 4.00
+  1: 2a9ef0bdefba Three - test - 6 0
+  0: 4a67dfeea974 [mq]: 1.patch - test - 4 0
   ==== qref
   adding 3
   Date: 6 0
@@ -261,8 +261,8 @@ 
   +++ b/3
   @@ -0,0 +1,1 @@
   +3
-  1: 7f19ad9eea7b Three - test - 6.00
-  0: 4a67dfeea974 [mq]: 1.patch - test - 4.00
+  1: 7f19ad9eea7b Three - test - 6 0
+  0: 4a67dfeea974 [mq]: 1.patch - test - 4 0
   ==== qref -m
   Date: 6 0
   
@@ -273,8 +273,8 @@ 
   +++ b/3
   @@ -0,0 +1,1 @@
   +3
-  1: 7ff7377793e3 Drei - test - 6.00
-  0: 4a67dfeea974 [mq]: 1.patch - test - 4.00
+  1: 7ff7377793e3 Drei - test - 6 0
+  0: 4a67dfeea974 [mq]: 1.patch - test - 4 0
   ==== qref -d
   Date: 7 0
   
@@ -285,8 +285,8 @@ 
   +++ b/3
   @@ -0,0 +1,1 @@
   +3
-  1: d89d3144f518 Drei - test - 7.00
-  0: 4a67dfeea974 [mq]: 1.patch - test - 4.00
+  1: d89d3144f518 Drei - test - 7 0
+  0: 4a67dfeea974 [mq]: 1.patch - test - 4 0
   ==== qref -d -m
   Date: 8 0
   
@@ -297,8 +297,8 @@ 
   +++ b/3
   @@ -0,0 +1,1 @@
   +3
-  1: b1b6b0fe0e6d Three (again) - test - 8.00
-  0: 4a67dfeea974 [mq]: 1.patch - test - 4.00
+  1: b1b6b0fe0e6d Three (again) - test - 8 0
+  0: 4a67dfeea974 [mq]: 1.patch - test - 4 0
   ==== qnew -m
   adding 4
   Four
@@ -331,9 +331,9 @@ 
   now at: 3.patch
   # HG changeset patch
   # Date 10 0
-  2: d16a272220d2 imported patch 5.patch - test - 10.00
-  1: b1b6b0fe0e6d Three (again) - test - 8.00
-  0: 4a67dfeea974 [mq]: 1.patch - test - 4.00
+  2: d16a272220d2 imported patch 5.patch - test - 10 0
+  1: b1b6b0fe0e6d Three (again) - test - 8 0
+  0: 4a67dfeea974 [mq]: 1.patch - test - 4 0
   ==== hg qref
   adding 5
   # HG changeset patch
@@ -345,9 +345,9 @@ 
   +++ b/5
   @@ -0,0 +1,1 @@
   +5
-  2: 5dbf69c07df9 [mq]: 5.patch - test - 10.00
-  1: b1b6b0fe0e6d Three (again) - test - 8.00
-  0: 4a67dfeea974 [mq]: 1.patch - test - 4.00
+  2: 5dbf69c07df9 [mq]: 5.patch - test - 10 0
+  1: b1b6b0fe0e6d Three (again) - test - 8 0
+  0: 4a67dfeea974 [mq]: 1.patch - test - 4 0
   ==== hg qref -d
   # HG changeset patch
   # Date 11 0
@@ -358,9 +358,9 @@ 
   +++ b/5
   @@ -0,0 +1,1 @@
   +5
-  2: 049de6af0c1d [mq]: 5.patch - test - 11.00
-  1: b1b6b0fe0e6d Three (again) - test - 8.00
-  0: 4a67dfeea974 [mq]: 1.patch - test - 4.00
+  2: 049de6af0c1d [mq]: 5.patch - test - 11 0
+  1: b1b6b0fe0e6d Three (again) - test - 8 0
+  0: 4a67dfeea974 [mq]: 1.patch - test - 4 0
   ==== qnew with plain header
   popping 6.patch
   now at: 5.patch
@@ -380,10 +380,10 @@ 
   +++ b/6
   @@ -0,0 +1,1 @@
   +6
-  3: 038c46b02a56 [mq]: 6.patch - test - 12.00
-  2: 049de6af0c1d [mq]: 5.patch - test - 11.00
-  1: b1b6b0fe0e6d Three (again) - test - 8.00
-  0: 4a67dfeea974 [mq]: 1.patch - test - 4.00
+  3: 038c46b02a56 [mq]: 6.patch - test - 12 0
+  2: 049de6af0c1d [mq]: 5.patch - test - 11 0
+  1: b1b6b0fe0e6d Three (again) - test - 8 0
+  0: 4a67dfeea974 [mq]: 1.patch - test - 4 0
   ==== hg qref -d
   Date: 13 0
   
@@ -392,10 +392,10 @@ 
   +++ b/6
   @@ -0,0 +1,1 @@
   +6
-  3: 2785642ea4b4 [mq]: 6.patch - test - 13.00
-  2: 049de6af0c1d [mq]: 5.patch - test - 11.00
-  1: b1b6b0fe0e6d Three (again) - test - 8.00
-  0: 4a67dfeea974 [mq]: 1.patch - test - 4.00
+  3: 2785642ea4b4 [mq]: 6.patch - test - 13 0
+  2: 049de6af0c1d [mq]: 5.patch - test - 11 0
+  1: b1b6b0fe0e6d Three (again) - test - 8 0
+  0: 4a67dfeea974 [mq]: 1.patch - test - 4 0
   popping 6.patch
   now at: 5.patch
   ==== qnew -u
@@ -448,10 +448,10 @@ 
   +++ b/7
   @@ -0,0 +1,1 @@
   +7
-  3: 4f9d07369cc4 [mq]: 7.patch - john - 13.00
-  2: 049de6af0c1d [mq]: 5.patch - test - 11.00
-  1: b1b6b0fe0e6d Three (again) - test - 8.00
-  0: 4a67dfeea974 [mq]: 1.patch - test - 4.00
+  3: 4f9d07369cc4 [mq]: 7.patch - john - 13 0
+  2: 049de6af0c1d [mq]: 5.patch - test - 11 0
+  1: b1b6b0fe0e6d Three (again) - test - 8 0
+  0: 4a67dfeea974 [mq]: 1.patch - test - 4 0
   ==== qnew
   adding 8
   diff -r ... 8
@@ -523,10 +523,10 @@ 
   applying 5.patch
   applying 7.patch
   now at: 7.patch
-  3: d26a5b7ffce1 imported patch 7.patch - john - 13.00
-  2: dda6cf77060a imported patch 5.patch - test - 11.00
-  1: 25e32d66c8c7 Three (again) - test - 8.00
-  0: e5011c0211fe imported patch 1.patch - test - 4.00
+  3: d26a5b7ffce1 imported patch 7.patch - john - 13 0
+  2: dda6cf77060a imported patch 5.patch - test - 11 0
+  1: 25e32d66c8c7 Three (again) - test - 8 0
+  0: e5011c0211fe imported patch 1.patch - test - 4 0
   $ rm -r sandbox
 
 ======= hg headers
@@ -540,7 +540,7 @@ 
   # Date 3 0
   # Parent 
   
-  0: 758bd2596a39 [mq]: 1.patch - test - 3.00
+  0: 758bd2596a39 [mq]: 1.patch - test - 3 0
   ==== qref
   adding 1
   # HG changeset patch
@@ -552,7 +552,7 @@ 
   +++ b/1
   @@ -0,0 +1,1 @@
   +1
-  0: 8c640e9949a8 [mq]: 1.patch - test - 3.00
+  0: 8c640e9949a8 [mq]: 1.patch - test - 3 0
   ==== qref -d
   # HG changeset patch
   # Date 4 0
@@ -563,7 +563,7 @@ 
   +++ b/1
   @@ -0,0 +1,1 @@
   +1
-  0: 4a67dfeea974 [mq]: 1.patch - test - 4.00
+  0: 4a67dfeea974 [mq]: 1.patch - test - 4 0
   ==== qnew
   adding 2
   # HG changeset patch
@@ -596,8 +596,8 @@ 
   # Parent 
   Three
   
-  1: 2a9ef0bdefba Three - test - 6.00
-  0: 4a67dfeea974 [mq]: 1.patch - test - 4.00
+  1: 2a9ef0bdefba Three - test - 6 0
+  0: 4a67dfeea974 [mq]: 1.patch - test - 4 0
   ==== qref
   adding 3
   # HG changeset patch
@@ -610,8 +610,8 @@ 
   +++ b/3
   @@ -0,0 +1,1 @@
   +3
-  1: 7f19ad9eea7b Three - test - 6.00
-  0: 4a67dfeea974 [mq]: 1.patch - test - 4.00
+  1: 7f19ad9eea7b Three - test - 6 0
+  0: 4a67dfeea974 [mq]: 1.patch - test - 4 0
   ==== qref -m
   # HG changeset patch
   # Date 6 0
@@ -623,8 +623,8 @@ 
   +++ b/3
   @@ -0,0 +1,1 @@
   +3
-  1: 7ff7377793e3 Drei - test - 6.00
-  0: 4a67dfeea974 [mq]: 1.patch - test - 4.00
+  1: 7ff7377793e3 Drei - test - 6 0
+  0: 4a67dfeea974 [mq]: 1.patch - test - 4 0
   ==== qref -d
   # HG changeset patch
   # Date 7 0
@@ -636,8 +636,8 @@ 
   +++ b/3
   @@ -0,0 +1,1 @@
   +3
-  1: d89d3144f518 Drei - test - 7.00
-  0: 4a67dfeea974 [mq]: 1.patch - test - 4.00
+  1: d89d3144f518 Drei - test - 7 0
+  0: 4a67dfeea974 [mq]: 1.patch - test - 4 0
   ==== qref -d -m
   # HG changeset patch
   # Date 8 0
@@ -649,8 +649,8 @@ 
   +++ b/3
   @@ -0,0 +1,1 @@
   +3
-  1: b1b6b0fe0e6d Three (again) - test - 8.00
-  0: 4a67dfeea974 [mq]: 1.patch - test - 4.00
+  1: b1b6b0fe0e6d Three (again) - test - 8 0
+  0: 4a67dfeea974 [mq]: 1.patch - test - 4 0
   ==== qnew -m
   adding 4
   # HG changeset patch
@@ -686,9 +686,9 @@ 
   now at: 3.patch
   # HG changeset patch
   # Date 10 0
-  2: d16a272220d2 imported patch 5.patch - test - 10.00
-  1: b1b6b0fe0e6d Three (again) - test - 8.00
-  0: 4a67dfeea974 [mq]: 1.patch - test - 4.00
+  2: d16a272220d2 imported patch 5.patch - test - 10 0
+  1: b1b6b0fe0e6d Three (again) - test - 8 0
+  0: 4a67dfeea974 [mq]: 1.patch - test - 4 0
   ==== hg qref
   adding 5
   # HG changeset patch
@@ -700,9 +700,9 @@ 
   +++ b/5
   @@ -0,0 +1,1 @@
   +5
-  2: 5dbf69c07df9 [mq]: 5.patch - test - 10.00
-  1: b1b6b0fe0e6d Three (again) - test - 8.00
-  0: 4a67dfeea974 [mq]: 1.patch - test - 4.00
+  2: 5dbf69c07df9 [mq]: 5.patch - test - 10 0
+  1: b1b6b0fe0e6d Three (again) - test - 8 0
+  0: 4a67dfeea974 [mq]: 1.patch - test - 4 0
   ==== hg qref -d
   # HG changeset patch
   # Date 11 0
@@ -713,9 +713,9 @@ 
   +++ b/5
   @@ -0,0 +1,1 @@
   +5
-  2: 049de6af0c1d [mq]: 5.patch - test - 11.00
-  1: b1b6b0fe0e6d Three (again) - test - 8.00
-  0: 4a67dfeea974 [mq]: 1.patch - test - 4.00
+  2: 049de6af0c1d [mq]: 5.patch - test - 11 0
+  1: b1b6b0fe0e6d Three (again) - test - 8 0
+  0: 4a67dfeea974 [mq]: 1.patch - test - 4 0
   ==== qnew with plain header
   popping 6.patch
   now at: 5.patch
@@ -735,10 +735,10 @@ 
   +++ b/6
   @@ -0,0 +1,1 @@
   +6
-  3: 038c46b02a56 [mq]: 6.patch - test - 12.00
-  2: 049de6af0c1d [mq]: 5.patch - test - 11.00
-  1: b1b6b0fe0e6d Three (again) - test - 8.00
-  0: 4a67dfeea974 [mq]: 1.patch - test - 4.00
+  3: 038c46b02a56 [mq]: 6.patch - test - 12 0
+  2: 049de6af0c1d [mq]: 5.patch - test - 11 0
+  1: b1b6b0fe0e6d Three (again) - test - 8 0
+  0: 4a67dfeea974 [mq]: 1.patch - test - 4 0
   ==== hg qref -d
   Date: 13 0
   
@@ -747,10 +747,10 @@ 
   +++ b/6
   @@ -0,0 +1,1 @@
   +6
-  3: 2785642ea4b4 [mq]: 6.patch - test - 13.00
-  2: 049de6af0c1d [mq]: 5.patch - test - 11.00
-  1: b1b6b0fe0e6d Three (again) - test - 8.00
-  0: 4a67dfeea974 [mq]: 1.patch - test - 4.00
+  3: 2785642ea4b4 [mq]: 6.patch - test - 13 0
+  2: 049de6af0c1d [mq]: 5.patch - test - 11 0
+  1: b1b6b0fe0e6d Three (again) - test - 8 0
+  0: 4a67dfeea974 [mq]: 1.patch - test - 4 0
   popping 6.patch
   now at: 5.patch
   ==== qnew -u
@@ -811,10 +811,10 @@ 
   +++ b/7
   @@ -0,0 +1,1 @@
   +7
-  3: 4f9d07369cc4 [mq]: 7.patch - john - 13.00
-  2: 049de6af0c1d [mq]: 5.patch - test - 11.00
-  1: b1b6b0fe0e6d Three (again) - test - 8.00
-  0: 4a67dfeea974 [mq]: 1.patch - test - 4.00
+  3: 4f9d07369cc4 [mq]: 7.patch - john - 13 0
+  2: 049de6af0c1d [mq]: 5.patch - test - 11 0
+  1: b1b6b0fe0e6d Three (again) - test - 8 0
+  0: 4a67dfeea974 [mq]: 1.patch - test - 4 0
   ==== qnew
   adding 8
   # HG changeset patch
@@ -894,8 +894,8 @@ 
   applying 5.patch
   applying 7.patch
   now at: 7.patch
-  3: d26a5b7ffce1 imported patch 7.patch - john - 13.00
-  2: dda6cf77060a imported patch 5.patch - test - 11.00
-  1: 25e32d66c8c7 Three (again) - test - 8.00
-  0: e5011c0211fe imported patch 1.patch - test - 4.00
+  3: d26a5b7ffce1 imported patch 7.patch - john - 13 0
+  2: dda6cf77060a imported patch 5.patch - test - 11 0
+  1: 25e32d66c8c7 Three (again) - test - 8 0
+  0: e5011c0211fe imported patch 1.patch - test - 4 0
   $ rm -r sandbox