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:
@@ -14,7 +14,9 @@ Phase 3.3: 商業變現能力 - Day-1 ROI
|
||||
|
||||
import logging
|
||||
from dataclasses import dataclass, field
|
||||
from datetime import datetime, timedelta
|
||||
from datetime import timedelta
|
||||
|
||||
from src.utils.timezone import now_taipei
|
||||
from enum import Enum
|
||||
from typing import Literal
|
||||
|
||||
@@ -232,7 +234,7 @@ class IdleResourceScanner:
|
||||
CostReport 包含所有浪費資源與建議動作
|
||||
"""
|
||||
self._scan_counter += 1
|
||||
scan_id = f"scan-{self._scan_counter:04d}-{datetime.utcnow().strftime('%Y%m%d%H%M%S')}"
|
||||
scan_id = f"scan-{self._scan_counter:04d}-{now_taipei().strftime('%Y%m%d%H%M%S')}"
|
||||
|
||||
logger.info(f"[FinOps] Starting full scan: {scan_id}")
|
||||
|
||||
@@ -254,7 +256,7 @@ class IdleResourceScanner:
|
||||
|
||||
report = CostReport(
|
||||
scan_id=scan_id,
|
||||
scanned_at=datetime.utcnow(),
|
||||
scanned_at=now_taipei(),
|
||||
cluster_name=cluster_name,
|
||||
total_wasted_usd=total_wasted,
|
||||
total_resources_scanned=self._get_mock_total_resources(),
|
||||
@@ -288,23 +290,23 @@ class IdleResourceScanner:
|
||||
"namespace": "database",
|
||||
"size_gb": 500,
|
||||
"storage_class": "gp3",
|
||||
"created": datetime.utcnow() - timedelta(days=90),
|
||||
"last_used": datetime.utcnow() - timedelta(days=60),
|
||||
"created": now_taipei() - timedelta(days=90),
|
||||
"last_used": now_taipei() - timedelta(days=60),
|
||||
},
|
||||
{
|
||||
"name": "logs-elasticsearch-2023",
|
||||
"namespace": "logging",
|
||||
"size_gb": 200,
|
||||
"storage_class": "gp2",
|
||||
"created": datetime.utcnow() - timedelta(days=180),
|
||||
"last_used": datetime.utcnow() - timedelta(days=120),
|
||||
"created": now_taipei() - timedelta(days=180),
|
||||
"last_used": now_taipei() - timedelta(days=120),
|
||||
},
|
||||
{
|
||||
"name": "cache-redis-temp",
|
||||
"namespace": "default",
|
||||
"size_gb": 50,
|
||||
"storage_class": "gp3",
|
||||
"created": datetime.utcnow() - timedelta(days=30),
|
||||
"created": now_taipei() - timedelta(days=30),
|
||||
"last_used": None,
|
||||
},
|
||||
]
|
||||
@@ -348,8 +350,8 @@ class IdleResourceScanner:
|
||||
"cpu_request": 2.0, # vCPU
|
||||
"mem_request_gb": 4.0,
|
||||
"avg_cpu_percent": 0.3,
|
||||
"created": datetime.utcnow() - timedelta(days=120),
|
||||
"last_active": datetime.utcnow() - timedelta(days=45),
|
||||
"created": now_taipei() - timedelta(days=120),
|
||||
"last_active": now_taipei() - timedelta(days=45),
|
||||
},
|
||||
{
|
||||
"name": "test-worker-batch-xyz99",
|
||||
@@ -357,8 +359,8 @@ class IdleResourceScanner:
|
||||
"cpu_request": 1.0,
|
||||
"mem_request_gb": 2.0,
|
||||
"avg_cpu_percent": 0.1,
|
||||
"created": datetime.utcnow() - timedelta(days=60),
|
||||
"last_active": datetime.utcnow() - timedelta(days=30),
|
||||
"created": now_taipei() - timedelta(days=60),
|
||||
"last_active": now_taipei() - timedelta(days=30),
|
||||
},
|
||||
{
|
||||
"name": "debug-shell-admin",
|
||||
@@ -366,8 +368,8 @@ class IdleResourceScanner:
|
||||
"cpu_request": 0.5,
|
||||
"mem_request_gb": 1.0,
|
||||
"avg_cpu_percent": 0.0,
|
||||
"created": datetime.utcnow() - timedelta(days=14),
|
||||
"last_active": datetime.utcnow() - timedelta(days=10),
|
||||
"created": now_taipei() - timedelta(days=14),
|
||||
"last_active": now_taipei() - timedelta(days=10),
|
||||
},
|
||||
]
|
||||
|
||||
@@ -420,7 +422,7 @@ class IdleResourceScanner:
|
||||
"requested_mem_gb": 48.0,
|
||||
"actual_cpu": 2.0,
|
||||
"actual_mem_gb": 8.0,
|
||||
"created": datetime.utcnow() - timedelta(days=200),
|
||||
"created": now_taipei() - timedelta(days=200),
|
||||
},
|
||||
{
|
||||
"name": "worker-gpu-unused",
|
||||
@@ -431,7 +433,7 @@ class IdleResourceScanner:
|
||||
"requested_mem_gb": 16.0,
|
||||
"actual_cpu": 0.5,
|
||||
"actual_mem_gb": 2.0,
|
||||
"created": datetime.utcnow() - timedelta(days=90),
|
||||
"created": now_taipei() - timedelta(days=90),
|
||||
},
|
||||
]
|
||||
|
||||
@@ -468,7 +470,7 @@ class IdleResourceScanner:
|
||||
),
|
||||
monthly_cost_usd=monthly_cost,
|
||||
created_at=node["created"],
|
||||
last_used_at=datetime.utcnow(),
|
||||
last_used_at=now_taipei(),
|
||||
spec={
|
||||
"totalCpu": node["total_cpu"],
|
||||
"totalMemoryGb": node["total_mem_gb"],
|
||||
|
||||
Reference in New Issue
Block a user