SvelteKit 结合 Prisma 时服务端到客户端日期类型数据显示异常的解决方案咨询
SvelteKit 结合 Prisma 时服务端到客户端日期类型数据显示异常的解决方案咨询
嘿,这个问题我之前也碰到过,本质就是时区转换在捣鬼!先给你理清楚来龙去脉,再给你几个靠谱的解决办法:
问题根源
你数据库里存的shift_date是@db.Date类型(无时区的YYYY-MM-DD格式),Prisma读取后会把它转成UTC时区的午夜时间戳(比如你看到的2022-03-15T00:00:00.000Z)。而你的客户端处于UTC-4的东部夏令时,解析这个UTC时间时,会自动转成本地时间——也就是2022-03-14T20:00:00,看起来就像是“少了一天”,但其实只是时区转换的正常结果。
解决方案推荐
方案1:服务端统一转成日期字符串(最省心)
既然你不想在客户端每次都额外处理,那最好的办法就是在服务端把shift_date转成纯日期字符串(YYYY-MM-DD)再返回给客户端,这样客户端拿到的就是和数据库完全一致的日期,不会被时区干扰。
你可以在load函数里拿到查询结果后,遍历数据修改shift_date:
export async function load({ params, getClientAddress }) { const allData = await prisma.TurnReport_Depts.findUnique({ where: { dept_id: parseInt(params.dept) }, include: { TurnReport_Areas: { where: { dept_id: parseInt(params.dept) }, include: { vTurnReport: { where: { shift_date: params.date + 'T00:00:00.000Z', shift_num: parseInt(params.shift) }, include: { vTurnReport_Attachments: true } } } } } }); // 新增:处理shift_date为纯日期字符串 allData.TurnReport_Areas.forEach(area => { area.vTurnReport.forEach(report => { report.shift_date = report.shift_date.toISOString().split('T')[0]; }); }); await prisma.$disconnect(); console.log(allData); return { allData }; }
这样客户端拿到的shift_date就是"2022-03-15",直接显示或者转成Date对象都不会有问题。
方案2:客户端忽略时区,基于UTC构建日期
如果必须在客户端保留Date对象,那可以通过UTC方法来构建正确的日期,避免本地时区偏移:
<!-- 客户端组件里的处理示例 --> <script> export let report; // 基于UTC日期构建本地Date对象 const correctShiftDate = new Date(Date.UTC( report.shift_date.getUTCFullYear(), report.shift_date.getUTCMonth(), report.shift_date.getUTCDate() )); </script> <p>Shift Date: {correctShiftDate.toLocaleDateString()}</p>
这个方法会直接提取UTC时间里的年、月、日,生成一个本地时区的Date对象,显示出来就是正确的2022-03-15。
不推荐的方案
不要尝试修改Prisma或数据库的时区配置——@db.Date本身就是无时区的日期类型,Prisma转成UTC午夜的处理是符合标准的,强行改时区反而会引入更多兼容性问题。
备注:内容来源于stack exchange,提问作者Avi4nFLu
相关产品推荐
相关产品推荐

