From 86911df07b65768a5870ee7647879e0b77d75949 Mon Sep 17 00:00:00 2001 From: Alexazhu Date: Fri, 1 May 2026 18:48:05 +0800 Subject: [PATCH] chore: make trace_cli datetime.fromtimestamp() tz-aware (DTZ006) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `datetime.fromtimestamp(x)` is ambiguous — it implicitly uses the system local timezone. Python's own docs suggest passing `tz=` explicitly. These are CLI debug views meant to display the operator's local time, so the semantics-preserving form is: datetime.fromtimestamp(x, tz=timezone.utc).astimezone() which produces an aware datetime in the system's local timezone — `strftime()` output is byte-identical to the naive version (verified with a representative epoch) but the behavior no longer depends on an implicit default. ruff --select DTZ006 on m_flow/debug/trace_cli.py is now clean. --- m_flow/debug/trace_cli.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/m_flow/debug/trace_cli.py b/m_flow/debug/trace_cli.py index 24007ac..8419073 100644 --- a/m_flow/debug/trace_cli.py +++ b/m_flow/debug/trace_cli.py @@ -16,7 +16,7 @@ import json import os from collections import defaultdict -from datetime import datetime +from datetime import datetime, timezone from typing import List, Dict, Any @@ -82,8 +82,10 @@ def print_trace_summary(events: List[Dict[str, Any]]) -> None: print("\n[STATS] Trace Summary") print(f" Events: {len(events)}") print(f" Duration: {duration_ms}ms") - print(f" Start: {datetime.fromtimestamp(start_ts / 1000).strftime('%H:%M:%S.%f')[:-3]}") - print(f" End: {datetime.fromtimestamp(end_ts / 1000).strftime('%H:%M:%S.%f')[:-3]}") + print( + f" Start: {datetime.fromtimestamp(start_ts / 1000, tz=timezone.utc).astimezone().strftime('%H:%M:%S.%f')[:-3]}" + ) + print(f" End: {datetime.fromtimestamp(end_ts / 1000, tz=timezone.utc).astimezone().strftime('%H:%M:%S.%f')[:-3]}") # Count by name cnt = defaultdict(int) @@ -106,7 +108,7 @@ def print_events(events: List[Dict[str, Any]], tail: int = 100) -> None: ts = e.get("ts_ms", 0) data = e.get("data", {}) - ts_str = datetime.fromtimestamp(ts / 1000).strftime("%H:%M:%S.%f")[:-3] + ts_str = datetime.fromtimestamp(ts / 1000, tz=timezone.utc).astimezone().strftime("%H:%M:%S.%f")[:-3] print(f"[{ts_str}] {name}") if isinstance(data, dict): @@ -161,7 +163,7 @@ def main(): print(f"\n[LIST] Recent Traces ({len(traces)}):") print("-" * 80) for t in traces: - mtime_str = datetime.fromtimestamp(t["mtime"]).strftime("%Y-%m-%d %H:%M:%S") + mtime_str = datetime.fromtimestamp(t["mtime"], tz=timezone.utc).astimezone().strftime("%Y-%m-%d %H:%M:%S") print(f" {t['trace_id']} {mtime_str} {t['size']:>8} bytes") return