114 lines
2.7 KiB
Python
114 lines
2.7 KiB
Python
"""
|
|
辅助函数
|
|
"""
|
|
from datetime import datetime, timedelta
|
|
from typing import Optional, Any
|
|
import json
|
|
|
|
|
|
def format_datetime(dt: Optional[datetime]) -> Optional[str]:
|
|
"""格式化日期时间"""
|
|
if not dt:
|
|
return None
|
|
return dt.isoformat()
|
|
|
|
|
|
def parse_datetime(dt_str: str) -> Optional[datetime]:
|
|
"""解析日期时间字符串"""
|
|
if not dt_str:
|
|
return None
|
|
try:
|
|
return datetime.fromisoformat(dt_str)
|
|
except:
|
|
return None
|
|
|
|
|
|
def format_duration(seconds: int) -> str:
|
|
"""格式化时长"""
|
|
if seconds < 60:
|
|
return f"{seconds}s"
|
|
elif seconds < 3600:
|
|
return f"{seconds // 60}m"
|
|
elif seconds < 86400:
|
|
return f"{seconds // 3600}h"
|
|
else:
|
|
return f"{seconds // 86400}d"
|
|
|
|
|
|
def truncate_string(s: str, max_length: int = 100, suffix: str = "...") -> str:
|
|
"""截断字符串"""
|
|
if len(s) <= max_length:
|
|
return s
|
|
return s[:max_length - len(suffix)] + suffix
|
|
|
|
|
|
def safe_json_loads(data: str, default: Any = None) -> Any:
|
|
"""安全的 JSON 解析"""
|
|
try:
|
|
return json.loads(data)
|
|
except:
|
|
return default
|
|
|
|
|
|
def safe_json_dumps(data: Any, default: str = "{}") -> str:
|
|
"""安全的 JSON 序列化"""
|
|
try:
|
|
return json.dumps(data, ensure_ascii=False)
|
|
except:
|
|
return default
|
|
|
|
|
|
def generate_session_title() -> str:
|
|
"""生成默认会话标题"""
|
|
return f"Session {datetime.utcnow().strftime('%Y-%m-%d %H:%M')}"
|
|
|
|
|
|
def calculate_timeout(start_time: datetime, timeout_seconds: int) -> bool:
|
|
"""检查是否超时"""
|
|
if not start_time:
|
|
return True
|
|
|
|
elapsed = (datetime.utcnow() - start_time).total_seconds()
|
|
return elapsed > timeout_seconds
|
|
|
|
|
|
def merge_dicts(base: dict, override: dict) -> dict:
|
|
"""合并字典"""
|
|
result = base.copy()
|
|
result.update(override)
|
|
return result
|
|
|
|
|
|
def filter_none_values(data: dict) -> dict:
|
|
"""过滤字典中的 None 值"""
|
|
return {k: v for k, v in data.items() if v is not None}
|
|
|
|
|
|
class PaginationHelper:
|
|
"""分页辅助类"""
|
|
|
|
@staticmethod
|
|
def paginate(query, page: int = 1, per_page: int = 20):
|
|
"""分页查询"""
|
|
if page < 1:
|
|
page = 1
|
|
if per_page < 1:
|
|
per_page = 20
|
|
if per_page > 100:
|
|
per_page = 100
|
|
|
|
total = query.count()
|
|
items = query.offset((page - 1) * per_page).limit(per_page).all()
|
|
|
|
pages = (total + per_page - 1) // per_page
|
|
|
|
return {
|
|
'items': items,
|
|
'total': total,
|
|
'page': page,
|
|
'per_page': per_page,
|
|
'pages': pages,
|
|
'has_next': page < pages,
|
|
'has_prev': page > 1,
|
|
}
|