Bug 4040 - templating: the date-formatting filter always expands 'numeric timezone specifier' format "%z" to "+0000"
Summary: templating: the date-formatting filter always expands 'numeric timezone speci...
Status: RESOLVED FIXED
Alias: None
Product: Mercurial
Classification: Unclassified
Component: Mercurial (show other bugs)
Version: 2.8.2
Hardware: PC Linux
: normal bug
Assignee: Bugzilla
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2013-09-17 20:03 UTC by ytr
Modified: 2015-11-16 23:58 UTC (History)
5 users (show)

See Also:
Python Version: ---


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description ytr 2013-09-17 20:03 UTC
According to "hg help templating", there is a keyword called "date" which relates the "date information". Then, to format such a datetime, any one of several filters is to be used. One of those filters is called "date" again. That filter can (like all filters) be called like a function. Unlike most filters, the "date()" function call can include an optional second parameter, the format.

It seems that the specifics of that format aren't specified by any hg documentation directly, though the example already suggests that the format is passed to the standard C library's strftime (or to a similar function elsewhere in hg or python).

In any case, during tests the format appeared to accept the specifier "%Z" (capital letter Z) which is to return an abbreviation for a timezone name, and more relevantly the format specifier "%z" (small letter Z) which is to return a numeric timezone specifier.

However, it became apparent that neither of these specifiers works as expected. Crucially, this makes it impossible to correctly use a custom format and have the written datetime properly include correct timezone information.

In the testing log in the follow-up comment, the results were that all the date and time elements of the written datetime matched those of the predefined format filters (isodatesec, etc) while the numeric timezone specifier always was "+0000".

( Additionally, the timezone abbreviation always was that of the local timezone currently configured for the invoked hg command. (Not to be confused with the local timezone of the datetime stamp internally stored for the commit.) However, assuming hg doesn't and shouldn't store abbreviations with the commits, the specifier %Z for the abbreviation arguably just shouldn't be supported at all. And with the possible ambiguities, such abbreviations already don't help with formatting and transmitting an unambiguous reference to UTC. )

In the tests, the expected result would be that for the %z format, the applicable numeric timezone specifier would occur rather than "+0000". For the "formatted date" that's "+0200" (because the commit's datetime was specified with that, and "7200 seconds ahead of UTC" is the timezone stored internally for the commit) and for the "formatted localdate" that's "+0400" (matching the currently-configured local timezone, regardless the commit's internally-stored timezone).

Basically, the "formatted" fields should numerically match the isodatesec-formatted datetime stamps just below them.

I tested this with almost the same script some time ago using 2.6.2 already; like 2.7.1 here it always expanded the "%z" to "+0000" in these tests.
Comment 1 ytr 2013-09-17 20:04 UTC
Script used for testing:

export TZ=TST-04:00
date '+Active timezone is called "%Z" and is %:z ahead of UTC.'
hg version
rm * -f
rm .hg -rf
hg init .
true > foo
hg add foo
hg ci -d "2000-01-01 00:00:00 +0200" -m "test commit" -u "test user <test@example.org>"
hg log --template "date       : {date}\ndate|hgdate: {date|hgdate}\nformatted date  : {date(date, '%Y-%m-%d %H:%M:%S %z %a %Z')}\ndate|isodatesec : {date|isodatesec}\ndate|rfc3339date: {date|rfc3339date}\ndate|rfc822date : {date|rfc822date}\ndate|date       : {date|date}\n\n"
hg log --template "localdate       : {date|localdate}\nlocaldate|hgdate: {date|localdate|hgdate}\nformatted localdate  : {date(date|localdate, '%Y-%m-%d %H:%M:%S %z %a %Z')}\nlocaldate|isodatesec : {date|localdate|isodatesec}\nlocaldate|rfc3339date: {date|localdate|rfc3339date}\nlocaldate|rfc822date : {date|localdate|rfc822date}\nlocaldate|date       : {date|localdate|date}\n\n"
Comment 2 ytr 2013-09-17 20:05 UTC
Output of testing script:

ytr@ytr-m1:~/test/repo$ export TZ=TST-04:00
ytr@ytr-m1:~/test/repo$ date '+Active timezone is called "%Z" and is %:z ahead of UTC.'
Active timezone is called "TST" and is +04:00 ahead of UTC.
ytr@ytr-m1:~/test/repo$ hg version
Mercurial Distributed SCM (version 2.7.1)
(see http://mercurial.selenic.com for more information)

Copyright (C) 2005-2013 Matt Mackall and others
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
ytr@ytr-m1:~/test/repo$ rm * -f
ytr@ytr-m1:~/test/repo$ rm .hg -rf
ytr@ytr-m1:~/test/repo$ hg init .
ytr@ytr-m1:~/test/repo$ true > foo
ytr@ytr-m1:~/test/repo$ hg add foo
ytr@ytr-m1:~/test/repo$ hg ci -d "2000-01-01 00:00:00 +0200" -m "test commit" -u "test user <test@example.org>"
ytr@ytr-m1:~/test/repo$ hg log --template "date       : {date}\ndate|hgdate: {date|hgdate}\nformatted date  : {date(date, '%Y-%m-%d %H:%M:%S %z %a %Z')}\ndate|isodatesec : {date|isodatesec}\ndate|rfc3339date: {date|rfc3339date}\ndate|rfc822date : {date|rfc822date}\ndate|date       : {date|date}\n\n"
date       : 946677600.0-7200
date|hgdate: 946677600 -7200
formatted date  : 2000-01-01 00:00:00 +0000 Sat TST
date|isodatesec : 2000-01-01 00:00:00 +0200
date|rfc3339date: 2000-01-01T00:00:00+02:00
date|rfc822date : Sat, 01 Jan 2000 00:00:00 +0200
date|date       : Sat Jan 01 00:00:00 2000 +0200

ytr@ytr-m1:~/test/repo$ hg log --template "localdate       : {date|localdate}\nlocaldate|hgdate: {date|localdate|hgdate}\nformatted localdate  : {date(date|localdate, '%Y-%m-%d %H:%M:%S %z %a %Z')}\nlocaldate|isodatesec : {date|localdate|isodatesec}\nlocaldate|rfc3339date: {date|localdate|rfc3339date}\nlocaldate|rfc822date : {date|localdate|rfc822date}\nlocaldate|date       : {date|localdate|date}\n\n"
localdate       : 946677600.0-14400
localdate|hgdate: 946677600 -14400
formatted localdate  : 2000-01-01 02:00:00 +0000 Sat TST
localdate|isodatesec : 2000-01-01 02:00:00 +0400
localdate|rfc3339date: 2000-01-01T02:00:00+04:00
localdate|rfc822date : Sat, 01 Jan 2000 02:00:00 +0400
localdate|date       : Sat Jan 01 02:00:00 2000 +0400

ytr@ytr-m1:~/test/repo$
Comment 3 ytr 2013-09-17 20:06 UTC
libc version in use:

ytr@ytr-m1:~/test/repo$ dpkg-query -W -f='(${Architecture} ${Package} ${Version}) ${binary:Summary}\n' libc6
(i386 libc6 2.17-92) Embedded GNU C Library: Shared libraries
ytr@ytr-m1:~/test/repo$ $(ldd $(cat $(which hg) | head -n 1 | sed -re 's/^#! *([^ ]+)( .*)?$/\1/') | grep "libc\." | sed -re 's/^ *[^ ]+ *=> *([^ ]*)( +.*)?$/\1/' | tee /dev/stderr )
/lib/i386-linux-gnu/i686/cmov/libc.so.6
GNU C Library (Debian EGLIBC 2.17-92) stable release version 2.17, by Roland McGrath et al.
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 4.7.3.
Compiled on a Linux 3.10.3 system on 2013-08-01.
Available extensions:
	crypt add-on version 2.1 by Michael Glad and others
	GNU Libidn by Simon Josefsson
	Native POSIX Threads Library by Ulrich Drepper et al
	BIND-8.2.3-T5B
libc ABIs: UNIQUE IFUNC
For bug reporting instructions, please see:
<http://www.debian.org/Bugs/>.
ytr@ytr-m1:~/test/repo$ 

python version in use:

ytr@ytr-m1:~/test/repo$ python --version
Python 2.7.3
Comment 4 HG Bot 2013-11-07 16:45 UTC
Fixed by http://selenic.com/repo/hg/rev/c38c3fdc8b93
Matt Mackall <mpm@selenic.com>
date: allow %z in format (issue4040)

(please test the fix)
Comment 5 Valdemar Jakobsen 2015-11-16 02:18 UTC
2 years later, I just discovered this bug in Mercurial 2.8.2 and eventually found my way to this "fixed" issue from 2.7.1.

Using the script below, I ran the same tests to demonstrate the incorrect behaviour.

+ hg version

> Mercurial Distributed SCM (version 2.8.2)
> (see http://mercurial.selenic.com for more information)
>  
> Copyright (C) 2005-2013 Matt Mackall and others
> This is free software; see the source for copying conditions. There is NO
> warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

+ rm -rf hg-date-test
+ mkdir hg-date-test
+ cd hg-date-test
+ TZ=TST-04:00
+ date '+Active timezone is called "%Z" and is %:z ahead of UTC.'
  
> Active timezone is called "TST" and is +04:00 ahead of UTC.

+ hg init .
+ true
+ hg add foo
+ hg ci -d '2000-01-01 00:00:00 +0200' -m 'test commit' -u 'test user <test@example.org>'
+ hg log --template 'date                  : {date}          \ndate|hgdate           : {date|hgdate}          \nformatted date        : {date(date,           '\''%Y-%m-%d %H:%M:%S %z %a %Z'\'')}\ndate|isodatesec       : {date|isodatesec}          \ndate|rfc3339date      : {date|rfc3339date}          \ndate|rfc822date       : {date|rfc822date}          \ndate|date             : {date|date}\n\n'

> date                  : 946677600.0-7200
> date|hgdate           : 946677600 -7200
> formatted date        : 2000-01-01 00:00:00 +0000 Sat TST
> date|isodatesec       : 2000-01-01 00:00:00 +0200
> date|rfc3339date      : 2000-01-01T00:00:00+02:00
> date|rfc822date       : Sat, 01 Jan 2000 00:00:00 +0200
> date|date             : Sat Jan 01 00:00:00 2000 +0200

+ hg log --template 'localdate             : {date|localdate}\nlocaldate|hgdate      : {date|localdate|hgdate}\nformatted localdate   : {date(date|localdate, '\''%Y-%m-%d %H:%M:%S %z %a %Z'\'')}\nlocaldate|isodatesec  : {date|localdate|isodatesec}\nlocaldate|rfc3339date : {date|localdate|rfc3339date}\nlocaldate|rfc822date  : {date|localdate|rfc822date}\nlocaldate|date        : {date|localdate|date}\n\n'

> localdate             : 946677600.0-14400
> localdate|hgdate      : 946677600 -14400
> formatted localdate   : 2000-01-01 02:00:00 +0000 Sat TST
> localdate|isodatesec  : 2000-01-01 02:00:00 +0400
> localdate|rfc3339date : 2000-01-01T02:00:00+04:00
> localdate|rfc822date  : Sat, 01 Jan 2000 02:00:00 +0400
> localdate|date        : Sat Jan 01 02:00:00 2000 +0400
Comment 6 Matt Mackall 2015-11-16 15:23 UTC
The fix was in 2.9, released Feb 2014.
Comment 7 Valdemar Jakobsen 2015-11-16 23:58 UTC
Thanks for the confirmation.  It's a pity that Ubuntu 14.04 LTS uses the 2.8 branch :/