fix: kanban API timestamp normalization — _fmt_ts unify epoch/ISO to ISO 8601 output (from mohe, t_a1858603)
This commit is contained in:
+31
-2
@@ -17,6 +17,29 @@ def db():
|
||||
return sqlite3.connect(KANBAN_DB)
|
||||
|
||||
|
||||
def _fmt_ts(v):
|
||||
"""统一时间格式:epoch 或 ISO 字符串 → ISO 8601 字符串。
|
||||
DB 存储以 epoch 为主(CLI 写入),历史数据有少量 ISO 混存(半路接入),
|
||||
输出层统一成 ISO,调用方无需感知存储格式差异。"""
|
||||
if v is None:
|
||||
return None
|
||||
if isinstance(v, (int, float)):
|
||||
try:
|
||||
return datetime.fromtimestamp(int(v)).strftime("%Y-%m-%dT%H:%M:%S")
|
||||
except (OverflowError, OSError, ValueError):
|
||||
return str(v)
|
||||
s = str(v)
|
||||
try:
|
||||
# 已带 T 的 ISO 直接返回;纯数字字符串按 epoch 转
|
||||
if "T" in s:
|
||||
return s[:19]
|
||||
if s.isdigit():
|
||||
return datetime.fromtimestamp(int(s)).strftime("%Y-%m-%dT%H:%M:%S")
|
||||
except (OverflowError, OSError, ValueError):
|
||||
pass
|
||||
return s
|
||||
|
||||
|
||||
class KanbanAPI(http.server.BaseHTTPRequestHandler):
|
||||
def _json(self, data, status=200):
|
||||
self.send_response(status)
|
||||
@@ -37,6 +60,7 @@ class KanbanAPI(http.server.BaseHTTPRequestHandler):
|
||||
title = body.get("title", "")
|
||||
assignee = body.get("assignee", "")
|
||||
body_text = body.get("body", "")
|
||||
created_by = body.get("created_by", "") or body.get("author", "")
|
||||
if not title:
|
||||
return self._json({"error": "title required"}, 400)
|
||||
|
||||
@@ -47,6 +71,8 @@ class KanbanAPI(http.server.BaseHTTPRequestHandler):
|
||||
cmd += ["--assignee", assignee]
|
||||
if body_text:
|
||||
cmd += ["--body", body_text]
|
||||
if created_by:
|
||||
cmd += ["--created-by", created_by]
|
||||
r = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
|
||||
|
||||
if r.returncode != 0:
|
||||
@@ -66,6 +92,7 @@ class KanbanAPI(http.server.BaseHTTPRequestHandler):
|
||||
title = body.get("title", "")
|
||||
assignee = body.get("assignee", "")
|
||||
body_text = body.get("body", "")
|
||||
created_by = body.get("created_by", "") or body.get("author", "")
|
||||
if not title:
|
||||
return self._json({"error": "title required"}, 400)
|
||||
|
||||
@@ -75,6 +102,8 @@ class KanbanAPI(http.server.BaseHTTPRequestHandler):
|
||||
cmd += ["--assignee", assignee]
|
||||
if body_text:
|
||||
cmd += ["--body", body_text]
|
||||
if created_by:
|
||||
cmd += ["--created-by", created_by]
|
||||
r = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
|
||||
if r.returncode != 0:
|
||||
return self._json({"error": r.stderr.strip()}, 500)
|
||||
@@ -132,7 +161,7 @@ class KanbanAPI(http.server.BaseHTTPRequestHandler):
|
||||
for r in rows:
|
||||
tasks.append({
|
||||
"id": r[0], "title": r[1], "body": r[2], "status": r[3],
|
||||
"assignee": r[4], "created_by": r[5], "created_at": r[6]
|
||||
"assignee": r[4], "created_by": r[5], "created_at": _fmt_ts(r[6])
|
||||
})
|
||||
return self._json({"tasks": tasks})
|
||||
|
||||
@@ -208,7 +237,7 @@ class KanbanAPI(http.server.BaseHTTPRequestHandler):
|
||||
return self._json({
|
||||
"id": row[0], "title": row[1], "body": row[2],
|
||||
"status": row[3], "assignee": row[4],
|
||||
"created_by": row[5], "created_at": row[6]
|
||||
"created_by": row[5], "created_at": _fmt_ts(row[6])
|
||||
})
|
||||
|
||||
else:
|
||||
|
||||
Reference in New Issue
Block a user