51 lines
1.7 KiB
TypeScript
51 lines
1.7 KiB
TypeScript
|
|
/**
|
||
|
|
* 타임존 & 날짜 포맷 유틸리티
|
||
|
|
*
|
||
|
|
* 현재 KST 고정. 추후 토글 필요 시 DISPLAY_TZ 상수만 변경.
|
||
|
|
*/
|
||
|
|
|
||
|
|
/** 표시용 타임존. 'UTC' | 'Asia/Seoul' 등 IANA tz 문자열. */
|
||
|
|
export const DISPLAY_TZ = 'Asia/Seoul' as const;
|
||
|
|
|
||
|
|
/** 표시 레이블 (예: "KST") */
|
||
|
|
export const DISPLAY_TZ_LABEL = 'KST' as const;
|
||
|
|
|
||
|
|
/* ── 포맷 함수 ─────────────────────────────────────────────── */
|
||
|
|
|
||
|
|
const pad2 = (n: number) => String(n).padStart(2, '0');
|
||
|
|
|
||
|
|
/** DISPLAY_TZ 기준으로 Date → "YYYY년 MM월 DD일 HH시 mm분 ss초" */
|
||
|
|
export function fmtDateTimeFull(date: Date): string {
|
||
|
|
const parts = new Intl.DateTimeFormat('ko-KR', {
|
||
|
|
timeZone: DISPLAY_TZ,
|
||
|
|
year: 'numeric',
|
||
|
|
month: '2-digit',
|
||
|
|
day: '2-digit',
|
||
|
|
hour: '2-digit',
|
||
|
|
minute: '2-digit',
|
||
|
|
second: '2-digit',
|
||
|
|
hour12: false,
|
||
|
|
}).formatToParts(date);
|
||
|
|
|
||
|
|
const p: Record<string, string> = {};
|
||
|
|
for (const { type, value } of parts) p[type] = value;
|
||
|
|
|
||
|
|
return `${p.year}년 ${p.month}월 ${p.day}일 ${p.hour}시 ${pad2(Number(p.minute))}분 ${pad2(Number(p.second))}초`;
|
||
|
|
}
|
||
|
|
|
||
|
|
/** ISO 문자열 → "YYYY년 MM월 DD일 HH시 mm분 ss초" (파싱 실패 시 fallback) */
|
||
|
|
export function fmtIsoFull(iso: string | null | undefined): string {
|
||
|
|
if (!iso) return '-';
|
||
|
|
const d = new Date(iso);
|
||
|
|
if (Number.isNaN(d.getTime())) return String(iso);
|
||
|
|
return fmtDateTimeFull(d);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** ISO 문자열 → "HH:mm:ss" (시간만) */
|
||
|
|
export function fmtIsoTime(iso: string | null | undefined): string {
|
||
|
|
if (!iso) return '';
|
||
|
|
const d = new Date(iso);
|
||
|
|
if (Number.isNaN(d.getTime())) return String(iso);
|
||
|
|
return d.toLocaleTimeString('ko-KR', { timeZone: DISPLAY_TZ, hour12: false });
|
||
|
|
}
|