/** * 日期工具 · 跨 API 共享, 避免日期 / 时区 相关 bug。 * * 为什么用 UTC 而不是本地时区? * MySQL @db.Date 列存储时只保留日期部分。如果用 setHours(0,0,0,0) 取本地午夜, * JS Date 对应的 UTC 时刻在 +8 区是当日 16:00 UTC, 经过 Prisma 序列化 + MySQL * TZ 转换后, 存的"日期"和读的"日期"可能差一天, 导致 dailyQuota 复合键 (userId, date) * 找不到刚 upsert 的行 (P2025)。 * * 用 setUTCHours(0,0,0,0) 拿到的是 "今天的 UTC 0 点", 无论服务器 / 客户端 TZ, * 存取一致。代价: 中国用户在 08:00 之前(UTC 0 点之前)算"昨天"。对于按日额度场景 * 足够好(短期可接受, 长期需要按"运营日"显式划分)。 */ export function startOfUtcDay(d = new Date()): Date { const x = new Date(d); x.setUTCHours(0, 0, 0, 0); return x; } /** 判断两个 Date 是否同一个 UTC 日期 */ export function isSameUtcDay(a: Date, b: Date): boolean { return ( a.getUTCFullYear() === b.getUTCFullYear() && a.getUTCMonth() === b.getUTCMonth() && a.getUTCDate() === b.getUTCDate() ); }