From 5fef6fbfb4d8c766dcfb4b6fb32af771de06d4a2 Mon Sep 17 00:00:00 2001 From: Tres Seaver Date: Tue, 10 May 2016 13:07:19 -0400 Subject: [PATCH 1/2] Spell out nanosecond precisiion w/ '%0.9d'. --- gcloud/test__helpers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcloud/test__helpers.py b/gcloud/test__helpers.py index fe4a8d2f4b19..6def426327e5 100644 --- a/gcloud/test__helpers.py +++ b/gcloud/test__helpers.py @@ -511,7 +511,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( From d1edca04e423fd9767a8c22ec503f388dcf195f0 Mon Sep 17 00:00:00 2001 From: Tres Seaver Date: Tue, 10 May 2016 13:19:37 -0400 Subject: [PATCH 2/2] Tolerate timestamps w/ truncated nanos. Closes #1783. --- gcloud/_helpers.py | 6 ++++-- gcloud/test__helpers.py | 28 +++++++++++++++++++++------- 2 files changed, 25 insertions(+), 9 deletions(-) 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 6def426327e5..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