From 3d8b6f47e0a869d1068dcf38ca682330c60d44b7 Mon Sep 17 00:00:00 2001 From: Jens Larsson Date: Thu, 8 Sep 2016 13:50:57 +0200 Subject: [PATCH] Support parsing DATE columns from Standard SQL tables Change-Id: I20a6fff4362e27ee35286a3538c24e37bc858faf --- google/cloud/_helpers.py | 13 +++++++++++++ google/cloud/bigquery/_helpers.py | 8 ++++++++ unit_tests/bigquery/test__helpers.py | 21 +++++++++++++++++++++ unit_tests/test__helpers.py | 12 ++++++++++++ 4 files changed, 54 insertions(+) diff --git a/google/cloud/_helpers.py b/google/cloud/_helpers.py index da3e689ddc5e..a190a544d987 100644 --- a/google/cloud/_helpers.py +++ b/google/cloud/_helpers.py @@ -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. diff --git a/google/cloud/bigquery/_helpers.py b/google/cloud/bigquery/_helpers.py index 222cf2579c17..a14a9053d8d4 100644 --- a/google/cloud/bigquery/_helpers.py +++ b/google/cloud/bigquery/_helpers.py @@ -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): @@ -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): @@ -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, } diff --git a/unit_tests/bigquery/test__helpers.py b/unit_tests/bigquery/test__helpers.py index 8e885c31cd59..86884f3dab2e 100644 --- a/unit_tests/bigquery/test__helpers.py +++ b/unit_tests/bigquery/test__helpers.py @@ -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): diff --git a/unit_tests/test__helpers.py b/unit_tests/test__helpers.py index db25efb23c9e..62a9ce2b63a1 100644 --- a/unit_tests/test__helpers.py +++ b/unit_tests/test__helpers.py @@ -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):