/** * 格式化相關工具函式 */ /** * 格式化數字為千分位格式 */ export const formatNumber = (num: number | null | undefined): string => { if (num === null || num === undefined) return "0"; return num.toLocaleString(); }; /** * 格式化貨幣(NT$) */ export const formatCurrency = (num: number | null | undefined): string => { if (num === null || num === undefined) return "NT$ 0"; return `NT$ ${num.toLocaleString()}`; }; /** * 格式化日期 */ export const formatDate = (date: string): string => { if (!date) return "-"; // Assume date format is YYYY-MM-DD or YYYY-MM-DD HH:mm:ss const datePart = date.split("T")[0].split(" ")[0]; // Directly return the parsed string components to guarantee no timezone shift const parts = datePart.split("-"); if (parts.length === 3) { return `${parts[0]}/${parts[1]}/${parts[2]}`; } // Fallback for unexpected formats return datePart.replace(/-/g, "/"); }; /** * 格式化日期並包含星期 */ export const formatDateWithDayOfWeek = (date: string): string => { if (!date) return "-"; const datePart = date.split("T")[0].split(" ")[0]; const parts = datePart.split("-"); if (parts.length === 3) { const [y, m, d] = parts.map(Number); // Use noon to safely calculate the day of week const dt = new Date(y, m - 1, d, 12, 0, 0); const weekDay = dt.toLocaleDateString("zh-TW", { weekday: "short" }); // Return original string parts + calculated weekday return `${parts[0]}/${parts[1]}/${parts[2]} (${weekDay})`; } return datePart.replace(/-/g, "/"); }; /** * 格式化發票號碼 * 例如:AB12345678 -> AB-12345678 */ export const formatInvoiceNumber = (invoice: string | null | undefined): string => { if (!invoice) return "-"; const cleanInvoice = invoice.replace(/-/g, ""); if (/^[a-zA-Z]{2}\d+$/.test(cleanInvoice)) { return `${cleanInvoice.slice(0, 2).toUpperCase()}-${cleanInvoice.slice(2)}`; } return invoice; }; /** * 獲取當前日期(YYYY-MM-DD 格式) */ export const getCurrentDate = (): string => { const now = new Date(); const year = now.getFullYear(); const month = String(now.getMonth() + 1).padStart(2, "0"); const day = String(now.getDate()).padStart(2, "0"); return `${year}-${month}-${day}`; }; /** * 生成唯一 ID */ export const generateId = (): string => { return `${Date.now()}-${Math.random().toString(36).substring(2, 9)}`; }; /** * 生成撥補單號 */ export const generateOrderNumber = (): string => { return `TO${Date.now().toString().slice(-8)}`; }; /** * 生成批號 * 格式:{倉庫代碼}-{日期YYYYMMDD}-{流水號} * 例如:WH1-20251128-001 */ export const generateBatchNumber = ( warehouseId: string, date?: string, sequence?: number ): string => { const targetDate = date || getCurrentDate(); const dateStr = targetDate.replace(/-/g, ""); const seq = sequence || Math.floor(Math.random() * 1000); const seqStr = seq.toString().padStart(3, "0"); return `WH${warehouseId}-${dateStr}-${seqStr}`; }; /** * 獲取當前日期時間(YYYY-MM-DDTHH:mm 格式,用於 datetime-local input) */ export const getCurrentDateTime = (): string => { const now = new Date(); const year = now.getFullYear(); const month = String(now.getMonth() + 1).padStart(2, "0"); const day = String(now.getDate()).padStart(2, "0"); const hours = String(now.getHours()).padStart(2, "0"); const minutes = String(now.getMinutes()).padStart(2, "0"); return `${year}-${month}-${day}T${hours}:${minutes}`; }; /** * 格式化日期時間顯示 */ export const formatDateTime = (datetime: string): string => { if (!datetime) return "-"; return new Date(datetime).toLocaleString("zh-TW", { year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", hour12: false, }); }; /** * 獲取日期區間(YYYY-MM-DD 格式) * 支援: today, yesterday, this_week, this_month, last_month */ export const getDateRange = (type: string): { start: string, end: string } => { const now = new Date(); // Reset time to avoid timezone issues when calculating dates now.setHours(12, 0, 0, 0); let start = new Date(now); let end = new Date(now); const format = (d: Date) => { const year = d.getFullYear(); const month = String(d.getMonth() + 1).padStart(2, "0"); const day = String(d.getDate()).padStart(2, "0"); return `${year}-${month}-${day}`; }; switch (type) { case "today": break; case "yesterday": start.setDate(now.getDate() - 1); end.setDate(now.getDate() - 1); break; case "this_week": // 週一為一週的第一天 const dayOfWeek = now.getDay() || 7; start.setDate(now.getDate() - dayOfWeek + 1); end.setDate(now.getDate() + (7 - dayOfWeek)); break; case "this_month": start = new Date(now.getFullYear(), now.getMonth(), 1); end = new Date(now.getFullYear(), now.getMonth() + 1, 0); break; case "last_month": start = new Date(now.getFullYear(), now.getMonth() - 1, 1); end = new Date(now.getFullYear(), now.getMonth(), 0); break; } return { start: format(start), end: format(end) }; };