Skip to content

Commit f8e51c8

Browse files
author
Mike
committed
Explicitly set timespec for isoformat everywhere
1 parent 297d624 commit f8e51c8

5 files changed

Lines changed: 61 additions & 25 deletions

File tree

src/hdx/data/dataset.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -613,7 +613,7 @@ def _save_dataset_add_filestore_resources(
613613
# No need to output timezone info here so no need to use now_utc()
614614
self.data[
615615
"updated_by_script"
616-
] = f"{scriptinfo} ({datetime.utcnow().isoformat()})"
616+
] = f"{scriptinfo} ({datetime.utcnow().isoformat(timespec='microseconds')})"
617617
batch = kwargs.get("batch")
618618
if batch:
619619
if not is_valid_uuid(batch):

src/hdx/data/date_helper.py

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,17 @@
1010
class DateHelper:
1111
@staticmethod
1212
def get_hdx_date(
13-
date: Union[datetime, str], ignore_timeinfo: bool, max=False
13+
date: Union[datetime, str],
14+
ignore_timeinfo: bool,
15+
include_microseconds=False,
16+
max=False,
1417
):
1518
"""Get an HDX date as a string from a datetime.datetime object.
1619
1720
Args:
1821
date (Union[datetime, str]): Date as datetime or string
1922
ignore_timeinfo (bool): Ignore time and time zone of date. Defaults to True.
23+
include_microseconds (bool): Include microsconds. Defaults to False.
2024
2125
Returns:
2226
str: HDX date as a string
@@ -27,26 +31,34 @@ def get_hdx_date(
2731
timezone_handling = 3
2832

2933
if isinstance(date, str):
30-
date = parse_date(date, timezone_handling=timezone_handling)
34+
date = parse_date(
35+
date,
36+
timezone_handling=timezone_handling,
37+
include_microseconds=include_microseconds,
38+
)
3139

3240
if ignore_timeinfo:
3341
if max:
3442
date = date.replace(
3543
hour=23,
3644
minute=59,
3745
second=59,
38-
microsecond=0,
39-
tzinfo=None,
46+
microsecond=999999,
4047
)
4148
else:
4249
date = date.replace(
43-
hour=0, minute=0, second=0, microsecond=0, tzinfo=None
50+
hour=0,
51+
minute=0,
52+
second=0,
53+
microsecond=0,
4454
)
4555
else:
46-
date = date.astimezone(timezone.utc).replace(
47-
microsecond=0, tzinfo=None
48-
)
49-
return date.isoformat()
56+
date = date.astimezone(timezone.utc)
57+
if include_microseconds:
58+
timespec = "microseconds"
59+
else:
60+
timespec = "seconds"
61+
return date.replace(tzinfo=None).isoformat(timespec=timespec)
5062

5163
@staticmethod
5264
def get_reference_period_info(
@@ -93,8 +105,8 @@ def get_reference_period_info(
93105
result["startdate"] = startdate
94106
result["enddate"] = enddate
95107
if date_format is None:
96-
startdate_str = startdate.isoformat()
97-
enddate_str = enddate.isoformat()
108+
startdate_str = startdate.isoformat(timespec="seconds")
109+
enddate_str = enddate.isoformat(timespec="seconds")
98110
else:
99111
startdate_str = startdate.strftime(date_format)
100112
enddate_str = enddate.strftime(date_format)
@@ -123,14 +135,23 @@ def get_hdx_reference_period(
123135
Returns:
124136
str: HDX reference period
125137
"""
126-
startdate = cls.get_hdx_date(startdate, ignore_timeinfo)
138+
startdate = cls.get_hdx_date(
139+
startdate,
140+
ignore_timeinfo=ignore_timeinfo,
141+
include_microseconds=False,
142+
)
127143
if ongoing:
128144
enddate = "*"
129145
else:
130146
if not enddate:
131147
enddate = startdate
132148
else:
133-
enddate = cls.get_hdx_date(enddate, ignore_timeinfo, max=True)
149+
enddate = cls.get_hdx_date(
150+
enddate,
151+
ignore_timeinfo=ignore_timeinfo,
152+
include_microseconds=False,
153+
max=True,
154+
)
134155
return f"[{startdate} TO {enddate}]"
135156

136157
@classmethod

src/hdx/data/filestore_helper.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,5 +100,7 @@ def dataset_merge_filestore_resource(
100100
if resource.get_file_to_upload():
101101
resource["url"] = cls.temporary_url
102102
if data_updated:
103-
resource["last_modified"] = datetime.utcnow().isoformat()
103+
resource["last_modified"] = datetime.utcnow().isoformat(
104+
timespec="microseconds"
105+
)
104106
resource.data_updated = False

src/hdx/data/resource.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,9 @@ def _resource_merge_hdx_update(
370370
"""
371371
data_updated = kwargs.pop("data_updated", self.data_updated)
372372
if data_updated and not self.file_to_upload:
373-
self.old_data["last_modified"] = datetime.utcnow().isoformat()
373+
self.old_data["last_modified"] = datetime.utcnow().isoformat(
374+
timespec="microseconds"
375+
)
374376
self.data_updated = False
375377
# old_data will be merged into data in the next step
376378
self._merge_hdx_update(
@@ -769,20 +771,22 @@ def get_date_data_updated(self) -> datetime:
769771
Returns:
770772
datetime: Date resource data was updated
771773
"""
772-
return parse_date(self.data["last_modified"])
774+
return parse_date(
775+
self.data["last_modified"], include_microseconds=True
776+
)
773777

774778
def set_date_data_updated(
775-
self, date: Union[datetime, str], ignore_timeinfo: bool = True
779+
self, date: Union[datetime, str], ignore_timeinfo: bool = False
776780
) -> None:
777781
"""Set date resource data was updated
778782
779783
Args:
780784
date (Union[datetime, str]): Date resource data was updated
781-
ignore_timeinfo (bool): Ignore time and time zone of date. Defaults to True.
785+
ignore_timeinfo (bool): Ignore time and time zone of date. Defaults to False.
782786
783787
Returns:
784788
None
785789
"""
786790
self.data["last_modified"] = DateHelper.get_hdx_date(
787-
date, ignore_timeinfo
791+
date, ignore_timeinfo=ignore_timeinfo, include_microseconds=True
788792
)

tests/hdx/data/test_resource.py

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1019,8 +1019,17 @@ def test_date_data_updated(self, configuration, read):
10191019
assert resource["id"] == "de6549d8-268b-4dfe-adaf-a4ae5c8510d5"
10201020
assert resource["name"] == "MyResource1"
10211021
assert resource["package_id"] == "6f36a41c-f126-4b18-aaaf-6c2ddfbc5d4d"
1022-
resource.set_date_data_updated("2020-03-02")
1023-
expected = "2020-03-02T00:00:00+00:00"
1024-
assert resource.get_date_data_updated().isoformat() == expected
1025-
resource.set_date_data_updated(parse_date("2020-03-02"))
1026-
assert resource.get_date_data_updated().isoformat() == expected
1022+
date = "2020-03-02 10:34:43.123456"
1023+
resource.set_date_data_updated(date)
1024+
expected = "2020-03-02T10:34:43.123456+00:00"
1025+
assert (
1026+
resource.get_date_data_updated().isoformat(timespec="microseconds")
1027+
== expected
1028+
)
1029+
resource.set_date_data_updated(
1030+
parse_date(date, include_microseconds=True)
1031+
)
1032+
assert (
1033+
resource.get_date_data_updated().isoformat(timespec="microseconds")
1034+
== expected
1035+
)

0 commit comments

Comments
 (0)