React+Node.js部署后日期时区异常问题求助(Cyclic+Vercel)
我使用React前端与Node.js Express后端开发项目,需求是将前端发送请求时的日期按用户时区处理后存入数据库。本地开发时功能正常,但部署至生产环境(前端托管于Vercel、后端托管于Cyclic.sh)后,后端接收的日期比本地时间晚2小时。
前端发送日期代码
const handleSaveMeal = () => { const currentDate = new Date(); postMealWithProducts.mutate({ ...mealInfo, prods: mealProducts, title: selectedMealType, isPortion: isPortion, createdAt: currentDate, }); };
后端接收处理日期代码
const { prods, createdAt, ...rest } = req.body; if (prods.length < 1) return res.status(400).json({ error: "At least one product is required" }); const luxonDate = DateTime.fromISO(createdAt); console.log(luxonDate); if (luxonDate.invalidExplanation) return res.status(400).json({ error: luxonDate.invalidExplanation }); const normalizedDate = luxonDate.toISO();
本地与生产环境下,前端发送日期前的日志均显示为本地时间,但后端日志显示:本地环境标准化日期为2023-11-08T19:58:24.323+02:00,生产环境则为2023-11-08T18:01:18.358+00:00。
原因分析
前端日期序列化的隐性转换:前端直接传递
new Date()对象时,HTTP请求会自动将其序列化为ISO格式字符串(比如通过JSON.stringify处理),这个过程会把本地时间转成UTC时区的ISO字符串(带Z后缀)。本地开发时,前后端运行在同一时区(比如你的本地时区是+02:00),后端解析后会自动转成本地时区显示;但生产后端服务器(Cyclic.sh)默认使用UTC时区,所以解析后直接显示UTC时间,看起来比用户本地时间晚2小时。Luxon解析的时区默认规则:后端用
DateTime.fromISO(createdAt)解析日期时,如果传入的ISO字符串没有指定时区(或是带Z的UTC字符串),Luxon会默认采用运行环境的时区(即后端服务器的UTC时区)创建DateTime对象。本地开发时后端在你的本地时区,解析结果和前端一致;生产环境后端在UTC时区,解析结果自然是UTC时间,出现时差。前后端环境时区差异:本地开发阶段,前后端都在你的本地机器运行,时区完全一致,所以日期处理没有偏差;但生产环境中,前端运行在用户浏览器(本地时区),后端服务器运行在UTC时区,代码中没有显式指定时区处理逻辑,就导致了日期显示的差异。
内容的提问来源于stack exchange,提问作者Aušrys Mikoliūnas

