On Fri, May 26, 2017 at 8:33 PM, Ulrich Mueller <ulm@xxxxxxxxxx> wrote: > The following commands work as expected (using commit b06d364310 > in the git://git.kernel.org/pub/scm/git/git.git repo as test case): > > $ export TZ=Europe/Berlin > $ git --no-pager log -1 --pretty="%ad" --date=iso b06d364310 > 2017-05-09 23:26:02 +0900 > $ git --no-pager log -1 --pretty="%ad" --date=iso-local b06d364310 > 2017-05-09 16:26:02 +0200 > > However, if I use explicit format: then the output of the time zone is > wrong: > > $ git --no-pager log -1 --pretty="%ad" --date="format:%F %T %z" b06d364310 > 2017-05-09 23:26:02 +0000 > $ git --no-pager log -1 --pretty="%ad" --date="format-local:%F %T %z" b06d364310 > 2017-05-09 16:26:02 +0000 > > I would expect the output to be the same as in the first two examples. This patch solves half of your problem, i.e. makes the latter format-local case work: diff --git a/date.c b/date.c index 63fa99685e..469306ebf5 100644 --- a/date.c +++ b/date.c @@ -70,6 +70,12 @@ static struct tm *time_to_tm(timestamp_t time, int tz) return gmtime(&t); } +static struct tm *time_to_local_tm(timestamp_t time, int tz) +{ + time_t t = gm_time_t(time, tz); + return localtime(&t); +} + /* * What value of "tz" was in effect back then at "time" in the * local timezone? @@ -214,10 +220,14 @@ const char *show_date(timestamp_t time, int tz, const struct date_mode *mode) return timebuf.buf; } - tm = time_to_tm(time, tz); - if (!tm) { - tm = time_to_tm(0, 0); - tz = 0; + if (mode->type == DATE_STRFTIME) { + tm = time_to_local_tm(time, tz); + } else { + tm = time_to_tm(time, tz); + if (!tm) { + tm = time_to_tm(0, 0); + tz = 0; + } } strbuf_reset(&timebuf); There's another test which breaks if we just s/gmtime/localtime/g. As far as I can tell to make the non-local case work we'd need to do a whole dance where we set the TZ variable to e.g. UTC$offset, then call strftime(), then call it again. Maybe there's some way to just specify the tz offset, but I didn't find any in a quick skimming of time.h.