xueyiming 1 месяц назад
Родитель
Сommit
cb9ff2e37f
1 измененных файлов с 14 добавлено и 7 удалено
  1. 14 7
      examples/demand/web_api.py

+ 14 - 7
examples/demand/web_api.py

@@ -9,6 +9,7 @@ import sys
 from datetime import datetime, timedelta
 from pathlib import Path
 from typing import Any, Literal, Optional
+from zoneinfo import ZoneInfo
 
 from fastapi import FastAPI, HTTPException
 from pydantic import BaseModel
@@ -51,10 +52,13 @@ DEMAND_SCHEDULER_ENABLED: bool = os.getenv("DEMAND_SCHEDULER_ENABLED", "1").stri
 
 DEMAND_SCHEDULER_START_HOUR: int = 2
 
+# 定时任务统一使用北京时间,避免服务器时区(如 UTC)带来的偏差
+BEIJING_TZ = ZoneInfo("Asia/Shanghai")
+
 
 def _get_today_time_window(now: datetime) -> tuple[datetime, datetime]:
     """返回今天的 [start, end) 时间窗口(本地时区)。"""
-    start_of_today = datetime(year=now.year, month=now.month, day=now.day)
+    start_of_today = datetime(year=now.year, month=now.month, day=now.day, tzinfo=now.tzinfo)
     end_of_today = start_of_today + timedelta(days=1)
     return start_of_today, end_of_today
 
@@ -99,6 +103,9 @@ def _today_has_status_0_or_1(cluster_name: str, platform_type: str, now: datetim
     - 若存在 status 为 0 或 1 的记录,则跳过
     """
     start_of_today, end_of_today = _get_today_time_window(now)
+    # MySQL DATETIME 一般按无时区存储,这里使用北京时间对应的“本地时间”窗口做过滤
+    start_of_today_naive = start_of_today.replace(tzinfo=None)
+    end_of_today_naive = end_of_today.replace(tzinfo=None)
     return mysql_db.exists(
         "demand_task",
         where=(
@@ -111,8 +118,8 @@ def _today_has_status_0_or_1(cluster_name: str, platform_type: str, now: datetim
         where_params=(
             str(cluster_name)[:32],
             str(platform_type)[:32],
-            start_of_today,
-            end_of_today,
+            start_of_today_naive,
+            end_of_today_naive,
         ),
     )
 
@@ -126,7 +133,7 @@ async def demand_scheduled_run_once() -> None:
     if not DEMAND_SCHEDULE_CLUSTER_PLATFORM_LIST:
         return
 
-    now = datetime.now()
+    now = datetime.now(BEIJING_TZ)
     for item in DEMAND_SCHEDULE_CLUSTER_PLATFORM_LIST:
         cluster_name = item.get("cluster_name")
         platform_type = item.get("platform_type")
@@ -204,11 +211,11 @@ async def _start_demand_scheduler() -> None:
         print("[scheduler] apscheduler 未安装,跳过定时任务启动")
         return
 
-    scheduler = AsyncIOScheduler()
+    scheduler = AsyncIOScheduler(timezone=BEIJING_TZ)
     # 02:00 - 23:30:每 30 分钟一次
     scheduler.add_job(
         func=_demand_scheduler_job,
-        trigger=CronTrigger(hour=f"{DEMAND_SCHEDULER_START_HOUR}-23", minute="0,30"),
+        trigger=CronTrigger(hour=f"{DEMAND_SCHEDULER_START_HOUR}-23", minute="0,30", timezone=BEIJING_TZ),
         id="demand_scheduler_job_main",
         replace_existing=True,
         max_instances=1,
@@ -217,7 +224,7 @@ async def _start_demand_scheduler() -> None:
     # 24:00(即下一天 00:00):每天一次
     scheduler.add_job(
         func=_demand_scheduler_job,
-        trigger=CronTrigger(hour="0", minute="0"),
+        trigger=CronTrigger(hour="0", minute="0", timezone=BEIJING_TZ),
         id="demand_scheduler_job_midnight",
         replace_existing=True,
         max_instances=1,