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(storage): fix incorrect mtime by UTC offset #42

Merged
15 changes: 15 additions & 0 deletions google/cloud/storage/_helpers.py
Expand Up @@ -19,6 +19,7 @@

import base64
from hashlib import md5
from datetime import datetime
import os

from google.cloud.storage.constants import _DEFAULT_TIMEOUT
Expand Down Expand Up @@ -297,3 +298,17 @@ def _base64_md5hash(buffer_object):
_write_buffer_to_hash(buffer_object, hash_obj)
digest_bytes = hash_obj.digest()
return base64.b64encode(digest_bytes)


def _convert_to_timestamp(value):
"""Convert non-none datetime to timestamp.

:type value: :class:`datetime.datetime`
:param value: The datetime to convert.

:rtype: int
:returns: The timestamp.
"""
utc_naive = value.replace(tzinfo=None) - value.utcoffset()
mtime = (utc_naive - datetime(1970, 1, 1)).total_seconds()
return mtime
8 changes: 6 additions & 2 deletions google/cloud/storage/blob.py
Expand Up @@ -31,8 +31,8 @@
from io import BytesIO
import mimetypes
import os
import time
import warnings
import six

from six.moves.urllib.parse import parse_qsl
from six.moves.urllib.parse import quote
Expand All @@ -57,6 +57,7 @@
from google.cloud.storage._helpers import _get_storage_host
from google.cloud.storage._helpers import _PropertyMixin
from google.cloud.storage._helpers import _scalar_property
from google.cloud.storage._helpers import _convert_to_timestamp
from google.cloud.storage._signing import generate_signed_url_v2
from google.cloud.storage._signing import generate_signed_url_v4
from google.cloud.storage.acl import ACL
Expand Down Expand Up @@ -846,7 +847,10 @@ def download_to_filename(

updated = self.updated
if updated is not None:
mtime = time.mktime(updated.timetuple())
if six.PY2:
mtime = _convert_to_timestamp(updated)
else:
mtime = updated.timestamp()
os.utime(file_obj.name, (mtime, mtime))

def download_as_string(self, client=None, start=None, end=None, raw_download=False):
Expand Down
7 changes: 5 additions & 2 deletions tests/unit/test_blob.py
Expand Up @@ -1060,7 +1060,7 @@ def test_download_to_file_w_chunks_w_raw(self):

def _download_to_filename_helper(self, updated, raw_download):
import os
import time
from google.cloud.storage._helpers import _convert_to_timestamp
from google.cloud._testing import _NamedTemporaryFile

blob_name = "blob-name"
Expand All @@ -1080,7 +1080,10 @@ def _download_to_filename_helper(self, updated, raw_download):
self.assertIsNone(blob.updated)
else:
mtime = os.path.getmtime(temp.name)
updated_time = time.mktime(blob.updated.timetuple())
if six.PY2:
updated_time = _convert_to_timestamp(blob.updated)
else:
updated_time = blob.updated.timestamp()
self.assertEqual(mtime, updated_time)

headers = {"accept-encoding": "gzip"}
Expand Down