8000 feat: adds datetime_format as an option (#2236) · googleapis/python-bigquery@54d3dc6 · GitHub
[go: up one dir, main page]

Skip to content
  • Insights
  • Commit 54d3dc6

    Browse files
    authored
    feat: adds datetime_format as an option (#2236)
    * feat: adds datetime_format as an option * updates docstrings
    1 parent 371ad29 commit 54d3dc6

    File tree

    5 files changed

    +65
    -0
    lines changed

    5 files changed

    +65
    -0
    lines changed

    google/cloud/bigquery/external_config.py

    Lines changed: 15 additions & 0 deletions
    Original file line numberDiff line numberDiff line change
    @@ -862,6 +862,21 @@ def date_format(self) -> Optional[str]:
    862862
    def date_format(self, value: Optional[str]):
    863863
    self._properties["dateFormat"] = value
    864864

    865+
    @property
    866+
    def datetime_format(self) -> Optional[str]:
    867+
    """Optional[str]: Format used to parse DATETIME values. Supports C-style
    868+
    and SQL-style values.
    869+
    870+
    See:
    871+
    https://cloud.google.com/bigquery/docs/reference/rest/v2/tables#ExternalDataConfiguration.FIELDS.datetime_format
    872+
    """
    873+
    result = self._properties.get("datetimeFormat")
    874+
    return typing.cast(str, result)
    875+
    876+
    @datetime_format.setter
    877+
    def datetime_format(self, value: Optional[str]):
    878+
    self._properties["datetimeFormat"] = value
    879+
    865880
    @property
    866881
    def time_zone(self) -> Optional[str]:
    867882
    """Optional[str]: Time zone used when parsing timestamp values that do not

    google/cloud/bigquery/job/load.py

    Lines changed: 20 additions & 0 deletions
    Original file line numberDiff line numberDiff line change
    @@ -561,6 +561,19 @@ def date_format(self) -> Optional[str]:
    561561
    def date_format(self, value: Optional[str]):
    562562
    self._set_sub_prop("dateFormat", value)
    563563

    564+
    @property
    565+
    def datetime_format(self) -> Optional[str]:
    566+
    """Optional[str]: Date format used for parsing DATETIME values.
    567+
    568+
    See:
    569+
    https://cloud.google.com/bigquery/docs/reference/rest/v2/Job#JobConfigurationLoad.FIELDS.datetime_format
    570+
    """
    571+
    return self._get_sub_prop("datetimeFormat")
    572+
    573+
    @datetime_format.setter
    574+
    def datetime_format(self, value: Optional[str]):
    575+
    self._set_sub_prop("datetimeFormat", value)
    576+
    564577
    @property
    565578
    def time_zone(self) -> Optional[str]:
    566579
    """Optional[str]: Default time zone that will apply when parsing timestamp
    @@ -949,6 +962,13 @@ def date_format(self):
    949962
    """
    950963
    return self.configuration.date_format
    951964

    965+
    @property
    966+
    def datetime_format(self):
    967+
    """See
    968+
    :attr:`google.cloud.bigquery.job.LoadJobConfig.datetime_format`.
    969+
    """
    970+
    return self.configuration.datetime_format
    971+
    952972
    @property
    953973
    def time_zone(self):
    954974
    """See

    tests/unit/job/test_load.py

    Lines changed: 9 additions & 0 deletions
    Original file line numberDiff line numberDiff line change
    @@ -38,6 +38,7 @@ def _setUpConstants(self):
    3838
    self.OUTPUT_ROWS = 345
    3939
    self.REFERENCE_FILE_SCHEMA_URI = "gs://path/to/reference"
    4040
    self.DATE_FORMAT = "%Y-%m-%d"
    41+
    self.DATETIME_FORMAT = "%Y-%m-%dT%H:%M:%S"
    4142
    self.TIME_ZONE = "UTC"
    4243
    self.TIME_FORMAT = "%H:%M:%S"
    4344
    self.TIMESTAMP_FORMAT = "YYYY-MM-DD HH:MM:SS.SSSSSSZ"
    @@ -47,6 +48,7 @@ def _make_resource(self, started=False, ended=False):
    4748
    config = resource["configuration"]["load"]
    4849
    config["sourceUris"] = [self.SOURCE1]
    4950
    config["dateFormat"] = self.DATE_FORMAT
    51+
    config["datetimeFormat"] = self.DATETIME_FORMAT
    5052
    config["timeZone"] = self.TIME_ZONE
    5153
    config["timeFormat"] = self.TIME_FORMAT
    5254
    config["timestampFormat"] = self.TIMESTAMP_FORMAT
    @@ -164,6 +166,10 @@ def _verifyResourceProperties(self, job, resource):
    164166
    self.assertEqual(job.date_format, config["dateFormat"])
    165167
    else:
    166168
    self.assertIsNone(job.date_format)
    169+
    if "datetimeFormat" in config:
    170+
    self.assertEqual(job.datetime_format, config["datetimeFormat"])
    171+
    else:
    172+
    self.assertIsNone(job.datetime_format)
    167173
    if "timeZone" in config:
    168174
    self.assertEqual(job.time_zone, config["timeZone"])
    169175
    else:
    @@ -219,6 +225,7 @@ def test_ctor(self):
    219225
    self.assertIsNone(job.schema_update_options)
    220226
    self.assertIsNone(job.reference_file_schema_uri)
    221227
    self.assertIsNone(job.date_format)
    228+
    self.assertIsNone(job.datetime_format)
    222229
    self.assertIsNone(job.time_zone)
    223230
    self.assertIsNone(job.time_format)
    224231
    self.assertIsNone(job.timestamp_format)
    @@ -618,6 +625,7 @@ def test_begin_w_alternate_client(self):
    618625
    },
    619626
    "schemaUpdateOptions": [SchemaUpdateOption.ALLOW_FIELD_ADDITION],
    620627
    "dateFormat": self.DATE_FORMAT,
    628+
    "datetimeFormat": self.DATETIME_FORMAT,
    621629
    "timeZone": self.TIME_ZONE,
    622630
    "timeFormat": self.TIME_FORMAT,
    623631
    "timestampFormat": self.TIMESTAMP_FORMAT,
    @@ -651,6 +659,7 @@ def test_begin_w_alternate_client(self):
    651659
    config.schema_update_options = [SchemaUpdateOption.ALLOW_FIELD_ADDITION]
    652660
    config.reference_file_schema_uri = "gs://path/to/reference"
    653661
    config.date_format = self.DATE_FORMAT
    662+
    config.datetime_format = self.DATETIME_FORMAT
    654663
    config.time_zone = self.TIME_ZONE
    655664
    config.time_format = self.TIME_FORMAT
    656665
    config.timestamp_format = self.TIMESTAMP_FORMAT

    tests/unit/job/test_load_config.py

    Lines changed: 16 additions & 0 deletions
    Original file line numberDiff line numberDiff line change
    @@ -844,6 +844,22 @@ def test_date_format_setter(self):
    844844
    config.date_format = date_format
    845845
    self.assertEqual(config._properties["load"]["dateFormat"], date_format)
    846846

    847+
    def test_datetime_format_missing(self):
    848+
    config = self._get_target_class()()
    849+
    self.assertIsNone(config.datetime_format)
    850+
    851+
    def test_datetime_format_hit(self):
    852+
    datetime_format = "%Y-%m-%dT%H:%M:%S"
    853+
    config = self._get_target_class()()
    854+
    config._properties["load"]["datetimeFormat"] = datetime_format
    855+
    self.assertEqual(config.datetime_format, datetime_format)
    856+
    857+
    def test_datetime_format_setter(self):
    858+
    datetime_format = "YYYY/MM/DD HH24:MI:SS"
    859+
    config = self._get_target_class()()
    860+
    config.datetime_format = datetime_format
    861+
    self.assertEqual(config._properties["load"]["datetimeFormat"], datetime_format)
    862+
    847863
    def test_time_zone_missing(self):
    848864
    config = self._get_target_class()()
    849865
    self.assertIsNone(config.time_zone)

    tests/unit/test_external_config.py

    Lines changed: 5 additions & 0 deletions
    Original file line numberDiff line numberDiff line change
    @@ -26,6 +26,7 @@
    2626
    class TestExternalConfig(unittest.TestCase):
    2727
    SOURCE_URIS = ["gs://foo", "gs://bar"]
    2828
    DATE_FORMAT = "MM/DD/YYYY"
    29+
    DATETIME_FORMAT = "MM/DD/YYYY HH24:MI:SS"
    2930
    TIME_ZONE = "America/Los_Angeles"
    3031
    TIME_FORMAT = "HH24:MI:SS"
    3132
    TIMESTAMP_FORMAT = "MM/DD/YYYY HH24:MI:SS.FF6 TZR"
    @@ -38,6 +39,7 @@ class TestExternalConfig(unittest.TestCase):
    3839
    "ignoreUnknownValues": False,
    3940
    "compression": "compression",
    4041
    "dateFormat": DATE_FORMAT,
    42+
    "datetimeFormat": DATETIME_FORMAT,
    4143
    "timeZone": TIME_ZONE,
    4244
    "timeFormat": TIME_FORMAT,
    4345
    "timestampFormat": TIMESTAMP_FORMAT,
    @@ -88,6 +90,7 @@ def test_to_api_repr_base(self):
    8890
    ec.schema = [schema.SchemaField("full_name", "STRING", mode="REQUIRED")]
    8991

    9092
    ec.date_format = self.DATE_FORMAT
    93+
    ec.datetime_format = self.DATETIME_FORMAT
    9194
    ec.time_zone = self.TIME_ZONE
    9295
    ec.time_format = self.TIME_FORMAT
    9396
    ec.timestamp_format = self.TIMESTAMP_FORMAT
    @@ -106,6 +109,7 @@ def test_to_api_repr_base(self):
    106109
    "connectionId": "path/to/connection",
    107110
    "schema": exp_schema,
    108111
    "dateFormat": self.DATE_FORMAT,
    112+
    "datetimeFormat": self.DATETIME_FORMAT,
    109113
    "timeZone": self.TIME_ZONE,
    110114
    "timeFormat": self.TIME_FORMAT,
    111115
    "timestampFormat": self.TIMESTAMP_FORMAT,
    @@ -145,6 +149,7 @@ def _verify_base(self, ec):
    145149
    self.assertEqual(ec.max_bad_records, 17)
    146150
    self.assertEqual(ec.source_uris, self.SOURCE_URIS)
    147151
    self.assertEqual(ec.date_format, self.DATE_FORMAT)
    152+
    self.assertEqual(ec.datetime_format, self.DATETIME_FORMAT)
    148153
    self.assertEqual(ec.time_zone, self.TIME_ZONE)
    149154
    self.assertEqual(ec.time_format, self.TIME_FORMAT)
    150155
    self.assertEqual(ec.timestamp_format, self.TIMESTAMP_FORMAT)

    0 commit comments

    Comments
     (0)
    0