/** * 중앙 포맷팅 함수. * 모든 컴포넌트는 날짜/숫자/통화를 표시할 때 이 함수들만 호출한다. * * 사용법: * import { formatDate, formatNumber, formatCurrency } from "@/lib/formatting"; * formatDate("2025-01-01") // "2025-01-01" * formatDate("2025-01-01T14:30:00Z", "datetime") // "2025-01-01 14:30:00" * formatNumber(1234567) // "1,234,567" * formatCurrency(50000) // "₩50,000" */ export { getFormatRules, setFormatRules, DEFAULT_FORMAT_RULES } from "./rules"; export type { FormatRules, DateFormatRules, NumberFormatRules, CurrencyFormatRules } from "./rules"; import { getFormatRules } from "./rules"; // --- 날짜 포맷 --- type DateFormatType = "display" | "datetime" | "input" | "time"; /** * 날짜 값을 지정된 형식으로 포맷한다. * @param value - ISO 문자열, Date, 타임스탬프 * @param type - "display" | "datetime" | "input" | "time" * @returns 포맷된 문자열 (파싱 실패 시 원본 반환) */ export function formatDate(value: unknown, type: DateFormatType = "display"): string { if (value == null || value === "") return ""; const rules = getFormatRules(); const format = rules.date[type]; try { const date = value instanceof Date ? value : new Date(String(value)); if (isNaN(date.getTime())) return String(value); return applyDateFormat(date, format); } catch { return String(value); } } /** * YYYY-MM-DD HH:mm:ss 패턴을 Date 객체에 적용 */ function applyDateFormat(date: Date, pattern: string): string { const y = date.getFullYear(); const M = date.getMonth() + 1; const d = date.getDate(); const H = date.getHours(); const m = date.getMinutes(); const s = date.getSeconds(); return pattern .replace("YYYY", String(y)) .replace("MM", String(M).padStart(2, "0")) .replace("DD", String(d).padStart(2, "0")) .replace("HH", String(H).padStart(2, "0")) .replace("mm", String(m).padStart(2, "0")) .replace("ss", String(s).padStart(2, "0")); } // --- 숫자 포맷 --- /** * 숫자를 로케일 기반으로 포맷한다 (천단위 구분자 등). * @param value - 숫자 또는 숫자 문자열 * @param decimals - 소수점 자릿수 (미지정 시 기본값 사용) * @returns 포맷된 문자열 */ export function formatNumber(value: unknown, decimals?: number): string { if (value == null || value === "") return ""; const rules = getFormatRules(); const num = typeof value === "number" ? value : parseFloat(String(value)); if (isNaN(num)) return String(value); const dec = decimals ?? rules.number.decimals; return new Intl.NumberFormat(rules.number.locale, { minimumFractionDigits: dec, maximumFractionDigits: dec, }).format(num); } // --- 통화 포맷 --- /** * 금액을 통화 형식으로 포맷한다. * @param value - 숫자 또는 숫자 문자열 * @param currencyCode - 통화 코드 (미지정 시 기본값 사용) * @returns 포맷된 문자열 (예: "₩50,000") */ export function formatCurrency(value: unknown, currencyCode?: string): string { if (value == null || value === "") return ""; const rules = getFormatRules(); const num = typeof value === "number" ? value : parseFloat(String(value)); if (isNaN(num)) return String(value); const code = currencyCode ?? rules.currency.code; return new Intl.NumberFormat(rules.currency.locale, { style: "currency", currency: code, maximumFractionDigits: code === "KRW" ? 0 : 2, }).format(num); } // --- 범용 포맷 --- /** * 데이터 타입에 따라 자동으로 적절한 포맷을 적용한다. * @param value - 포맷할 값 * @param dataType - "date" | "datetime" | "number" | "currency" | "text" */ export function formatValue(value: unknown, dataType: string): string { switch (dataType) { case "date": return formatDate(value, "display"); case "datetime": return formatDate(value, "datetime"); case "time": return formatDate(value, "time"); case "number": case "integer": case "float": case "decimal": return formatNumber(value); case "currency": case "money": return formatCurrency(value); default: return value == null ? "" : String(value); } }