Files
Aislo/common_util/common_util_time.py
T
eomsangdonandClaude Sonnet 5.5 bbc61e5040 fix(시간 표시): 서버 시각 모두 끝 Z · Z 없는 옛 기록 = 한국 시각으로 읽음 (PLAN 593-2 · 요구 456)
- 서버: DB 시각 글(DATE_FORMAT) 끝 Z · B03 올린 때 · D04 확정 시각 · 건강 확인 시각 = UTC Z · 개요 최근 변경 T 치환 뺌
- 서버가 만드는 엑셀(E05 면적 계산 시각) = 한국 시각 글(kst_text · Z 없는 옛 글은 이미 한국 시각)
- 화면: Z 없는 글 = 옛 로컬 기록 → +09:00 로 읽음(옛 파일은 고쳐 쓰지 않음)
- 시험: test_593_time(UTC · 서울 · 뉴욕 시간대 · Z 없는 길 0 정적 검사 · D04 · kst_text)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-30 10:26:24 +09:00

67 lines
2.4 KiB
Python

"""서버 시각 글 — 저장·전송은 UTC(끝에 Z) · 서버가 만드는 파일 글(엑셀 · PDF · 메일 · 파일 이름)은 한국 시각 고정.
화면 글은 `common_util_time.ts`(보는 PC 시간대) — 서버 PC 시간대에 기대지 않음(한국은 서머타임 없음 = 고정 +9).
"""
from datetime import date, datetime, timedelta, timezone
KST = timezone(timedelta(hours=9), "KST")
def utc_text(value: datetime | str | None) -> str | None:
"""시간대 없는 값 = UTC 로 보고 「2026-10-30T01:02:03Z」 · 시간대 있는 값은 UTC 로 바꿈 · 없음 = None · 글은 그대로."""
if value is None or isinstance(value, str):
return value or None
if value.tzinfo is not None:
value = value.astimezone(timezone.utc)
return value.replace(tzinfo=None, microsecond=0).isoformat() + "Z"
def utc_now_text() -> str:
"""지금 — UTC 글(저장용)."""
return utc_text(datetime.now(timezone.utc)) or ""
def utc_from_timestamp(seconds: float) -> str:
"""파일 수정 시각 등 epoch 초 → UTC 글."""
return utc_text(datetime.fromtimestamp(seconds, timezone.utc)) or ""
def kst_now() -> datetime:
"""지금 — 한국 시각(서버 PC 시간대와 무관)."""
return datetime.now(KST)
def kst_today() -> date:
return kst_now().date()
def kst_from_timestamp(seconds: float) -> datetime:
return datetime.fromtimestamp(seconds, KST)
def kst_text(value: datetime | str | None) -> str:
"""저장된 시각 → 「2026-10-30 10:02:03」 한국 시각(파일 글용) · Z · +hh:mm 있으면 바꿈 · 없는 옛 글 = 이미 한국 시각."""
if value is None or value == "":
return ""
if isinstance(value, str):
try:
value = datetime.fromisoformat(value.strip().replace(" ", "T"))
except ValueError:
return value
if value.tzinfo is None:
return value.replace(microsecond=0).isoformat(sep=" ")
return value.astimezone(KST).replace(tzinfo=None, microsecond=0).isoformat(sep=" ")
def utc_now_naive() -> datetime:
"""지금 — DB 칸(UTC, 시간대 표시 없음)과 견주는 값."""
return datetime.now(timezone.utc).replace(tzinfo=None)
def install_json_utc() -> None:
"""응답의 datetime(DB 값 = UTC) 을 끝에 Z 붙은 글로 — 화면이 보는 사람 시간대로 바꿈."""
from fastapi.encoders import ENCODERS_BY_TYPE
ENCODERS_BY_TYPE[datetime] = lambda value: utc_text(value) or ""