diff --git a/gcloud/_helpers.py b/gcloud/_helpers.py index b60b17290180..23b66c944810 100644 --- a/gcloud/_helpers.py +++ b/gcloud/_helpers.py @@ -45,7 +45,7 @@ \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2} # YYYY-MM-DDTHH:MM:SS ) \. # decimal point - (?P\d{9}) # nanoseconds + (?P\d{1,9}) # nanoseconds, maybe truncated Z # Zulu """, re.VERBOSE) @@ -344,7 +344,9 @@ def _rfc3339_nanos_to_datetime(dt_str): dt_str, _RFC3339_NANOS.pattern)) bare_seconds = datetime.datetime.strptime( with_nanos.group('no_fraction'), _RFC3339_NO_FRACTION) - nanos = int(with_nanos.group('nanos')) + fraction = with_nanos.group('nanos') + scale = 9 - len(fraction) + nanos = int(fraction) * (10 ** scale) micros = nanos // 1000 return bare_seconds.replace(microsecond=micros, tzinfo=UTC) diff --git a/gcloud/test__helpers.py b/gcloud/test__helpers.py index fe4a8d2f4b19..6ccdb6be0b97 100644 --- a/gcloud/test__helpers.py +++ b/gcloud/test__helpers.py @@ -483,7 +483,9 @@ def test_w_bogus_zone(self): with self.assertRaises(ValueError): self._callFUT(dt_str) - def test_w_microseconds(self): + def test_w_truncated_nanos(self): + import datetime + from gcloud._helpers import UTC year = 2009 month = 12 @@ -491,12 +493,24 @@ def test_w_microseconds(self): hour = 12 minute = 44 seconds = 32 - micros = 123456 - - dt_str = '%d-%02d-%02dT%02d:%02d:%02d.%06dZ' % ( - year, month, day, hour, minute, seconds, micros) - with self.assertRaises(ValueError): - self._callFUT(dt_str) + truncateds_and_micros = [ + ('12345678', 123456), + ('1234567', 123456), + ('123456', 123456), + ('12345', 123450), + ('1234', 123400), + ('123', 123000), + ('12', 120000), + ('1', 100000), + ] + + for truncated, micros in truncateds_and_micros: + dt_str = '%d-%02d-%02dT%02d:%02d:%02d.%sZ' % ( + year, month, day, hour, minute, seconds, truncated) + result = self._callFUT(dt_str) + expected_result = datetime.datetime( + year, month, day, hour, minute, seconds, micros, UTC) + self.assertEqual(result, expected_result) def test_w_naonseconds(self): import datetime @@ -511,7 +525,7 @@ def test_w_naonseconds(self): nanos = 123456789 micros = nanos // 1000 - dt_str = '%d-%02d-%02dT%02d:%02d:%02d.%06dZ' % ( + dt_str = '%d-%02d-%02dT%02d:%02d:%02d.%09dZ' % ( year, month, day, hour, minute, seconds, nanos) result = self._callFUT(dt_str) expected_result = datetime.datetime(