git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: Jeff King <peff@peff.net>
To: clime <clime7@gmail.com>
Cc: Git List <git@vger.kernel.org>
Subject: Re: :format:%s for date fields seems to be shifted by timezone
Date: Mon, 4 May 2020 11:43:43 -0400	[thread overview]
Message-ID: <20200504154343.GA12842@coredump.intra.peff.net> (raw)
In-Reply-To: <CAGqZTUu2U6FFXGTXihC64O0gB5Bz_Z3MbD750kMoJWMciAGH6w@mail.gmail.com>

On Sun, May 03, 2020 at 12:15:14PM +0200, clime wrote:

> my current timezone is UTC+0200.
> 
> I create a test repo, add one commit and create a tag:
> 
> Now:
> 
> $  git for-each-ref --format="%(taggerdate:format:%s)" refs/tags
> 1588504146
> 
> $ date +"%s"
> 1588500585
> 
> $  git for-each-ref --format="%(taggerdate:raw)" refs/tags
> 1588500546 +0200
> 
> Somehow %(taggerdate:format:%s) gives a Unix timestamp which is one
> hour in future and it is different than what ` date +"%s"` gives
> around approximately the same time the tag was created.

It's caused by strftime() being clever with DST. Try this:

  git commit --date=@1559361600 --allow-empty -m summer
  git commit --date=@1577854800 --allow-empty -m winter
  git log --format=%ad --date=unix >unix
  git log --format=%ad --date=format:%s >strftime
  diff -u unix strftime

We get the winter time right, but the summer time wrong.

The issue is that strftime() takes a broken-down "struct tm", not a unix
time_t. We have all of the right values for hour/minute/etc there, so
using "format:%H:%M:%S" prints what you'd expect. But we never set the
"isdst" field, so when it tries to convert back to unix time, it applies
a one-hour offset (if it's "summer" in your local timezone).

Unfortunately I don't think we can solve this easily. If we were
operating completely in your local timezone, then we would have gotten
that "struct tm" from localtime(), and its isdst field would be set
properly. And indeed, if you use "--date=format-local:%s", the problem
goes away.

But when we're formatting in the original author's timezone, which is
the default, we have no idea if they were in dst then or not. We only
know their offset-to-gmt, so we munge the time_t ourselves and use
gmtime().

So there are a few reasons I think this is the best we can do:

 - the full timezone information literally isn't there in Git; we might
   know the author was in +0200, but we don't know if they were
   observing DST, or if they were simply in a timezone further east.

 - even if we had a zone, there's no system function to convert a time_t
   to a tm in an arbitrary timezone (hence the gmtime() hack above;
   we've tried playing games with $TZ and tzset(), but it's awkward and
   unportable)

 - likewise, strftime() is doing the reverse conversion using the local
   timezone anyway, which would be wrong.

So my advice is not to use "%s" (which isn't portable anyway). Use
"--date=unix" or "%(taggerdate:unix)".

-Peff

  reply	other threads:[~2020-05-04 15:43 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-05-03 10:15 :format:%s for date fields seems to be shifted by timezone clime
2020-05-04 15:43 ` Jeff King [this message]
2020-05-06 18:03   ` clime
2020-05-06 19:06     ` Jeff King

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: http://vger.kernel.org/majordomo-info.html

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200504154343.GA12842@coredump.intra.peff.net \
    --to=peff@peff.net \
    --cc=clime7@gmail.com \
    --cc=git@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).