gzdaniel commited on
Commit
bdc814e
·
1 Parent(s): 48aa1f9

Fix time zone problem of doc status

Browse files
lightrag/api/routers/document_routes.py CHANGED
@@ -9,7 +9,7 @@ import aiofiles
9
  import shutil
10
  import traceback
11
  import pipmaster as pm
12
- from datetime import datetime
13
  from pathlib import Path
14
  from typing import Dict, List, Optional, Any, Literal
15
  from fastapi import APIRouter, BackgroundTasks, Depends, File, HTTPException, UploadFile
@@ -20,6 +20,30 @@ from lightrag.base import DocProcessingStatus, DocStatus
20
  from lightrag.api.utils_api import get_combined_auth_dependency
21
  from ..config import global_args
22
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  router = APIRouter(
24
  prefix="/documents",
25
  tags=["documents"],
@@ -207,14 +231,6 @@ Attributes:
207
 
208
 
209
  class DocStatusResponse(BaseModel):
210
- @staticmethod
211
- def format_datetime(dt: Any) -> Optional[str]:
212
- if dt is None:
213
- return None
214
- if isinstance(dt, str):
215
- return dt
216
- return dt.isoformat()
217
-
218
  id: str = Field(description="Document identifier")
219
  content_summary: str = Field(description="Summary of document content")
220
  content_length: int = Field(description="Length of document content in characters")
@@ -300,7 +316,7 @@ class PipelineStatusResponse(BaseModel):
300
  autoscanned: Whether auto-scan has started
301
  busy: Whether the pipeline is currently busy
302
  job_name: Current job name (e.g., indexing files/indexing texts)
303
- job_start: Job start time as ISO format string (optional)
304
  docs: Total number of documents to be indexed
305
  batchs: Number of batches for processing documents
306
  cur_batch: Current processing batch
@@ -322,6 +338,12 @@ class PipelineStatusResponse(BaseModel):
322
  history_messages: Optional[List[str]] = None
323
  update_status: Optional[dict] = None
324
 
 
 
 
 
 
 
325
  class Config:
326
  extra = "allow" # Allow additional fields from the pipeline status
327
 
@@ -1188,9 +1210,10 @@ def create_document_routes(
1188
  if "history_messages" in status_dict:
1189
  status_dict["history_messages"] = list(status_dict["history_messages"])
1190
 
1191
- # Format the job_start time if it exists
1192
- if status_dict.get("job_start"):
1193
- status_dict["job_start"] = str(status_dict["job_start"])
 
1194
 
1195
  return PipelineStatusResponse(**status_dict)
1196
  except Exception as e:
@@ -1240,10 +1263,10 @@ def create_document_routes(
1240
  content_summary=doc_status.content_summary,
1241
  content_length=doc_status.content_length,
1242
  status=doc_status.status,
1243
- created_at=DocStatusResponse.format_datetime(
1244
  doc_status.created_at
1245
  ),
1246
- updated_at=DocStatusResponse.format_datetime(
1247
  doc_status.updated_at
1248
  ),
1249
  chunks_count=doc_status.chunks_count,
 
9
  import shutil
10
  import traceback
11
  import pipmaster as pm
12
+ from datetime import datetime, timezone
13
  from pathlib import Path
14
  from typing import Dict, List, Optional, Any, Literal
15
  from fastapi import APIRouter, BackgroundTasks, Depends, File, HTTPException, UploadFile
 
20
  from lightrag.api.utils_api import get_combined_auth_dependency
21
  from ..config import global_args
22
 
23
+ # Function to format datetime to ISO format string with timezone information
24
+ def format_datetime(dt: Any) -> Optional[str]:
25
+ """Format datetime to ISO format string with timezone information
26
+
27
+ Args:
28
+ dt: Datetime object, string, or None
29
+
30
+ Returns:
31
+ ISO format string with timezone information, or None if input is None
32
+ """
33
+ if dt is None:
34
+ return None
35
+ if isinstance(dt, str):
36
+ return dt
37
+
38
+ # Check if datetime object has timezone information
39
+ if isinstance(dt, datetime):
40
+ # If datetime object has no timezone info (naive datetime), add UTC timezone
41
+ if dt.tzinfo is None:
42
+ dt = dt.replace(tzinfo=timezone.utc)
43
+
44
+ # Return ISO format string with timezone information
45
+ return dt.isoformat()
46
+
47
  router = APIRouter(
48
  prefix="/documents",
49
  tags=["documents"],
 
231
 
232
 
233
  class DocStatusResponse(BaseModel):
 
 
 
 
 
 
 
 
234
  id: str = Field(description="Document identifier")
235
  content_summary: str = Field(description="Summary of document content")
236
  content_length: int = Field(description="Length of document content in characters")
 
316
  autoscanned: Whether auto-scan has started
317
  busy: Whether the pipeline is currently busy
318
  job_name: Current job name (e.g., indexing files/indexing texts)
319
+ job_start: Job start time as ISO format string with timezone (optional)
320
  docs: Total number of documents to be indexed
321
  batchs: Number of batches for processing documents
322
  cur_batch: Current processing batch
 
338
  history_messages: Optional[List[str]] = None
339
  update_status: Optional[dict] = None
340
 
341
+ @field_validator('job_start', mode='before')
342
+ @classmethod
343
+ def parse_job_start(cls, value):
344
+ """Process datetime and return as ISO format string with timezone"""
345
+ return format_datetime(value)
346
+
347
  class Config:
348
  extra = "allow" # Allow additional fields from the pipeline status
349
 
 
1210
  if "history_messages" in status_dict:
1211
  status_dict["history_messages"] = list(status_dict["history_messages"])
1212
 
1213
+ # Ensure job_start is properly formatted as a string with timezone information
1214
+ if "job_start" in status_dict and status_dict["job_start"]:
1215
+ # Use format_datetime to ensure consistent formatting
1216
+ status_dict["job_start"] = format_datetime(status_dict["job_start"])
1217
 
1218
  return PipelineStatusResponse(**status_dict)
1219
  except Exception as e:
 
1263
  content_summary=doc_status.content_summary,
1264
  content_length=doc_status.content_length,
1265
  status=doc_status.status,
1266
+ created_at=format_datetime(
1267
  doc_status.created_at
1268
  ),
1269
+ updated_at=format_datetime(
1270
  doc_status.updated_at
1271
  ),
1272
  chunks_count=doc_status.chunks_count,
lightrag/lightrag.py CHANGED
@@ -6,7 +6,7 @@ import configparser
6
  import os
7
  import warnings
8
  from dataclasses import asdict, dataclass, field
9
- from datetime import datetime
10
  from functools import partial
11
  from typing import (
12
  Any,
@@ -756,8 +756,8 @@ class LightRAG:
756
  "content": content_data["content"],
757
  "content_summary": get_content_summary(content_data["content"]),
758
  "content_length": len(content_data["content"]),
759
- "created_at": datetime.now().isoformat(),
760
- "updated_at": datetime.now().isoformat(),
761
  "file_path": content_data[
762
  "file_path"
763
  ], # Store file path in document status
@@ -840,7 +840,7 @@ class LightRAG:
840
  {
841
  "busy": True,
842
  "job_name": "Default Job",
843
- "job_start": datetime.now().isoformat(),
844
  "docs": 0,
845
  "batchs": 0, # Total number of files to be processed
846
  "cur_batch": 0, # Number of files already processed
@@ -958,7 +958,7 @@ class LightRAG:
958
  "content_summary": status_doc.content_summary,
959
  "content_length": status_doc.content_length,
960
  "created_at": status_doc.created_at,
961
- "updated_at": datetime.now().isoformat(),
962
  "file_path": file_path,
963
  }
964
  }
@@ -1018,7 +1018,7 @@ class LightRAG:
1018
  "content_summary": status_doc.content_summary,
1019
  "content_length": status_doc.content_length,
1020
  "created_at": status_doc.created_at,
1021
- "updated_at": datetime.now().isoformat(),
1022
  "file_path": file_path,
1023
  }
1024
  }
@@ -1053,7 +1053,7 @@ class LightRAG:
1053
  "content_summary": status_doc.content_summary,
1054
  "content_length": status_doc.content_length,
1055
  "created_at": status_doc.created_at,
1056
- "updated_at": datetime.now().isoformat(),
1057
  "file_path": file_path,
1058
  }
1059
  }
 
6
  import os
7
  import warnings
8
  from dataclasses import asdict, dataclass, field
9
+ from datetime import datetime, timezone
10
  from functools import partial
11
  from typing import (
12
  Any,
 
756
  "content": content_data["content"],
757
  "content_summary": get_content_summary(content_data["content"]),
758
  "content_length": len(content_data["content"]),
759
+ "created_at": datetime.now(timezone.utc).isoformat(),
760
+ "updated_at": datetime.now(timezone.utc).isoformat(),
761
  "file_path": content_data[
762
  "file_path"
763
  ], # Store file path in document status
 
840
  {
841
  "busy": True,
842
  "job_name": "Default Job",
843
+ "job_start": datetime.now(timezone.utc).isoformat(),
844
  "docs": 0,
845
  "batchs": 0, # Total number of files to be processed
846
  "cur_batch": 0, # Number of files already processed
 
958
  "content_summary": status_doc.content_summary,
959
  "content_length": status_doc.content_length,
960
  "created_at": status_doc.created_at,
961
+ "updated_at": datetime.now(timezone.utc).isoformat(),
962
  "file_path": file_path,
963
  }
964
  }
 
1018
  "content_summary": status_doc.content_summary,
1019
  "content_length": status_doc.content_length,
1020
  "created_at": status_doc.created_at,
1021
+ "updated_at": datetime.now(timezone.utc).isoformat(),
1022
  "file_path": file_path,
1023
  }
1024
  }
 
1053
  "content_summary": status_doc.content_summary,
1054
  "content_length": status_doc.content_length,
1055
  "created_at": status_doc.created_at,
1056
+ "updated_at": datetime.now(timezone.utc).isoformat(),
1057
  "file_path": file_path,
1058
  }
1059
  }
lightrag_webui/src/components/documents/PipelineStatusDialog.tsx CHANGED
@@ -158,7 +158,16 @@ export default function PipelineStatusDialog({
158
  <div className="rounded-md border p-3 space-y-2">
159
  <div>{t('documentPanel.pipelineStatus.jobName')}: {status?.job_name || '-'}</div>
160
  <div className="flex justify-between">
161
- <span>{t('documentPanel.pipelineStatus.startTime')}: {status?.job_start ? new Date(status.job_start).toLocaleString() : '-'}</span>
 
 
 
 
 
 
 
 
 
162
  <span>{t('documentPanel.pipelineStatus.progress')}: {status ? `${status.cur_batch}/${status.batchs} ${t('documentPanel.pipelineStatus.unit')}` : '-'}</span>
163
  </div>
164
  </div>
 
158
  <div className="rounded-md border p-3 space-y-2">
159
  <div>{t('documentPanel.pipelineStatus.jobName')}: {status?.job_name || '-'}</div>
160
  <div className="flex justify-between">
161
+ <span>{t('documentPanel.pipelineStatus.startTime')}: {status?.job_start
162
+ ? new Date(status.job_start).toLocaleString(undefined, {
163
+ year: 'numeric',
164
+ month: 'numeric',
165
+ day: 'numeric',
166
+ hour: 'numeric',
167
+ minute: 'numeric',
168
+ second: 'numeric'
169
+ })
170
+ : '-'}</span>
171
  <span>{t('documentPanel.pipelineStatus.progress')}: {status ? `${status.cur_batch}/${status.batchs} ${t('documentPanel.pipelineStatus.unit')}` : '-'}</span>
172
  </div>
173
  </div>