Fix Ankara stale chart date overlay

This commit is contained in:
2569718930@qq.com
2026-06-15 23:12:56 +08:00
parent fd9d768c6d
commit 5075cf40b8
2 changed files with 74 additions and 1 deletions
+4
View File
@@ -1854,6 +1854,7 @@ def test_stale_ankara_chart_data_overlays_latest_mgm_canonical(monkeypatch):
"source_label": "METAR", "source_label": "METAR",
"obs_time": "2026-06-14T09:50:00+00:00", "obs_time": "2026-06-14T09:50:00+00:00",
}, },
"airport_primary_today_obs": [{"time": "12:50", "temp": 16.0}],
"hourly": {"times": ["2026-06-14T09:00:00Z"], "temps": [16.0]}, "hourly": {"times": ["2026-06-14T09:00:00Z"], "temps": [16.0]},
"deb": {"prediction": 23.0}, "deb": {"prediction": 23.0},
}, },
@@ -1897,6 +1898,9 @@ def test_stale_ankara_chart_data_overlays_latest_mgm_canonical(monkeypatch):
assert payload["airport_primary"]["temp"] == 19.0 assert payload["airport_primary"]["temp"] == 19.0
assert payload["airport_primary"]["source_code"] == "mgm" assert payload["airport_primary"]["source_code"] == "mgm"
assert payload["airport_primary"]["station_code"] == "17128" assert payload["airport_primary"]["station_code"] == "17128"
assert payload["local_date"] == "2026-06-15"
assert payload["local_time"] == "17:20"
assert payload["airport_primary_today_obs"] == [{"time": "17:20", "temp": 19.0}]
assert payload["deb"]["prediction"] == 23.0 assert payload["deb"]["prediction"] == 23.0
+70 -1
View File
@@ -7,6 +7,7 @@ import asyncio
import threading import threading
import time import time
from copy import deepcopy from copy import deepcopy
from datetime import datetime, timedelta, timezone
from typing import Any, Callable, Dict, List, Optional, Tuple from typing import Any, Callable, Dict, List, Optional, Tuple
from fastapi import HTTPException, Request from fastapi import HTTPException, Request
@@ -340,7 +341,62 @@ def _payload_observation_epoch(payload: Dict[str, Any]) -> Optional[int]:
return max(epochs) if epochs else None return max(epochs) if epochs else None
def _float_or_none(value: Any) -> Optional[float]:
try:
if value is None or value == "":
return None
return float(value)
except (TypeError, ValueError):
return None
def _latest_observation_local_context(
city: str,
latest_payload: Dict[str, Any],
) -> Dict[str, str]:
epoch = _payload_observation_epoch(latest_payload)
if epoch is None:
return {}
try:
offset_sec = int((legacy_routes.CITIES.get(city) or {}).get("tz") or 0)
except Exception:
offset_sec = 0
local_dt = datetime.fromtimestamp(epoch, timezone.utc) + timedelta(seconds=offset_sec)
return {
"local_date": local_dt.strftime("%Y-%m-%d"),
"local_time": local_dt.strftime("%H:%M"),
}
def _latest_airport_primary_point(
latest_payload: Dict[str, Any],
*,
local_time: str,
) -> List[Dict[str, Any]]:
if not local_time:
return []
airport = latest_payload.get("airport_primary") if isinstance(latest_payload.get("airport_primary"), dict) else {}
current = latest_payload.get("current") if isinstance(latest_payload.get("current"), dict) else {}
temp = _float_or_none(airport.get("temp") if airport else None)
if temp is None:
temp = _float_or_none(current.get("temp") if current else None)
if temp is None:
return []
return [{"time": local_time, "temp": round(float(temp), 1)}]
def _replace_airport_primary_today_obs(
payload: Dict[str, Any],
points: List[Dict[str, Any]],
) -> None:
payload["airport_primary_today_obs"] = points
official = payload.get("official")
if isinstance(official, dict):
official["airport_primary_today_obs"] = points
def _merge_latest_observation_payload( def _merge_latest_observation_payload(
city: str,
payload: Dict[str, Any], payload: Dict[str, Any],
latest_payload: Dict[str, Any], latest_payload: Dict[str, Any],
) -> Dict[str, Any]: ) -> Dict[str, Any]:
@@ -366,6 +422,19 @@ def _merge_latest_observation_payload(
next_payload["updated_at"] = latest_payload.get("updated_at") next_payload["updated_at"] = latest_payload.get("updated_at")
if latest_payload.get("temp_symbol"): if latest_payload.get("temp_symbol"):
next_payload["temp_symbol"] = latest_payload.get("temp_symbol") next_payload["temp_symbol"] = latest_payload.get("temp_symbol")
local_context = _latest_observation_local_context(city, latest_payload)
if local_context:
previous_local_date = str(next_payload.get("local_date") or "")
next_payload.update(local_context)
if previous_local_date and previous_local_date != local_context["local_date"]:
_replace_airport_primary_today_obs(
next_payload,
_latest_airport_primary_point(
latest_payload,
local_time=local_context["local_time"],
),
)
return next_payload return next_payload
@@ -375,7 +444,7 @@ async def _overlay_cached_canonical_observation(city: str, payload: Dict[str, An
canonical_payload = await _get_canonical_city_payload(city, detail_depth=str(payload.get("detail_depth") or "full")) canonical_payload = await _get_canonical_city_payload(city, detail_depth=str(payload.get("detail_depth") or "full"))
if not canonical_payload: if not canonical_payload:
return payload return payload
return _merge_latest_observation_payload(payload, canonical_payload) return _merge_latest_observation_payload(city, payload, canonical_payload)
def _overlay_cached_runway_history_from_db(city: str, payload: Dict[str, Any]) -> Dict[str, Any]: def _overlay_cached_runway_history_from_db(city: str, payload: Dict[str, Any]) -> Dict[str, Any]: