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",
"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]},
"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"]["source_code"] == "mgm"
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
+70 -1
View File
@@ -7,6 +7,7 @@ import asyncio
import threading
import time
from copy import deepcopy
from datetime import datetime, timedelta, timezone
from typing import Any, Callable, Dict, List, Optional, Tuple
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
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(
city: str,
payload: Dict[str, Any],
latest_payload: Dict[str, Any],
) -> Dict[str, Any]:
@@ -366,6 +422,19 @@ def _merge_latest_observation_payload(
next_payload["updated_at"] = latest_payload.get("updated_at")
if 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
@@ -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"))
if not canonical_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]: