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.
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"
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$
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
Fixed by http://selenic.com/repo/hg/rev/c38c3fdc8b93 Matt Mackall <mpm@selenic.com> date: allow %z in format (issue4040) (please test the fix)
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
The fix was in 2.9, released Feb 2014.
Thanks for the confirmation. It's a pity that Ubuntu 14.04 LTS uses the 2.8 branch :/