utils.py 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. """统一工具函数"""
  2. import uuid
  3. import random
  4. import string
  5. from datetime import date, datetime
  6. from typing import Optional, Union
  7. def generate_uuid() -> str:
  8. """生成UUID"""
  9. return str(uuid.uuid4()).replace("-", "").upper()
  10. def generate_id(prefix: str = "") -> str:
  11. """生成带前缀的ID"""
  12. uid = str(uuid.uuid4()).replace("-", "").upper()
  13. return f"{prefix}{uid}" if prefix else uid
  14. def generate_random_password(length: int = 8) -> str:
  15. """生成随机密码"""
  16. chars = string.ascii_letters + string.digits
  17. return ''.join(random.choice(chars) for _ in range(length))
  18. def get_current_time() -> datetime:
  19. """获取当前时间"""
  20. return datetime.now()
  21. def format_datetime(dt: Optional[datetime]) -> Optional[str]:
  22. """格式化时间为ISO 8601格式"""
  23. if dt is None:
  24. return None
  25. return dt.strftime("%Y-%m-%d %H:%M:%S")
  26. def parse_datetime(dt_str: str) -> Optional[datetime]:
  27. """解析ISO 8601格式时间"""
  28. if not dt_str:
  29. return None
  30. try:
  31. return datetime.fromisoformat(dt_str.replace("Z", "+00:00"))
  32. except (ValueError, AttributeError):
  33. return None
  34. def format_date(d: Optional[Union[date, datetime]]) -> str:
  35. """格式化日期为 YYYY-MM-DD"""
  36. if d is None:
  37. return ""
  38. if isinstance(d, datetime):
  39. d = d.date()
  40. return d.strftime("%Y-%m-%d")
  41. def parse_date(date_str: str) -> Optional[date]:
  42. """解析 YYYY-MM-DD 日期"""
  43. if not date_str:
  44. return None
  45. try:
  46. s = str(date_str).strip()
  47. if not s:
  48. return None
  49. return datetime.fromisoformat(s[:10]).date()
  50. except (ValueError, AttributeError):
  51. return None
  52. def optional_date(v: object) -> Optional[date]:
  53. """将字符串 / date / datetime 转为 date 或 None"""
  54. if v is None or v == "":
  55. return None
  56. if isinstance(v, datetime):
  57. return v.date()
  58. if isinstance(v, date):
  59. return v
  60. return parse_date(str(v))
  61. def get_file_size_display(size_bytes: int) -> str:
  62. """将字节数转换为可读的文件大小"""
  63. if size_bytes is None:
  64. return "0 B"
  65. for unit in ['B', 'KB', 'MB', 'GB', 'TB']:
  66. if size_bytes < 1024.0:
  67. return f"{size_bytes:.2f} {unit}"
  68. size_bytes /= 1024.0
  69. return f"{size_bytes:.2f} PB"