Skip to content

Commit fd6231b

Browse files
author
Val Brodsky
committed
Use python dateutil package to parse iso strings
1 parent bfabd85 commit fd6231b

File tree

3 files changed

+26
-9
lines changed

3 files changed

+26
-9
lines changed

labelbox/schema/data_row_metadata.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@
55
from itertools import chain
66
from typing import List, Optional, Dict, Union, Callable, Type, Any, Generator
77

8+
from dateutil.parser import isoparse
89
from pydantic import BaseModel, conlist, constr
910

1011
from labelbox.schema.ontology import SchemaId
11-
from labelbox.utils import _CamelCaseMixin, format_iso_datetime
12+
from labelbox.utils import _CamelCaseMixin, format_iso_datetime, format_iso_default_utc
1213

1314

1415
class DataRowMetadataKind(Enum):
@@ -466,7 +467,7 @@ def parse_metadata_fields(
466467
value=schema.uid)
467468
elif schema.kind == DataRowMetadataKind.datetime:
468469
field = DataRowMetadataField(schema_id=schema.uid,
469-
value=datetime.fromisoformat(
470+
value=format_iso_default_utc(
470471
f["value"]))
471472
else:
472473
field = DataRowMetadataField(schema_id=schema.uid,
@@ -838,7 +839,7 @@ def _validate_parse_number(
838839
def _validate_parse_datetime(
839840
field: DataRowMetadataField) -> List[Dict[str, Union[SchemaId, str]]]:
840841
if isinstance(field.value, str):
841-
field.value = datetime.fromisoformat(field.value)
842+
field.value = format_iso_default_utc(field.value)
842843
elif not isinstance(field.value, datetime):
843844
raise TypeError(
844845
f"Value for datetime fields must be either a string or datetime object. Found {type(field.value)}"

labelbox/utils.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,18 @@
11
import datetime
22
import re
3+
4+
import datetime
5+
from dateutil.tz import tzoffset
6+
from dateutil.parser import isoparse as dateutil_parse
7+
from dateutil.utils import default_tzinfo
8+
39
from urllib.parse import urlparse
410
from pydantic import BaseModel
511

612
UPPERCASE_COMPONENTS = ['uri', 'rgb']
713
ISO_DATETIME_FORMAT = '%Y-%m-%dT%H:%M:%SZ'
14+
DFLT_TZ = tzoffset("UTC", 0000)
15+
816

917

1018
def _convert(s, sep, title):
@@ -80,4 +88,13 @@ def format_iso_datetime(dt: datetime.datetime) -> str:
8088
Formats a datetime object into the format: 2011-11-04T00:05:23Z
8189
Note that datetime.isoformat() outputs 2011-11-04T00:05:23+00:00
8290
"""
83-
return dt.strftime(ISO_DATETIME_FORMAT)
91+
return dt.strftime(ISO_DATETIME_FORMAT)
92+
93+
94+
def format_iso_default_utc(date_string: str) -> datetime.datetime:
95+
"""
96+
Converts a string even if offset is missing: 2011-11-04T00:05:23Z or 2011-11-04T00:05:23+00:00 or 2011-11-04T00:05:23
97+
to a datetime object.
98+
For missing offsets, the default offset is UTC.
99+
"""
100+
return default_tzinfo(dateutil_parse(date_string), DFLT_TZ)

tests/integration/test_data_row_metadata.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,7 @@ def test_delete_schema(mdo):
445445

446446

447447
@pytest.mark.parametrize('datetime_str',
448-
['2011-11-04T00:05:23Z', '2011-05-07T14:34:14+00:00'])
448+
['2011-11-04T00:05:23Z', '2011-11-04T00:05:23+00:00'])
449449
def test_upsert_datarow_date_metadata(data_row, mdo, datetime_str):
450450
metadata = [
451451
DataRowMetadata(data_row_id=data_row.uid,
@@ -458,11 +458,11 @@ def test_upsert_datarow_date_metadata(data_row, mdo, datetime_str):
458458
assert len(errors) == 0
459459

460460
metadata = mdo.bulk_export([data_row.uid])
461-
assert metadata[0].fields[0].value == datetime.fromisoformat(datetime_str)
461+
assert f"{metadata[0].fields[0].value}" == "2011-11-04 00:05:23+00:00"
462462

463463

464464
@pytest.mark.parametrize('datetime_str',
465-
['2011-11-04T00:05:23Z', '2011-05-07T14:34:14+00:00'])
465+
['2011-11-04T00:05:23Z', '2011-11-04T00:05:23+00:00'])
466466
def test_create_data_row_with_metadata(dataset, image_url, datetime_str):
467467
client = dataset.client
468468
assert len(list(dataset.data_rows())) == 0
@@ -475,5 +475,4 @@ def test_create_data_row_with_metadata(dataset, image_url, datetime_str):
475475
metadata_fields=metadata_fields)
476476

477477
retrieved_data_row = client.get_data_row(data_row.uid)
478-
assert retrieved_data_row.metadata[0].value == datetime.fromisoformat(
479-
datetime_str)
478+
assert f"{retrieved_data_row.metadata[0].value}" == "2011-11-04 00:05:23+00:00"

0 commit comments

Comments
 (0)