54 lines
1.4 KiB
Python
54 lines
1.4 KiB
Python
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
from datetime import UTC, date, datetime
|
||
|
|
from zoneinfo import ZoneInfo
|
||
|
|
|
||
|
|
from app.services.employee_serialization import format_history_datetime as serialize_history_datetime
|
||
|
|
|
||
|
|
DISPLAY_TIMEZONE = ZoneInfo("Asia/Shanghai")
|
||
|
|
|
||
|
|
|
||
|
|
def normalize_optional_text(value: str | None) -> str | None:
|
||
|
|
if value is None:
|
||
|
|
return None
|
||
|
|
text_value = value.strip()
|
||
|
|
return text_value or None
|
||
|
|
|
||
|
|
|
||
|
|
def parse_date(value: str | None) -> date | None:
|
||
|
|
if not value:
|
||
|
|
return None
|
||
|
|
return datetime.strptime(value, "%Y-%m-%d").date()
|
||
|
|
|
||
|
|
|
||
|
|
def parse_datetime(value: str | datetime | None) -> datetime | None:
|
||
|
|
if value is None:
|
||
|
|
return None
|
||
|
|
if isinstance(value, datetime):
|
||
|
|
return value
|
||
|
|
return datetime.strptime(value, "%Y-%m-%d %H:%M")
|
||
|
|
|
||
|
|
|
||
|
|
def format_date(value: date | None) -> str | None:
|
||
|
|
if value is None:
|
||
|
|
return None
|
||
|
|
return value.strftime("%Y-%m-%d")
|
||
|
|
|
||
|
|
|
||
|
|
def to_display_datetime(value: datetime) -> datetime:
|
||
|
|
if value.tzinfo is None:
|
||
|
|
normalized = value.replace(tzinfo=UTC)
|
||
|
|
else:
|
||
|
|
normalized = value.astimezone(UTC)
|
||
|
|
return normalized.astimezone(DISPLAY_TIMEZONE)
|
||
|
|
|
||
|
|
|
||
|
|
def format_datetime(value: datetime | None) -> str | None:
|
||
|
|
if value is None:
|
||
|
|
return None
|
||
|
|
return to_display_datetime(value).strftime("%Y-%m-%d %H:%M")
|
||
|
|
|
||
|
|
|
||
|
|
def format_history_datetime(value: datetime | None) -> str:
|
||
|
|
return serialize_history_datetime(value, to_display_datetime=to_display_datetime)
|