Skip to content

Commit

Permalink
Merge pull request #2265 from thejens/master
Browse files Browse the repository at this point in the history
Support parsing DATE columns from Standard SQL tables
  • Loading branch information
tseaver authored Sep 9, 2016
2 parents 83914b9 + 3d8b6f4 commit 298b28a
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 0 deletions.
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

0 comments on commit 298b28a

Please sign in to comment.