summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Cowgill <jcowgill@jcowgill.uk>2023-01-24 12:40:29 +0000
committerJames Cowgill <jcowgill@jcowgill.uk>2023-01-24 12:41:24 +0000
commit854a2d1f7fde596babe85ba9f76f282e9d53086d (patch)
tree05aaf9032c8be41b5b7f7885819ed8078e0064a4
parentcc92d5126b2fc80f7cc6866fc8f99b3ffb0189ae (diff)
downloadgitpython-854a2d1f7fde596babe85ba9f76f282e9d53086d.tar.gz
Fix timezone parsing functions for non-hour timezones
The `utctz_to_altz` and `altz_to_utctz_str` functions fail to handle timezones with UTC offsets that are not a multiple of one hour. Rewrite them and add some unit tests. Fixes #630
-rw-r--r--git/objects/util.py35
-rw-r--r--test/test_util.py21
2 files changed, 40 insertions, 16 deletions
diff --git a/git/objects/util.py b/git/objects/util.py
index f405d628..af279154 100644
--- a/git/objects/util.py
+++ b/git/objects/util.py
@@ -137,22 +137,25 @@ def get_object_type_by_name(
def utctz_to_altz(utctz: str) -> int:
- """we convert utctz to the timezone in seconds, it is the format time.altzone
- returns. Git stores it as UTC timezone which has the opposite sign as well,
- which explains the -1 * ( that was made explicit here )
-
- :param utctz: git utc timezone string, i.e. +0200"""
- return -1 * int(float(utctz) / 100 * 3600)
-
-
-def altz_to_utctz_str(altz: float) -> str:
- """As above, but inverses the operation, returning a string that can be used
- in commit objects"""
- utci = -1 * int((float(altz) / 3600) * 100)
- utcs = str(abs(utci))
- utcs = "0" * (4 - len(utcs)) + utcs
- prefix = (utci < 0 and "-") or "+"
- return prefix + utcs
+ """Convert a git timezone offset into a timezone offset west of
+ UTC in seconds (compatible with time.altzone).
+
+ :param utctz: git utc timezone string, i.e. +0200
+ """
+ int_utctz = int(utctz)
+ seconds = ((abs(int_utctz) // 100) * 3600 + (abs(int_utctz) % 100) * 60)
+ return seconds if int_utctz < 0 else -seconds
+
+
+def altz_to_utctz_str(altz: int) -> str:
+ """Convert a timezone offset west of UTC in seconds into a git timezone offset string
+
+ :param altz: timezone offset in seconds west of UTC
+ """
+ hours = abs(altz) // 3600
+ minutes = (abs(altz) % 3600) // 60
+ sign = "-" if altz >= 60 else "+"
+ return "{}{:02}{:02}".format(sign, hours, minutes)
def verify_utctz(offset: str) -> str:
diff --git a/test/test_util.py b/test/test_util.py
index 90dd89a9..c17efce3 100644
--- a/test/test_util.py
+++ b/test/test_util.py
@@ -333,6 +333,27 @@ class TestUtils(TestBase):
self.assertRaises(IndexError, ilist.__delitem__, 0)
self.assertRaises(IndexError, ilist.__delitem__, "something")
+ def test_utctz_to_altz(self):
+ self.assertEqual(utctz_to_altz("+0000"), 0)
+ self.assertEqual(utctz_to_altz("+1400"), -(14 * 3600))
+ self.assertEqual(utctz_to_altz("-1200"), 12 * 3600)
+ self.assertEqual(utctz_to_altz("+0001"), -60)
+ self.assertEqual(utctz_to_altz("+0530"), -(5 * 3600 + 1800))
+ self.assertEqual(utctz_to_altz("-0930"), 9 * 3600 + 1800)
+
+ def test_altz_to_utctz_str(self):
+ self.assertEqual(altz_to_utctz_str(0), "+0000")
+ self.assertEqual(altz_to_utctz_str(-(14 * 3600)), "+1400")
+ self.assertEqual(altz_to_utctz_str(12 * 3600), "-1200")
+ self.assertEqual(altz_to_utctz_str(-60), "+0001")
+ self.assertEqual(altz_to_utctz_str(-(5 * 3600 + 1800)), "+0530")
+ self.assertEqual(altz_to_utctz_str(9 * 3600 + 1800), "-0930")
+
+ self.assertEqual(altz_to_utctz_str(1), "+0000")
+ self.assertEqual(altz_to_utctz_str(59), "+0000")
+ self.assertEqual(altz_to_utctz_str(-1), "+0000")
+ self.assertEqual(altz_to_utctz_str(-59), "+0000")
+
def test_from_timestamp(self):
# Correct offset: UTC+2, should return datetime + tzoffset(+2)
altz = utctz_to_altz("+0200")