Firestore按日期查询时出现RangeError: Invalid Time Value错误
解决Firestore日期查询时的RangeError: Invalid time value错误
核心问题原因
你遇到的错误本质是查询时传入的日期字符串格式不被JavaScript的Date构造函数支持——Firestore控制台显示的February 1, 2023 at 11:00:00 AM UTC+5:30是人性化展示格式,并非实际存储的Timestamp数据,但如果查询时直接用这个带at的字符串创建Date对象,会导致解析失败,进而触发toISOString()的错误。
正确的解决方法
方法1:规范查询参数的日期格式
查询时传入标准可解析的日期格式,比如:
- ISO 8601字符串(如
2023-02-01T05:30:00.000Z) - 时间戳数字
- 不带
at的自然语言日期字符串(如February 1, 2023 11:00:00 AM UTC+5:30)
修改查询代码,确保传入的options.date.from/to是合法格式:
async function getAllAppointments(options = { date: {} }) { const constraints = [] if('from' in options.date) constraints.push(where('appointmentDate', '>=', new Date(options.date.from))) if('to' in options.date) constraints.push(where('appointmentDate', '<', new Date(options.date.to))) return (await getDocs(query(collection(db, 'appointments'), ...constraints))).docs.map(appointment => appointment.data()) }
方法2:使用Firestore Timestamp类型存储和查询(推荐)
Firestore原生支持Timestamp类型,比JavaScript的Date更可靠,避免跨时区和格式解析问题:
存储时改用Timestamp:
import { Timestamp, setDoc, doc } from "firebase/firestore"; async function addNewAppointment(appointment) { // 将Date对象转换为Firestore Timestamp appointment.appointmentDate = Timestamp.fromDate(new Date(appointment.appointmentDate)) await setDoc(doc(db, 'appointments', appointment.appointmentID), appointment) }
查询时也用Timestamp构建条件:
import { Timestamp, where, query, collection, getDocs } from "firebase/firestore"; async function getAllAppointments(options = { date: {} }) { const constraints = [] if('from' in options.date) { const fromTimestamp = Timestamp.fromDate(new Date(options.date.from)) constraints.push(where('appointmentDate', '>=', fromTimestamp)) } if('to' in options.date) { const toTimestamp = Timestamp.fromDate(new Date(options.date.to)) constraints.push(where('appointmentDate', '<', toTimestamp)) } return (await getDocs(query(collection(db, 'appointments'), ...constraints))).docs.map(appointment => appointment.data()) }
方法3:预处理带"at"的日期字符串(临时兼容方案)
如果无法避免传入带at的字符串,可以先预处理替换掉at再解析:
// 预处理函数:替换日期字符串中的"at"为空格 const parseFirestoreDisplayDate = (dateStr) => { return new Date(dateStr.replace(' at ', ' ')) } async function getAllAppointments(options = { date: {} }) { const constraints = [] if('from' in options.date) constraints.push(where('appointmentDate', '>=', parseFirestoreDisplayDate(options.date.from))) if('to' in options.date) constraints.push(where('appointmentDate', '<', parseFirestoreDisplayDate(options.date.to))) return (await getDocs(query(collection(db, 'appointments'), ...constraints))).docs.map(appointment => appointment.data()) }
额外说明
Firestore控制台显示的日期格式只是给开发者看的友好展示,实际存储的是Timestamp或Date类型的二进制数据,不要直接用控制台显示的字符串作为查询参数。
内容的提问来源于stack exchange,提问作者Jaideep Shekhar
相关产品推荐
相关产品推荐

