Repository: gitpython-developers/GitPython (python)

Issue:
ValueError exception when asking for authored_datetime
I am receiving a `ValueError` exception when getting the author date of a commit in Rails project. You can replicate it with the following code:

```
> from git import Repo
> repo = Repo('rails')
> commit = repo.commit('4cf94979c9f4d6683c9338d694d5eb3106a4e734')
> commit.authored_datetime
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/dspadini/Documents/pydriller/.venv/lib/python3.6/site-packages/git/objects/commit.py", line 151, in authored_datetime
    return from_timestamp(self.authored_date, self.author_tz_offset)
  File "/Users/dspadini/Documents/pydriller/.venv/lib/python3.6/site-packages/git/objects/util.py", line 124, in from_timestamp
    > local_dt = utc_dt.astimezone(tzoffset(tz_offset))
ValueError: offset must be a timedelta strictly between -timedelta(hours=24) and timedelta(hours=24).
```

Tracing back the error, I got that the timestamp of the commit is 1312735823, while the tz_offset is -1864800. The problem is when creating the tzoffset: I indeed printed the timedelta 
```
local_dt = utc_dt.astimezone(tzoffset(tz_offset))

class tzoffset(tzinfo):
    def __init__(self, secs_west_of_utc, name=None):
        self._offset = timedelta(seconds=-secs_west_of_utc)
        print('Timedelta is {}'.format(timedelta(seconds=-secs_west_of_utc)))
```
and it is not in the range of [-24,24] hours, but it is actually 21 days. 

*EDIT*: looking at the information of the commit, the offset is completely wrong: 
`Date:   Mon Aug 29 06:50:23 2011 +51800`

So the problem is not of gitpython. 

Pull request description:
Avoid from_timestamp() function to raise an exception when the offset…
… is greater or lower than 24 hours.

Add tests that exercise the new behaviour

Fix #741 

Patch:
diff --git a/git/objects/util.py b/git/objects/util.py
index f630f966..7b6a2763 100644
--- a/git/objects/util.py
+++ b/git/objects/util.py
@@ -121,8 +121,11 @@ utc = tzoffset(0, 'UTC')
 def from_timestamp(timestamp, tz_offset):
     """Converts a timestamp + tz_offset into an aware datetime instance."""
     utc_dt = datetime.fromtimestamp(timestamp, utc)
-    local_dt = utc_dt.astimezone(tzoffset(tz_offset))
-    return local_dt
+    try:
+        local_dt = utc_dt.astimezone(tzoffset(tz_offset))
+        return local_dt
+    except ValueError:
+        return utc_dt
 
 
 def parse_date(string_date):


Test patch:
diff --git a/git/test/test_util.py b/git/test/test_util.py
index b7925c84..9c993205 100644
--- a/git/test/test_util.py
+++ b/git/test/test_util.py
@@ -7,7 +7,7 @@
 import tempfile
 import time
 from unittest import skipIf
-
+from datetime import datetime
 
 import ddt
 
@@ -18,7 +18,8 @@ from git.objects.util import (
     utctz_to_altz,
     verify_utctz,
     parse_date,
-)
+    tzoffset,
+    from_timestamp)
 from git.test.lib import (
     TestBase,
     assert_equal
@@ -260,3 +261,16 @@ class TestUtils(TestBase):
 
         self.failUnlessRaises(IndexError, ilist.__delitem__, 0)
         self.failUnlessRaises(IndexError, ilist.__delitem__, 'something')
+
+    def test_from_timestamp(self):
+        # Correct offset: UTC+2, should return datetime + tzoffset(+2)
+        altz = utctz_to_altz('+0200')
+        self.assertEqual(datetime.fromtimestamp(1522827734, tzoffset(altz)), from_timestamp(1522827734, altz))
+
+        # Wrong offset: UTC+58, should return datetime + tzoffset(UTC)
+        altz = utctz_to_altz('+5800')
+        self.assertEqual(datetime.fromtimestamp(1522827734, tzoffset(0)), from_timestamp(1522827734, altz))
+
+        # Wrong offset: UTC-9000, should return datetime + tzoffset(UTC)
+        altz = utctz_to_altz('-9000')
+        self.assertEqual(datetime.fromtimestamp(1522827734, tzoffset(0)), from_timestamp(1522827734, altz))