138 lines
4.2 KiB
TypeScript
138 lines
4.2 KiB
TypeScript
/**
|
|
* 중앙 포맷팅 함수.
|
|
* 모든 컴포넌트는 날짜/숫자/통화를 표시할 때 이 함수들만 호출한다.
|
|
*
|
|
* 사용법:
|
|
* 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);
|
|
}
|
|
}
|