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

@@ -0,0 +1,70 @@
"""
AWOOOI - 時區工具
==================
統一使用 Asia/Taipei (UTC+8) 時區
🔴 HARD RULE: 全系統使用台北時區,禁止 UTC
"""
from datetime import datetime, timezone, timedelta
# 台北時區 (UTC+8)
TAIPEI_TZ = timezone(timedelta(hours=8))
def now_taipei() -> datetime:
"""
取得台北時區當前時間
Returns:
datetime: 帶有 +08:00 時區資訊的 datetime
Example:
>>> now_taipei().isoformat()
'2026-03-25T02:08:04+08:00'
"""
return datetime.now(TAIPEI_TZ)
def to_taipei(dt: datetime) -> datetime:
"""
將 datetime 轉換為台北時區
Args:
dt: 任何 datetime (可能是 UTC 或 naive)
Returns:
datetime: 台北時區的 datetime
"""
if dt.tzinfo is None:
# naive datetime假設是 UTC
dt = dt.replace(tzinfo=timezone.utc)
return dt.astimezone(TAIPEI_TZ)
def format_taipei(dt: datetime | None = None, fmt: str = "%Y-%m-%d %H:%M:%S") -> str:
"""
格式化為台北時區字串
Args:
dt: datetime (預設為當前時間)
fmt: strftime 格式
Returns:
str: 格式化的時間字串
"""
if dt is None:
dt = now_taipei()
else:
dt = to_taipei(dt)
return dt.strftime(fmt)
def now_taipei_iso() -> str:
"""
取得 ISO 格式的台北時區時間
Returns:
str: ISO 格式,例如 '2026-03-25T02:08:04+08:00'
"""
return now_taipei().isoformat()