diff --git a/app/gibs_map.py b/app/gibs_map.py index 48d0edb..95e7b18 100644 --- a/app/gibs_map.py +++ b/app/gibs_map.py @@ -20,7 +20,7 @@ from __future__ import annotations import asyncio import re import time -from datetime import date, datetime, timedelta +from datetime import date, datetime, timedelta, timezone import httpx @@ -98,9 +98,18 @@ def _parse_time_domain(domain: str) -> dict: Returns {min, max, latest, ranges:[{start,end}]} where ranges keep the raw GIBS windows so the frontend can warn when a picked date is outside every window (GIBS still serves nearest-time tiles, but this is honest). + + GIBS' published windows include the current UTC day as soon as it starts, + but daily mosaics (MODIS/VIIRS true color, night lights) aren't actually + ingested until hours later — tiles for "today" 404 until then. So we clamp + daily-layer window ends to *yesterday* UTC: 'latest' then always points at + imagery that really exists. """ windows = [] min_d, max_d = None, None + # 00:00–~03:00+ UTC the newest full day is always yesterday; use a small + # margin so we never advertise a same-day mosaic that isn't ingested yet. + cutoff = datetime.now(timezone.utc).date() - timedelta(days=1) for part in domain.split(","): part = part.strip() m = _TIME_RANGE_RE.match(part) @@ -108,6 +117,10 @@ def _parse_time_domain(domain: str) -> dict: continue start = date.fromisoformat(m.group(1)) end = date.fromisoformat(m.group(2)) + if m.group(3) == "P1D" and end > cutoff: + end = cutoff + if start > end: + continue # whole window was "not yet ingested" days windows.append({"start": start.isoformat(), "end": end.isoformat()}) if min_d is None or start < min_d: min_d = start