export const getShanghaiDay = (date = new Date()) => { const parts = new Intl.DateTimeFormat('en-CA', { timeZone: 'Asia/Shanghai', year: 'numeric', month: '2-digit', day: '2-digit' }).formatToParts(date); const part = (type) => parts.find(item => item.type === type)?.value || ''; return `${part('year')}-${part('month')}-${part('day')}`; }; export const normalizeExpiryReminder = (reminder) => { if (!reminder || typeof reminder !== 'object') return null; const days = reminder.remaining_days; if (days === null || days === undefined || days === '' || !Number.isInteger(Number(days)) || Number(days) < 0 || Number(days) > 15 || !['red', 'purple', 'pink'].includes(reminder.level)) return null; return { ...reminder, remaining_days: Number(days) }; }; export const formatShanghaiExpiry = (value) => { if (!value) return '-'; const text = String(value); // An offset-free server date is already a Shanghai wall-clock value. if (!/(Z|[+-]\d{2}:?\d{2})$/i.test(text)) return text.replace('T', ' ').slice(0, 19); const date = new Date(text); if (!Number.isFinite(date.getTime())) return '-'; return new Intl.DateTimeFormat('zh-CN', { timeZone: 'Asia/Shanghai', year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', hourCycle: 'h23' }).format(date); };