From a5ce3f53079e29772feaba3814f65c298cc528a0 Mon Sep 17 00:00:00 2001 From: Yuri Zmytrakov Date: Mon, 6 Oct 2025 11:04:56 +0200 Subject: [PATCH 1/2] fix: Ensure 6-digit datetime precision Updated datetime to `strict_date_optional_time_nanos` for microsecond precision and replaced infinite/overflow values with 2262-04-11T23:47:16.854775Z to prevent format errors after reindexing. --- .../core/stac_fastapi/core/datetime_utils.py | 17 +++++++++++++---- .../stac_fastapi/sfeos_helpers/mappings.py | 5 ++++- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/stac_fastapi/core/stac_fastapi/core/datetime_utils.py b/stac_fastapi/core/stac_fastapi/core/datetime_utils.py index d5f992de8..7eb8313ab 100644 --- a/stac_fastapi/core/stac_fastapi/core/datetime_utils.py +++ b/stac_fastapi/core/stac_fastapi/core/datetime_utils.py @@ -13,17 +13,26 @@ def format_datetime_range(date_str: str) -> str: date_str (str): A string containing two datetime values separated by a '/'. Returns: - str: A string formatted as 'YYYY-MM-DDTHH:MM:SSZ/YYYY-MM-DDTHH:MM:SSZ', with '..' used if any element is None. + str: A string formatted as 'YYYY-MM-DDTHH:MM:SS.ssssssZ/YYYY-MM-DDTHH:MM:SS.ssssssZ'. + Each datetime is converted to UTC and preserves microsecond precision. + If a value is infinite '..', it is replaced with the maximum supported + UTC datetime ('2262-04-11T23:47:16.854775Z'). """ def normalize(dt): - """Normalize datetime string and preserve millisecond precision.""" + """Normalize datetime string and preserve microsecond precision.""" dt = dt.strip() + + max_es_date = datetime(2262, 4, 11, 23, 47, 16, 854775, tzinfo=timezone.utc) if not dt or dt == "..": - return ".." + return max_es_date.isoformat(timespec="microseconds").replace("+00:00", "Z") + dt_obj = rfc3339_str_to_datetime(dt) + if dt_obj > max_es_date: + dt_obj = max_es_date + dt_utc = dt_obj.astimezone(timezone.utc) - return dt_utc.isoformat(timespec="milliseconds").replace("+00:00", "Z") + return dt_utc.isoformat(timespec="microseconds").replace("+00:00", "Z") if not isinstance(date_str, str): return "../.." diff --git a/stac_fastapi/sfeos_helpers/stac_fastapi/sfeos_helpers/mappings.py b/stac_fastapi/sfeos_helpers/stac_fastapi/sfeos_helpers/mappings.py index b2d7264d6..c6df92634 100644 --- a/stac_fastapi/sfeos_helpers/stac_fastapi/sfeos_helpers/mappings.py +++ b/stac_fastapi/sfeos_helpers/stac_fastapi/sfeos_helpers/mappings.py @@ -142,7 +142,10 @@ class Geometry(Protocol): # noqa "type": "object", "properties": { # Common https://github.com/radiantearth/stac-spec/blob/master/item-spec/common-metadata.md - "datetime": {"type": "date"}, + "datetime": { + "type": "date", + "format": "strict_date_optional_time_nanos", + }, "start_datetime": {"type": "date"}, "end_datetime": {"type": "date"}, "created": {"type": "date"}, From da110dc3e326522283af5fd272d7963ae76aa507 Mon Sep 17 00:00:00 2001 From: Yuri Zmytrakov Date: Tue, 7 Oct 2025 09:26:54 +0200 Subject: [PATCH 2/2] docs: add note about nanos datetime format and handling of infinite values --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f0f028bc9..3224b3047 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Changed +- Changed datetime format to `strict_date_optional_time_nanos` for microsecond precision and updated normalization to replace infinite ("..") or overflow datetimes with the maximum supported Elasticsearch date 2262-04-11T23:47:16.854775Z. + ### Fixed [v6.5.1] - 2025-09-30