// 前端日期/周期工具: 与 server/checkin/period.js 保持同一套口径 (Asia/Shanghai) export const TZ = 'Asia/Shanghai' const FMT = new Intl.DateTimeFormat('en-CA', { timeZone: TZ, year: 'numeric', month: '2-digit', day: '2-digit', }) /** 任意时间 -> 本地日历日 "YYYY-MM-DD" */ export function toDateStr(d = new Date()) { return FMT.format(d instanceof Date ? d : new Date(d)) } function toUTC(s) { const [y, m, d] = String(s).split('-').map(Number) return new Date(Date.UTC(y, (m || 1) - 1, d || 1)) } function fromUTC(dt) { return dt.toISOString().slice(0, 10) } export function addDays(s, n) { const d = toUTC(s) d.setUTCDate(d.getUTCDate() + n) return fromUTC(d) } export function addMonths(s, n) { const [y, m] = String(s).split('-').map(Number) const first = new Date(Date.UTC(y, (m || 1) - 1 + n, 1)) const day = Number(String(s).slice(8, 10)) || 1 const lastDay = new Date(Date.UTC(first.getUTCFullYear(), first.getUTCMonth() + 1, 0)).getUTCDate() first.setUTCDate(Math.min(day, lastDay)) return fromUTC(first) } /** 周一为一周第一天 */ export function startOfWeek(s) { const dow = (toUTC(s).getUTCDay() + 6) % 7 return addDays(s, -dow) } export const PERIOD_LABEL = { day: '每天', week: '每周', month: '每月', year: '每年' } export function periodRange(period, s) { switch (period) { case 'week': { const start = startOfWeek(s) return { start, end: addDays(start, 6) } } case 'month': { const start = String(s).slice(0, 8) + '01' const [y, m] = String(s).split('-').map(Number) return { start, end: fromUTC(new Date(Date.UTC(y, m || 1, 0))) } } case 'year': { const y = String(s).slice(0, 4) return { start: y + '-01-01', end: y + '-12-31' } } default: return { start: s, end: s } } } /** 月历网格: 返回 6*7 = 42 天 (含前后月的补位), 周一起始 */ export function monthGrid(monthStr) { const first = monthStr + '-01' const gridStart = startOfWeek(first) const days = [] for (let i = 0; i < 42; i++) days.push(addDays(gridStart, i)) return days } export function weekdayLabels() { return ['一', '二', '三', '四', '五', '六', '日'] } /** 相对今天的文案: 昨天 / 今天 / 明天 / MM-DD */ export function dayLabel(dateStr, today = toDateStr()) { if (dateStr === today) return '今天' if (dateStr === addDays(today, -1)) return '昨天' if (dateStr === addDays(today, 1)) return '明天' return dateStr.slice(5).replace('-', '/') } export function fmtMonth(monthStr) { const [y, m] = monthStr.split('-') return y + '年' + Number(m) + '月' }