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

Support parsing DATE columns from Standard SQL tables #2265

Merged
merged 1 commit into from
Sep 9, 2016
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions google/cloud/_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,19 @@ def _millis_from_datetime(value):
return _millis(value)


def _date_from_iso8601_date(value):
"""Convert a ISO8601 date string to native datetime date

:type value: str
:param value: The date string to convert

:rtype: :class:`datetime.date`
:returns: A datetime date object created from the string

"""
return datetime.datetime.strptime(value, '%Y-%m-%d').date()


def _rfc3339_to_datetime(dt_str):
"""Convert a microsecond-precision timetamp to a native datetime.

Expand Down
8 changes: 8 additions & 0 deletions google/cloud/bigquery/_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"""Shared helper functions for BigQuery API classes."""

from google.cloud._helpers import _datetime_from_microseconds
from google.cloud._helpers import _date_from_iso8601_date


def _not_null(value, field):
Expand Down Expand Up @@ -47,6 +48,12 @@ def _datetime_from_json(value, field):
return _datetime_from_microseconds(1e6 * float(value))


def _date_from_json(value, field):
"""Coerce 'value' to a datetime date, if set or not nullable"""
if _not_null(value, field):
return _date_from_iso8601_date(value)


def _record_from_json(value, field):
"""Coerce 'value' to a mapping, if set or not nullable."""
if _not_null(value, field):
Expand All @@ -71,6 +78,7 @@ def _string_from_json(value, _):
'FLOAT': _float_from_json,
'BOOLEAN': _bool_from_json,
'TIMESTAMP': _datetime_from_json,
'DATE': _date_from_json,
'RECORD': _record_from_json,
'STRING': _string_from_json,
}
Expand Down
21 changes: 21 additions & 0 deletions unit_tests/bigquery/test__helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,27 @@ def test_w_float_value(self):
_EPOCH + datetime.timedelta(seconds=1, microseconds=234567))


class Test_date_from_json(unittest.TestCase):

def _callFUT(self, value, field):
from google.cloud.bigquery._helpers import _date_from_json
return _date_from_json(value, field)

def test_w_none_nullable(self):
self.assertIsNone(self._callFUT(None, _Field('NULLABLE')))

def test_w_none_required(self):
with self.assertRaises(TypeError):
self._callFUT(None, _Field('REQUIRED'))

def test_w_string_value(self):
import datetime
coerced = self._callFUT('1987-09-22', object())
self.assertEqual(
coerced,
datetime.date(1987, 9, 22))


class Test_record_from_json(unittest.TestCase):

def _callFUT(self, value, field):
Expand Down
12 changes: 12 additions & 0 deletions unit_tests/test__helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,18 @@ def test_it(self):
self.assertEqual(self._callFUT(NOW_MICROS), NOW)


class Test___date_from_iso8601_date(unittest.TestCase):

def _callFUT(self, value):
from google.cloud._helpers import _date_from_iso8601_date
return _date_from_iso8601_date(value)

def test_todays_date(self):
import datetime
TODAY = datetime.date.today()
self.assertEqual(self._callFUT(TODAY.strftime("%Y-%m-%d")), TODAY)


class Test__rfc3339_to_datetime(unittest.TestCase):

def _callFUT(self, dt_str):
Expand Down