feat(api): 統一使用台北時區 UTC+8 (禁止 UTC)

- 新增 src/utils/timezone.py 時區工具函式
- 修改 11 個後端檔案,全部改用 now_taipei()
- 更新 HARD_RULES.md 加入時區鐵律章節
- 更新 Skills 02/04 加入時區禁令

🔴 HARD RULE: 禁止 datetime.utcnow() / datetime.now(UTC)
 正確做法: from src.utils.timezone import now_taipei

Memory: feedback_timezone_taipei.md

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
OG T
2026-03-25 09:08:34 +08:00
parent 5f3271174f
commit 2a2dac865a
14 changed files with 276 additions and 49 deletions

View File

@@ -18,6 +18,8 @@ import re
import uuid
from dataclasses import dataclass, field
from datetime import datetime
from src.utils.timezone import now_taipei
from enum import Enum
from typing import Any
@@ -53,7 +55,7 @@ class MCPToolResult:
output: Any | None = None
error: str | None = None
duration: float = 0.0
timestamp: datetime = field(default_factory=datetime.utcnow)
timestamp: datetime = field(default_factory=now_taipei)
def to_dict(self) -> dict:
return {
@@ -390,7 +392,7 @@ class MCPBridge:
MCPToolResult (符合 ActionResult 介面)
"""
execution_id = str(uuid.uuid4())
start_time = datetime.utcnow()
start_time = now_taipei()
try:
# ========================================
@@ -494,7 +496,7 @@ class MCPBridge:
def _calc_duration(self, start_time: datetime) -> float:
"""計算執行時間 (毫秒)"""
return (datetime.utcnow() - start_time).total_seconds() * 1000
return (now_taipei() - start_time).total_seconds() * 1000
# ==================== ActionExecutor 介面對齊 ====================