// 시장 데이터 표시용 순수 유틸 (서버·클라이언트 공용 — 'use client'/'use server' 미선언) // 소수 포함 숫자 (지수·환율·금리 등) — 천 단위 구분 + 소수 자릿수 지정. null 은 — export function formatDecimal(value: number|null|undefined, fractionDigits = 2): string { if (value === null || value === undefined) { return '—'; } return value.toLocaleString('ko-KR', { minimumFractionDigits: fractionDigits, maximumFractionDigits: fractionDigits }); } // bp(만분율) → % 문자열 (부호 없이 절대값, 색·부호는 마크업에서 병행). 예: 1234 → "12.34%" export function formatBpRate(bp: number|null|undefined): string { if (bp === null || bp === undefined) { return '—'; } return `${(Math.abs(bp) / 100).toFixed(2)}%`; } // 금리 % (미고시 null → —). 예: 3.5 → "3.50%" export function formatRatePercent(value: number|null|undefined, fractionDigits = 2): string { if (value === null || value === undefined) { return '—'; } return `${value.toFixed(fractionDigits)}%`; } // 최신 기준일 라벨 (tradeDate null 이면 대체 문구) export function tradeDateLabel(date: string|null|undefined): string { return date ? `${date} 기준` : '데이터 준비 중'; } // 공시 접수번호 → DART 원문 링크 export function dartViewerUrl(rceptNo: string): string { return `https://dart.fss.or.kr/dsaf001/main.do?rcpNo=${encodeURIComponent(rceptNo)}`; } // SEIBro 코드 → 라벨 조회 (미매칭 시 원문 코드, 값 없으면 —) export function codeLabel(code: string|null|undefined, map: Record): string { if (code === null || code === undefined || code === '') { return '—'; } return map[code] ?? code; } // 주식수 등 정수 수량 (null 은 —). 예: 12345678 → "12,345,678" export function formatShares(value: number|null|undefined): string { if (value === null || value === undefined) { return '—'; } return value.toLocaleString('ko-KR'); } // 큰 금액(원/USD) → 조/억/만 축약 (외화커스터디·ELS 미상환·채권 발행액). null·0 은 — export function formatAmountCompact(value: number|null|undefined, unit = '원'): string { if (!value) { return '—'; } const eok = value / 100_000_000; if (eok >= 10_000) { const jo = Math.floor(eok / 10_000); const rest = Math.floor(eok % 10_000); return rest > 0 ? `${jo.toLocaleString('ko-KR')}조 ${rest.toLocaleString('ko-KR')}억${unit}` : `${jo.toLocaleString('ko-KR')}조${unit}`; } if (eok >= 1) { return `${Math.floor(eok).toLocaleString('ko-KR')}억${unit}`; } const man = value / 10_000; if (man >= 1) { return `${Math.floor(man).toLocaleString('ko-KR')}만${unit}`; } return `${value.toLocaleString('ko-KR')}${unit}`; } // yyyy-MM-dd 없으면 대체문구 export function dateOrDash(date: string|null|undefined): string { return date && date.length > 0 ? date : '—'; } // 총회시각 HHmm → "HH:mm" (없으면 빈 문자열) export function meetingTimeLabel(hhmm: string|null|undefined): string { if (!hhmm || hhmm.length < 3) { return ''; } const padded = hhmm.padStart(4, '0'); return `${padded.slice(0, 2)}:${padded.slice(2, 4)}`; } // KOSIS 수록시점 → 표시 라벨 (월간 YYYYMM → "YYYY.MM", 연간 YYYY 그대로, 그 외 원문). null 은 — export function macroPeriodLabel(period: string|null|undefined): string { if (!period) { return '—'; } if (/^\d{6}$/.test(period)) { return `${period.slice(0, 4)}.${period.slice(4, 6)}`; } return period; } // 거시지표 값 (천 단위 구분 + 소수 최대 2자리 — 단위는 마크업에서 병기). null 은 — export function formatMacroValue(value: number|null|undefined): string { if (value === null || value === undefined) { return '—'; } return value.toLocaleString('ko-KR', { maximumFractionDigits: 2 }); }