11import json
22import os
3- import time
43from abc import ABC , abstractmethod
5- from datetime import datetime
64from typing import Any
75
86from src .utils import logger
7+ from src .utils .datetime_utils import coerce_any_to_utc_datetime , utc_isoformat
98
109
1110class KnowledgeBaseException (Exception ):
@@ -54,6 +53,34 @@ def __init__(self, work_dir: str):
5453
5554 # 自动加载元数据
5655 self ._load_metadata ()
56+ self ._normalize_metadata_state ()
57+
58+ @staticmethod
59+ def _normalize_timestamp (value : Any ) -> str | None :
60+ """Convert persisted timestamps to a normalized UTC ISO string."""
61+ try :
62+ dt_value = coerce_any_to_utc_datetime (value )
63+ except (TypeError , ValueError ) as exc : # noqa: BLE001
64+ logger .warning (f"Invalid timestamp encountered: { value !r} ({ exc } )" )
65+ return None
66+
67+ if not dt_value :
68+ return None
69+ return utc_isoformat (dt_value )
70+
71+ def _normalize_metadata_state (self ) -> None :
72+ """Ensure in-memory metadata uses normalized timestamp formats."""
73+ for meta in self .databases_meta .values ():
74+ if "created_at" in meta :
75+ normalized = self ._normalize_timestamp (meta .get ("created_at" ))
76+ if normalized :
77+ meta ["created_at" ] = normalized
78+
79+ for file_info in self .files_meta .values ():
80+ if "created_at" in file_info :
81+ normalized = self ._normalize_timestamp (file_info .get ("created_at" ))
82+ if normalized :
83+ file_info ["created_at" ] = normalized
5784
5885 @property
5986 @abstractmethod
@@ -117,7 +144,7 @@ def create_database(
117144 "embed_info" : embed_info ,
118145 "llm_info" : llm_info ,
119146 "metadata" : kwargs ,
120- "created_at" : datetime . now (). isoformat (),
147+ "created_at" : utc_isoformat (),
121148 }
122149 self ._save_metadata ()
123150
@@ -237,17 +264,24 @@ def get_database_info(self, db_id: str) -> dict | None:
237264 db_files = {}
238265 for file_id , file_info in self .files_meta .items ():
239266 if file_info .get ("database_id" ) == db_id :
267+ created_at = self ._normalize_timestamp (file_info .get ("created_at" ))
240268 db_files [file_id ] = {
241269 "file_id" : file_id ,
242270 "filename" : file_info .get ("filename" , "" ),
243271 "path" : file_info .get ("path" , "" ),
244272 "type" : file_info .get ("file_type" , "" ),
245273 "status" : file_info .get ("status" , "done" ),
246- "created_at" : file_info . get ( " created_at" , time . time ()) ,
274+ "created_at" : created_at ,
247275 }
248276
249277 # 按创建时间倒序排序文件列表
250- sorted_files = dict (sorted (db_files .items (), key = lambda x : x [1 ].get ("created_at" , 0 ), reverse = True ))
278+ sorted_files = dict (
279+ sorted (
280+ db_files .items (),
281+ key = lambda item : item [1 ].get ("created_at" ) or "" ,
282+ reverse = True ,
283+ )
284+ )
251285
252286 meta ["files" ] = sorted_files
253287 meta ["row_count" ] = len (sorted_files )
@@ -273,17 +307,24 @@ def get_databases(self) -> dict:
273307 db_files = {}
274308 for file_id , file_info in self .files_meta .items ():
275309 if file_info .get ("database_id" ) == db_id :
310+ created_at = self ._normalize_timestamp (file_info .get ("created_at" ))
276311 db_files [file_id ] = {
277312 "file_id" : file_id ,
278313 "filename" : file_info .get ("filename" , "" ),
279314 "path" : file_info .get ("path" , "" ),
280315 "type" : file_info .get ("file_type" , "" ),
281316 "status" : file_info .get ("status" , "done" ),
282- "created_at" : file_info . get ( " created_at" , time . time ()) ,
317+ "created_at" : created_at ,
283318 }
284319
285320 # 按创建时间倒序排序文件列表
286- sorted_files = dict (sorted (db_files .items (), key = lambda x : x [1 ].get ("created_at" , 0 ), reverse = True ))
321+ sorted_files = dict (
322+ sorted (
323+ db_files .items (),
324+ key = lambda item : item [1 ].get ("created_at" ) or "" ,
325+ reverse = True ,
326+ )
327+ )
287328
288329 db_dict ["files" ] = sorted_files
289330 db_dict ["row_count" ] = len (sorted_files )
@@ -495,13 +536,14 @@ def _load_metadata(self):
495536
496537 def _save_metadata (self ):
497538 """保存元数据"""
539+ self ._normalize_metadata_state ()
498540 meta_file = os .path .join (self .work_dir , f"metadata_{ self .kb_type } .json" )
499541 try :
500542 data = {
501543 "databases" : self .databases_meta ,
502544 "files" : self .files_meta ,
503545 "kb_type" : self .kb_type ,
504- "updated_at" : datetime . now (). isoformat (),
546+ "updated_at" : utc_isoformat (),
505547 }
506548 with open (meta_file , "w" , encoding = "utf-8" ) as f :
507549 json .dump (data , f , ensure_ascii = False , indent = 2 )
0 commit comments