git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: Ben Walton <bdwalton@gmail.com>
To: gitster@pobox.com
Cc: esr@thyrsus.com, git@vger.kernel.org, Ben Walton <bdwalton@gmail.com>
Subject: [PATCH 2/3] Allow Git::get_tz_offset to properly handle DST boundary times
Date: Tue, 15 Jan 2013 23:10:04 +0000	[thread overview]
Message-ID: <1358291405-10173-3-git-send-email-bdwalton@gmail.com> (raw)
In-Reply-To: <1358291405-10173-1-git-send-email-bdwalton@gmail.com>

The Git::get_tz_offset is meant to provide a workalike replacement for
the GNU strftime %z format specifier.  The algorithm used failed to
properly handle DST boundary cases.

For example, the unix time 1162105199 in CST6CDT saw set_tz_offset
improperly return -0600 instead of -0500.

TZ=CST6CDT date -d @1162105199 +"%c %z"
Sun 29 Oct 2006 01:59:59 AM CDT -0500

$ zdump -v /usr/share/zoneinfo/CST6CDT | grep 2006
/usr/share/zoneinfo/CST6CDT  Sun Apr  2 07:59:59 2006 UTC = Sun Apr  2
01:59:59 2006 CST isdst=0 gmtoff=-21600
/usr/share/zoneinfo/CST6CDT  Sun Apr  2 08:00:00 2006 UTC = Sun Apr  2
03:00:00 2006 CDT isdst=1 gmtoff=-18000
/usr/share/zoneinfo/CST6CDT  Sun Oct 29 06:59:59 2006 UTC = Sun Oct 29
01:59:59 2006 CDT isdst=1 gmtoff=-18000
/usr/share/zoneinfo/CST6CDT  Sun Oct 29 07:00:00 2006 UTC = Sun Oct 29
01:00:00 2006 CST isdst=0 gmtoff=-21600

To determine how many hours/minutes away from GMT a particular time
was, we calculated the gmtime() of the requested time value and then
used Time::Local's timelocal() function to turn the GMT-based time
back into a scalar value representing seconds from the epoch.  Because
GMT has no daylight savings time, timelocal() cannot handle the
ambiguous times that occur at DST boundaries since there are two
possible correct results.

To work around the ambiguity at these boundaries, we must take into
account the pre and post conversion values for is_dst as provided by
both the original time value and the value that has been run through
timelocal().  If the is_dst field of the two times disagree then we
must modify the value returned from timelocal() by an hour in the
correct direction.

Signed-off-by: Ben Walton <bdwalton@gmail.com>
---
 perl/Git.pm |   20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/perl/Git.pm b/perl/Git.pm
index 5649bcc..788b9b4 100644
--- a/perl/Git.pm
+++ b/perl/Git.pm
@@ -528,7 +528,27 @@ If TIME is not supplied, the current local time is used.
 sub get_tz_offset {
 	# some systmes don't handle or mishandle %z, so be creative.
 	my $t = shift || time;
+	# timelocal() has a problem when it comes to DST ambiguity so
+	# times that are on a DST boundary cannot be properly converted
+	# using it.  we will possibly adjust its result depending on whehter
+	# pre and post conversions agree on DST
 	my $gm = timelocal(gmtime($t));
+
+	# we need to know whether we were originally in DST or not
+	my $orig_dst = (localtime($t))[8];
+	# and also whether timelocal thinks we're in DST
+	my $conv_dst = (localtime($gm))[8];
+
+	# re-adjust $gm based on the DST value for the two times we're
+	# handling.
+	if ($orig_dst != $conv_dst) {
+		if ($orig_dst == 1) {
+			$gm -= 3600;
+		} else {
+			$gm += 3600;
+		}
+	}
+
 	my $sign = qw( + + - )[ $t <=> $gm ];
 	return sprintf("%s%02d%02d", $sign, (gmtime(abs($t - $gm)))[2,1]);
 }
-- 
1.7.10.4

  parent reply	other threads:[~2013-01-15 23:11 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-01-15 23:10 [PATCH 0/3] Fix a portability issue with git-cvsimport Ben Walton
2013-01-15 23:10 ` [PATCH 1/3] Move Git::SVN::get_tz to Git::get_tz_offset Ben Walton
2013-01-16 15:37   ` Junio C Hamano
2013-01-16 20:16     ` Ben Walton
2013-01-16 20:36       ` Junio C Hamano
2013-01-15 23:10 ` Ben Walton [this message]
2013-01-17 19:09   ` [PATCH 2/3] Allow Git::get_tz_offset to properly handle DST boundary times Junio C Hamano
2013-01-20 20:06     ` Ben Walton
2013-01-20 21:03       ` Junio C Hamano
2013-01-15 23:10 ` [PATCH 3/3] Avoid non-portable strftime format specifiers in git-cvsimport Ben Walton
2013-01-16  1:53   ` Chris Rorvick
2013-01-16 10:38     ` Ben Walton
2013-01-15 23:43 ` [PATCH 0/3] Fix a portability issue with git-cvsimport Junio C Hamano

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=1358291405-10173-3-git-send-email-bdwalton@gmail.com \
    --to=bdwalton@gmail.com \
    --cc=esr@thyrsus.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    /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).