Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: correctly decode times without microseconds #375

Merged
merged 5 commits into from Feb 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 6 additions & 6 deletions google/cloud/storage/blob.py
Expand Up @@ -55,7 +55,7 @@
from google.cloud import exceptions
from google.cloud._helpers import _bytes_to_unicode
from google.cloud._helpers import _datetime_to_rfc3339
from google.cloud._helpers import _rfc3339_to_datetime
from google.cloud._helpers import _rfc3339_nanos_to_datetime
from google.cloud._helpers import _to_bytes
from google.cloud.exceptions import NotFound
from google.cloud.storage._helpers import _add_generation_match_parameters
Expand Down Expand Up @@ -3645,7 +3645,7 @@ def retention_expiration_time(self):
"""
value = self._properties.get("retentionExpirationTime")
if value is not None:
return _rfc3339_to_datetime(value)
return _rfc3339_nanos_to_datetime(value)

@property
def self_link(self):
Expand Down Expand Up @@ -3731,7 +3731,7 @@ def time_deleted(self):
"""
value = self._properties.get("timeDeleted")
if value is not None:
return _rfc3339_to_datetime(value)
return _rfc3339_nanos_to_datetime(value)

@property
def time_created(self):
Expand All @@ -3746,7 +3746,7 @@ def time_created(self):
"""
value = self._properties.get("timeCreated")
if value is not None:
return _rfc3339_to_datetime(value)
return _rfc3339_nanos_to_datetime(value)

@property
def updated(self):
Expand All @@ -3761,7 +3761,7 @@ def updated(self):
"""
value = self._properties.get("updated")
if value is not None:
return _rfc3339_to_datetime(value)
return _rfc3339_nanos_to_datetime(value)

@property
def custom_time(self):
Expand All @@ -3776,7 +3776,7 @@ def custom_time(self):
"""
value = self._properties.get("customTime")
if value is not None:
return _rfc3339_to_datetime(value)
return _rfc3339_nanos_to_datetime(value)

@custom_time.setter
def custom_time(self, value):
Expand Down
8 changes: 4 additions & 4 deletions google/cloud/storage/bucket.py
Expand Up @@ -28,7 +28,7 @@
from google.api_core import datetime_helpers
from google.cloud._helpers import _datetime_to_rfc3339
from google.cloud._helpers import _NOW
from google.cloud._helpers import _rfc3339_to_datetime
from google.cloud._helpers import _rfc3339_nanos_to_datetime
from google.cloud.exceptions import NotFound
from google.api_core.iam import Policy
from google.cloud.storage import _signing
Expand Down Expand Up @@ -499,7 +499,7 @@ def uniform_bucket_level_access_locked_time(self):
ubla = self.get("uniformBucketLevelAccess", {})
stamp = ubla.get("lockedTime")
if stamp is not None:
stamp = _rfc3339_to_datetime(stamp)
stamp = _rfc3339_nanos_to_datetime(stamp)
return stamp

@property
Expand Down Expand Up @@ -2556,7 +2556,7 @@ def retention_policy_effective_time(self):
if policy is not None:
timestamp = policy.get("effectiveTime")
if timestamp is not None:
return _rfc3339_to_datetime(timestamp)
return _rfc3339_nanos_to_datetime(timestamp)

@property
def retention_policy_locked(self):
Expand Down Expand Up @@ -2675,7 +2675,7 @@ def time_created(self):
"""
value = self._properties.get("timeCreated")
if value is not None:
return _rfc3339_to_datetime(value)
return _rfc3339_nanos_to_datetime(value)

@property
def versioning_enabled(self):
Expand Down
6 changes: 3 additions & 3 deletions google/cloud/storage/hmac_key.py
Expand Up @@ -13,7 +13,7 @@
# limitations under the License.

from google.cloud.exceptions import NotFound
from google.cloud._helpers import _rfc3339_to_datetime
from google.cloud._helpers import _rfc3339_nanos_to_datetime

from google.cloud.storage.constants import _DEFAULT_TIMEOUT
from google.cloud.storage.retry import DEFAULT_RETRY
Expand Down Expand Up @@ -151,7 +151,7 @@ def time_created(self):
"""
value = self._properties.get("timeCreated")
if value is not None:
return _rfc3339_to_datetime(value)
return _rfc3339_nanos_to_datetime(value)

@property
def updated(self):
Expand All @@ -164,7 +164,7 @@ def updated(self):
"""
value = self._properties.get("updated")
if value is not None:
return _rfc3339_to_datetime(value)
return _rfc3339_nanos_to_datetime(value)

@property
def path(self):
Expand Down
15 changes: 15 additions & 0 deletions tests/system/test_system.py
Expand Up @@ -1063,6 +1063,21 @@ def test_upload_blob_custom_time(self):
custom_time = same_blob.custom_time.replace(tzinfo=None)
self.assertEqual(custom_time, current_time)

def test_blob_custom_time_no_micros(self):
# Test that timestamps without microseconds are treated correctly by
# custom_time encoding/decoding.
blob = self.bucket.blob("CustomTimeNoMicrosBlob")
file_contents = b"Hello World"
time_without_micros = datetime.datetime(2021, 2, 10, 12, 30)
blob.custom_time = time_without_micros
blob.upload_from_string(file_contents)
self.case_blobs_to_delete.append(blob)

same_blob = self.bucket.blob(("CustomTimeNoMicrosBlob"))
same_blob.reload(projection="full")
custom_time = same_blob.custom_time.replace(tzinfo=None)
self.assertEqual(custom_time, time_without_micros)

def test_blob_crc32_md5_hash(self):
blob = self.bucket.blob("MyBuffer")
file_contents = b"Hello World"
Expand Down