Firestore按月份查询传感器数据时遇日期格式错误
解决Firestore按月份查询的Invalid date format错误
你遇到的错误核心原因是传递给dayjs的不是完整日期信息:在月份选择器的onChange中,你提取了newValue.getMonth()的数字索引(比如0代表1月)传给getDataMonth,但dayjs无法仅用单个月份数字生成合法日期对象(缺少年份信息),直接导致Firestore查询时的日期格式错误。同时,month state存储的是数字类型,但MUI DatePicker(搭配AdapterDayjs)的value期望的是dayjs实例/Date对象,类型不匹配也会引发格式问题。
修复步骤:
1. 修改月份选择器的onChange逻辑
直接传递DatePicker返回的完整dayjs日期对象,不要提取月份索引:
// 原错误代码 onChange={(newValue) => { if (newValue instanceof Date) { const selectedMonth = newValue.getMonth(); changeMonth(selectedMonth); } else { console.error("Invalid date format:", newValue); } }} // 修复后代码 onChange={(newValue) => { changeMonth(newValue); // 直接传递dayjs实例 }}
2. 修正changeMonth和getDataMonth函数
让getDataMonth接收完整的dayjs对象,直接用它计算月份首尾日期,同时处理空值情况:
// 原错误代码 const changeMonth = (newMonth) => { setMonth(newMonth); getDataMonth(newMonth); }; const getDataMonth = (targetMonth) => { setLoading(true); const startOfMonth = dayjs(targetMonth).startOf("month"); // targetMonth是数字,dayjs无法解析 // ... }; // 修复后代码 const changeMonth = (newMonth) => { setMonth(newMonth); // 存储dayjs实例 getDataMonth(newMonth); }; const getDataMonth = (targetMonth) => { if (!targetMonth) { // 初始加载/重置时不执行月份查询,直接结束 setLoading(false); return; } setLoading(true); // 直接用传入的dayjs实例计算月份首尾 const startOfMonth = targetMonth.startOf("month"); const endOfMonth = targetMonth.endOf("month"); const q = query( collection(db, ENV, VERSION, "facilities", facilityId, "sensorHistory"), orderBy("createdAt", "desc"), where("deviceId", "==", sensorId), where("dataType", "==", "data"), where("createdAt", ">=", startOfMonth.toDate()), where("createdAt", "<=", endOfMonth.toDate()) ); getDocs(q) .then((querysnapshot) => { setLoading(false); setHistory( querysnapshot.docs.map((doc) => ({ ...doc.data(), id: doc.id })) ); }) .catch((e) => { alert("Error fetching data!"); setLoading(false); console.error(e); }); };
3. 修正DatePicker的value绑定
确保value与state类型一致,直接绑定month state即可:
<DatePicker disableFuture={true} onChange={(newValue) => changeMonth(newValue)} sx={{ padding: "0px", outline: "none" }} label={BasicLanguage.users.activityReport.date.format[language]} value={month} views={['month', 'year']} />
额外优化建议:
- 统一日期处理库:代码中同时使用了
dayjs和moment,建议统一用dayjs减少依赖,比如表格中的日期格式化可以改成:{dayjs.unix(x.createdAt.seconds).format("YYYY-MM-DD HH:mm:ss")} - 避免重复查询:初始
useEffect中同时调用getData()和getDataMonth()会触发两次Firestore查询,建议默认只调用getData()查询最近100条数据。
内容的提问来源于stack exchange,提问作者Ortan Apex
相关产品推荐
相关产品推荐

