Skip to content

Commit 1e0074b

Browse files
Yuri ZmytrakovYuri Zmytrakov
authored andcommitted
fix: round milliseconds instead of truncating
1 parent 0517b4b commit 1e0074b

File tree

2 files changed

+55
-1
lines changed

2 files changed

+55
-1
lines changed

stac_fastapi/core/stac_fastapi/core/datetime_utils.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ def normalize(dt):
2323
return ".."
2424
dt_obj = rfc3339_str_to_datetime(dt)
2525
dt_utc = dt_obj.astimezone(timezone.utc)
26-
return dt_utc.isoformat(timespec="milliseconds").replace("+00:00", "Z")
26+
rounded_dt = dt_utc.replace(microsecond=round(dt_utc.microsecond / 1000) * 1000)
27+
return rounded_dt.isoformat(timespec="milliseconds").replace("+00:00", "Z")
2728

2829
if not isinstance(date_str, str):
2930
return "../.."

stac_fastapi/tests/api/test_api.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1625,3 +1625,56 @@ async def test_use_datetime_false(app_client, load_test_data, txn_client, monkey
16251625

16261626
assert "test-item-datetime-only" not in found_ids
16271627
assert "test-item-start-end-only" in found_ids
1628+
1629+
1630+
@pytest.mark.asyncio
1631+
async def test_format_datetime_range_microsecond_rounding(
1632+
app_client, txn_client, load_test_data
1633+
):
1634+
"""Test that microseconds are rounded to milliseconds"""
1635+
1636+
test_collection = load_test_data("test_collection.json")
1637+
test_collection_id = "test-collection-microseconds"
1638+
test_collection["id"] = test_collection_id
1639+
await create_collection(txn_client, test_collection)
1640+
1641+
item = load_test_data("test_item.json")
1642+
item["id"] = "test-item-1"
1643+
item["collection"] = test_collection_id
1644+
item["properties"]["datetime"] = "2020-01-01T12:00:00.123Z"
1645+
await create_item(txn_client, item)
1646+
1647+
test_cases = [
1648+
("2020-01-01T12:00:00.123678Z", False),
1649+
("2020-01-01T12:00:00.123499Z", True),
1650+
("2020-01-01T12:00:00.123500Z", False),
1651+
]
1652+
1653+
for datetime_input, should_match in test_cases:
1654+
# Test GET /collections/{id}/items
1655+
resp = await app_client.get(
1656+
f"/collections/{test_collection_id}/items",
1657+
params={"datetime": datetime_input},
1658+
)
1659+
assert resp.status_code == 200
1660+
resp_json = resp.json()
1661+
1662+
if should_match:
1663+
assert len(resp_json["features"]) == 1
1664+
assert resp_json["features"][0]["id"] == "test-item-1"
1665+
else:
1666+
assert len(resp_json["features"]) == 0
1667+
1668+
# Test GET /search
1669+
resp = await app_client.get(
1670+
"/search",
1671+
params={"collections": test_collection_id, "datetime": datetime_input},
1672+
)
1673+
assert resp.status_code == 200
1674+
resp_json = resp.json()
1675+
1676+
if should_match:
1677+
assert len(resp_json["features"]) == 1
1678+
assert resp_json["features"][0]["id"] == "test-item-1"
1679+
else:
1680+
assert len(resp_json["features"]) == 0

0 commit comments

Comments
 (0)