From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: AS53758 23.128.96.0/24 X-Spam-Status: No, score=-3.8 required=3.0 tests=AWL,BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE, SPF_HELO_PASS,SPF_PASS shortcircuit=no autolearn=ham autolearn_force=no version=3.4.2 Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by dcvr.yhbt.net (Postfix) with ESMTP id A91D01F953 for ; Mon, 1 Nov 2021 04:04:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229528AbhKAEGe (ORCPT ); Mon, 1 Nov 2021 00:06:34 -0400 Received: from cloud.peff.net ([104.130.231.41]:50628 "EHLO cloud.peff.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229462AbhKAEGa (ORCPT ); Mon, 1 Nov 2021 00:06:30 -0400 Received: (qmail 30408 invoked by uid 109); 1 Nov 2021 04:03:58 -0000 Received: from Unknown (HELO peff.net) (10.0.1.2) by cloud.peff.net (qpsmtpd/0.94) with ESMTP; Mon, 01 Nov 2021 04:03:58 +0000 Authentication-Results: cloud.peff.net; auth=none Received: (qmail 15858 invoked by uid 111); 1 Nov 2021 04:03:58 -0000 Received: from coredump.intra.peff.net (HELO sigill.intra.peff.net) (10.0.0.2) by peff.net (qpsmtpd/0.94) with (TLS_AES_256_GCM_SHA384 encrypted) ESMTPS; Mon, 01 Nov 2021 00:03:58 -0400 Authentication-Results: peff.net; auth=none Date: Mon, 1 Nov 2021 00:03:56 -0400 From: Jeff King To: Junio C Hamano Cc: Dongsheng Song , Git Mailing List Subject: Re: timezone related bug of git Message-ID: References: MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline In-Reply-To: Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org On Sun, Oct 31, 2021 at 11:46:40AM -0700, Junio C Hamano wrote: > Dongsheng Song writes: > > > Thank you for the clarification, it's really a disappointing answer. > > The situation may be disappointing, but I found the answer eminently > clear and helpful. The most disappointing thing IMHO is the lousy state of system-level date routines. ;) I have some patches working towards allowing timestamps before 1970, and the system routines are quite unreliable (both in giving insufficient portable interfaces, but also just doing weird things with negative values). > > Perhaps the manual needs to be clearer about this limitation. > > Sounds like we have a volunteer ;-)? Yeah, I'd be happy if somebody wanted to note this in the manual. But if anybody wants to pursue manually intercepting %s, I think the patch below might point them in the right direction. I won't be at all surprised if it has funny corner cases. Our tm_to_time_t() is pretty basic and hacky. We can't use mktime() because it only handles the current system timezone. OTOH, I think the tz_offset we're undoing here originally came from comparing mktime() versus tm_to_time_t() via local_time_tzoffset(), so it could be cancelling out any bugs exactly. :) So maybe the code below is sufficient, but we'd probably at least want some tests on top. Maybe something somebody interested would like to pick up and run with? --- diff --git a/cache.h b/cache.h index eba12487b9..aa6f380d10 100644 --- a/cache.h +++ b/cache.h @@ -1588,6 +1588,7 @@ timestamp_t approxidate_careful(const char *, int *); timestamp_t approxidate_relative(const char *date); void parse_date_format(const char *format, struct date_mode *mode); int date_overflows(timestamp_t date); +time_t tm_to_time_t(const struct tm *tm); #define IDENT_STRICT 1 #define IDENT_NO_DATE 2 diff --git a/date.c b/date.c index c55ea47e96..84bb4451c1 100644 --- a/date.c +++ b/date.c @@ -9,7 +9,7 @@ /* * This is like mktime, but without normalization of tm_wday and tm_yday. */ -static time_t tm_to_time_t(const struct tm *tm) +time_t tm_to_time_t(const struct tm *tm) { static const int mdays[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 diff --git a/strbuf.c b/strbuf.c index b22e981655..8b8b1900bc 100644 --- a/strbuf.c +++ b/strbuf.c @@ -1019,6 +1019,13 @@ void strbuf_addftime(struct strbuf *sb, const char *fmt, const struct tm *tm, strbuf_addstr(&munged_fmt, "%%"); fmt++; break; + case 's': + strbuf_addf(&munged_fmt, "%"PRItime, + tm_to_time_t(tm) - + 3600 * (tz_offset / 100) - + 60 * (tz_offset % 100)); + fmt++; + break; case 'z': strbuf_addf(&munged_fmt, "%+05d", tz_offset); fmt++;