| 
37 | 37 | from stac_fastapi.types.core import AsyncBaseCoreClient, AsyncBaseTransactionsClient  | 
38 | 38 | from stac_fastapi.types.extension import ApiExtension  | 
39 | 39 | from stac_fastapi.types.requests import get_base_url  | 
40 |  | -from stac_fastapi.types.rfc3339 import DateTimeType  | 
 | 40 | +from stac_fastapi.types.rfc3339 import DateTimeType, rfc3339_str_to_datetime  | 
41 | 41 | from stac_fastapi.types.search import BaseSearchPostRequest  | 
42 | 42 | 
 
  | 
43 | 43 | logger = logging.getLogger(__name__)  | 
@@ -428,18 +428,31 @@ def _return_date(  | 
428 | 428 | 
 
  | 
429 | 429 |     def _format_datetime_range(self, date_str: str) -> str:  | 
430 | 430 |         """  | 
431 |  | -        Convert a datetime range into a formatted string.  | 
 | 431 | +        Convert a datetime range string into a normalized UTC string for API requests using rfc3339_str_to_datetime.  | 
432 | 432 | 
  | 
433 | 433 |         Args:  | 
434 |  | -            date_tuple (str): A string containing two datetime values separated by a '/'.  | 
 | 434 | +            date_str (str): A string containing two datetime values separated by a '/'.  | 
435 | 435 | 
  | 
436 | 436 |         Returns:  | 
437 |  | -            str: A string formatted as 'YYYY-MM-DDTHH:MM:SS.sssZ/YYYY-MM-DDTHH:MM:SS.sssZ', with '..' used if any element is None.  | 
 | 437 | +            str: A string formatted as 'YYYY-MM-DDTHH:MM:SSZ/YYYY-MM-DDTHH:MM:SSZ', with '..' used if any element is None.  | 
438 | 438 |         """  | 
439 |  | -        start, end = date_str.split("/")  | 
440 |  | -        start = start.replace("+01:00", "Z") if start else ".."  | 
441 |  | -        end = end.replace("+01:00", "Z") if end else ".."  | 
442 |  | -        return f"{start}/{end}"  | 
 | 439 | +        def normalize(dt):  | 
 | 440 | +            dt = dt.strip()  | 
 | 441 | +            if not dt or dt == "..":  | 
 | 442 | +                return ".."  | 
 | 443 | +            dt_obj = rfc3339_str_to_datetime(dt)  | 
 | 444 | +            dt_utc = dt_obj.astimezone(timezone.utc)  | 
 | 445 | +            return dt_utc.strftime("%Y-%m-%dT%H:%M:%SZ")  | 
 | 446 | + | 
 | 447 | +        if not isinstance(date_str, str):  | 
 | 448 | +            return "../.."  | 
 | 449 | +        if "/" not in date_str:  | 
 | 450 | +            return f"{normalize(date_str)}/{normalize(date_str)}"  | 
 | 451 | +        try:  | 
 | 452 | +            start, end = date_str.split("/", 1)  | 
 | 453 | +        except Exception:  | 
 | 454 | +            return "../.."  | 
 | 455 | +        return f"{normalize(start)}/{normalize(end)}"  | 
443 | 456 | 
 
  | 
444 | 457 |     async def get_search(  | 
445 | 458 |         self,  | 
 | 
0 commit comments