From 13afc654ab359d5761a636ddac9ad11e8ee58156 Mon Sep 17 00:00:00 2001 From: 16337 <1633794139@qq.com> Date: Thu, 22 Jan 2026 09:08:44 +0800 Subject: [PATCH] =?UTF-8?q?fix(timezone):=E4=BF=AE=E5=A4=8D=E8=A7=A6?= =?UTF-8?q?=E5=8F=91=E5=91=8A=E8=AD=A6=E8=AE=B0=E5=BD=95=E7=9A=84=E6=97=B6?= =?UTF-8?q?=E9=97=B4=E6=B7=B7=E4=B9=B1=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/alarm.py | 60 +++++++++++++++++++++++++++------------------------ api/camera.py | 18 ++++++++++++++-- 2 files changed, 48 insertions(+), 30 deletions(-) diff --git a/api/alarm.py b/api/alarm.py index 25cea74..bc11a93 100644 --- a/api/alarm.py +++ b/api/alarm.py @@ -1,4 +1,4 @@ -from datetime import datetime +from datetime import datetime, timezone, timedelta from typing import List, Optional from fastapi import APIRouter, Depends, HTTPException, Query, Body @@ -23,6 +23,35 @@ class AlarmUpdateRequest(BaseModel): processed: Optional[bool] = None +def convert_to_china_time(dt: Optional[datetime]) -> Optional[str]: + """将 UTC 时间转换为中国时间 (UTC+8)""" + if dt is None: + return None + try: + china_tz = timezone(timedelta(hours=8)) + if dt.tzinfo is None: + dt = dt.replace(tzinfo=timezone.utc) + return dt.astimezone(china_tz).isoformat() + except Exception: + return dt.isoformat() if dt else None + + +def format_alarm_response(alarm) -> dict: + """格式化告警响应,将 UTC 时间转换为中国时间""" + return { + "id": alarm.id, + "camera_id": alarm.camera_id, + "roi_id": alarm.roi_id, + "event_type": alarm.event_type, + "confidence": alarm.confidence, + "snapshot_path": alarm.snapshot_path, + "llm_checked": alarm.llm_checked, + "llm_result": alarm.llm_result, + "processed": alarm.processed, + "created_at": convert_to_china_time(alarm.created_at), + } + + @router.get("", response_model=List[dict]) def list_alarms( camera_id: Optional[int] = None, @@ -32,21 +61,7 @@ def list_alarms( db: Session = Depends(get_db), ): alarms = get_alarms(db, camera_id=camera_id, event_type=event_type, limit=limit, offset=offset) - return [ - { - "id": alarm.id, - "camera_id": alarm.camera_id, - "roi_id": alarm.roi_id, - "event_type": alarm.event_type, - "confidence": alarm.confidence, - "snapshot_path": alarm.snapshot_path, - "llm_checked": alarm.llm_checked, - "llm_result": alarm.llm_result, - "processed": alarm.processed, - "created_at": alarm.created_at.isoformat() if alarm.created_at else None, - } - for alarm in alarms - ] + return [format_alarm_response(alarm) for alarm in alarms] @router.get("/stats") @@ -62,18 +77,7 @@ def get_alarm(alarm_id: int, db: Session = Depends(get_db)): alarm = next((a for a in alarms if a.id == alarm_id), None) if not alarm: raise HTTPException(status_code=404, detail="告警不存在") - return { - "id": alarm.id, - "camera_id": alarm.camera_id, - "roi_id": alarm.roi_id, - "event_type": alarm.event_type, - "confidence": alarm.confidence, - "snapshot_path": alarm.snapshot_path, - "llm_checked": alarm.llm_checked, - "llm_result": alarm.llm_result, - "processed": alarm.processed, - "created_at": alarm.created_at.isoformat() if alarm.created_at else None, - } + return format_alarm_response(alarm) @router.put("/{alarm_id}") diff --git a/api/camera.py b/api/camera.py index d2d860a..d8b9657 100644 --- a/api/camera.py +++ b/api/camera.py @@ -1,3 +1,4 @@ +from datetime import datetime, timezone, timedelta from typing import List, Optional from fastapi import APIRouter, Depends, HTTPException, Body @@ -26,6 +27,19 @@ class CameraUpdateRequest(BaseModel): enabled: Optional[bool] = None +def convert_to_china_time(dt: Optional[datetime]) -> Optional[str]: + """将 UTC 时间转换为中国时间 (UTC+8)""" + if dt is None: + return None + try: + china_tz = timezone(timedelta(hours=8)) + if dt.tzinfo is None: + dt = dt.replace(tzinfo=timezone.utc) + return dt.astimezone(china_tz).isoformat() + except Exception: + return dt.isoformat() if dt else None + + @router.get("", response_model=List[dict]) def list_cameras( enabled_only: bool = True, @@ -40,7 +54,7 @@ def list_cameras( "enabled": cam.enabled, "fps_limit": cam.fps_limit, "process_every_n_frames": cam.process_every_n_frames, - "created_at": cam.created_at.isoformat() if cam.created_at else None, + "created_at": convert_to_china_time(cam.created_at), } for cam in cameras ] @@ -58,7 +72,7 @@ def get_camera(camera_id: int, db: Session = Depends(get_db)): "enabled": camera.enabled, "fps_limit": camera.fps_limit, "process_every_n_frames": camera.process_every_n_frames, - "created_at": camera.created_at.isoformat() if camera.created_at else None, + "created_at": convert_to_china_time(camera.created_at), }