MERN预约应用UTC转换问题:星期值计算异常排查
问题:Date.getDay() 返回值不符合预期(周日被解析为6而非0)
我正在开发MERN预约应用,调用/available-times?date=2024-03-03接口时,终端显示计算出的dayOfWeek为6,但2024-03-03实际是周日,预期值应为0,导致无法从availability表获取对应时段。当前appointments表为空,接口代码及终端输出如下:
// get available slots app.get('/available-times', (req, res) => { const { date } = req.query; if (!date) { return res.status(400).send('Date query parameter is required'); } const inputDate = new Date(date); const dayOfWeek = inputDate.getDay(); const sqlAvailabilities = 'SELECT * FROM availability WHERE weekday = ?'; db.query(sqlAvailabilities, [dayOfWeek], (err, availabilityResults) => { if (err) { return res.status(500).json({ error: err.message }); } const sqlAppointments = 'SELECT * FROM appointments WHERE date = ?'; db.query(sqlAppointments, [date], (err, appointmentResults) => { if (err) { return res.status(500).json({ error: err.message }); } // Create one-hour increments from availability spans const oneHourIncrements = availabilityResults.flatMap(avail => { const increments = []; const startTime = new Date(`1970-01-01T${avail.start_time}`); const endTime = new Date(`1970-01-01T${avail.end_time}`); while(startTime < endTime) { const endIncrement = new Date(startTime.getTime()); endIncrement.setHours(endIncrement.getHours() + 1); increments.push({ start: startTime.toISOString().split('T')[1].substring(0, 5), end: endIncrement.toISOString().split('T')[1].substring(0, 5), }); // Move to next hour startTime.setHours(startTime.getHours() + 1); } return increments; }); // Filter out booked slots const availableTimes = oneHourIncrements.filter(increment => { return !appointmentResults.some(app => { const appStart = `1970-01-01T${app.start_time}`; const appEnd = `1970-01-01T${app.end_time}`; const incStart = `1970-01-01T${increment.start}`; const incEnd = `1970-01-01T${increment.end}`; return (incStart < appEnd) && (incEnd > appStart); }); }); console.log('Received date:', date); console.log('Calculated dayOfWeek:', dayOfWeek); console.log('Availability results:', availabilityResults); console.log('Appointment results:', appointmentResults); console.log('One-hour increments:', oneHourIncrements); console.log('Available Times:', availableTimes); res.json(availableTimes); }); }); });
终端输出:
Received date: 2024-03-03
Calculated dayOfWeek: 6
Availability results: []
Appointment results: []
One-hour increments: []
Available Times: []
问题原因
JavaScript中,当使用new Date('YYYY-MM-DD')这种ISO格式字符串构造日期时,默认会以UTC时区解析。如果你的本地时区比UTC早(比如东八区),2024-03-03会被解析为UTC时间的2024-03-03T00:00:00Z,对应本地时区的2024-03-02T16:00:00(假设UTC-8),此时getDay()返回的是周六的6,而非预期的周日0。
修复方案
有两种可靠的方式确保日期以本地时区解析:
方案1:拆分日期字符串,用年、月、日参数构造Date
将日期字符串拆分为年、月、日,直接传入Date构造函数(注意月份是0-based,需要减1):
const { date } = req.query; if (!date) { return res.status(400).send('Date query parameter is required'); } // 拆分日期,按本地时区构造Date const [year, month, day] = date.split('-').map(Number); const inputDate = new Date(year, month - 1, day); // 月份从0开始,所以减1 const dayOfWeek = inputDate.getDay();
方案2:调整UTC时间到本地时区
通过时区偏移量修正解析后的日期:
const inputDate = new Date(date); // 加上时区偏移量,将UTC时间转为本地时间的日期 inputDate.setMinutes(inputDate.getMinutes() + inputDate.getTimezoneOffset()); const dayOfWeek = inputDate.getDay();
验证与后续检查
- 修改代码后,重新调用接口,
dayOfWeek应返回0(对应周日)。 - 确认
availability表中,周日对应的weekday字段值为0,确保数据库数据与代码逻辑匹配。
内容的提问来源于stack exchange,提问作者nodenewbie
相关产品推荐
相关产品推荐

