git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 2/3] Allow Git::get_tz_offset to properly handle DST boundary times

From
Ben Walton <bdwalton@gmail.com>
Date
Jan 15, 2013, 23:10 UTC
Message-ID
<1358291405-10173-3-git-send-email-bdwalton@gmail.com>
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
Previous: Junio C HamanoNext: Junio C Hamano
Message 6 of 13 in “Fix a portability issue with git-cvsimport”
  1. 0/3 Fix a portability issue with git-cvsimportBen Walton, Jan 15, 2013
  2. 1/3 Move Git::SVN::get_tz to Git::get_tz_offsetBen Walton, Jan 15, 2013
  3. Junio C HamanoJan 16, 2013
  4. Ben WaltonJan 16, 2013
  5. Junio C HamanoJan 16, 2013
  6. 2/3 Allow Git::get_tz_offset to properly handle DST boundary timesBen Walton, Jan 15, 2013
  7. Junio C HamanoJan 17, 2013
  8. Ben WaltonJan 20, 2013
  9. Junio C HamanoJan 20, 2013
  10. 3/3 Avoid non-portable strftime format specifiers in git-cvsimportBen Walton, Jan 15, 2013
  11. Chris RorvickJan 16, 2013
  12. Ben WaltonJan 16, 2013
  13. Junio C HamanoJan 15, 2013

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.