/** * 格式化日期对象为字符串 * @param {Date} date - 日期对象 * @returns {string} - 格式化后的日期字符串,格式为 YYYY-MM-DD HH:mm:ss */ export const formatDate = (date: Date) => { const pad = (num: number) => (num < 10 ? "0" + num : num) return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}` } /** * 将日期字符串解析为日期对象 * @param {string} dateStr - 日期字符串,格式为 YYYY-MM-DD HH:mm:ss * @returns {Date} - 解析后的日期对象 */ const parseDate = (dateStr: string) => { const [datePart, timePart] = dateStr.split(" ") const [year, month, day] = datePart.split("-").map(Number) const [hours, minutes, seconds] = timePart.split(":").map(Number) return new Date(year, month - 1, day, hours, minutes, seconds) } /** * 获取指定时间点的时间 * @param {("today" | "yesterday" | "twoDaysAgo" | "oneWeekAgo" | "lastMonday" | "lastSunday")} timePoint - 时间点,可以是 "today"、"yesterday"、"twoDaysAgo"、"oneWeekAgo"、"lastMonday" 或 "lastSunday" * @param {number} hourRange - 整点范围,输入 24 为 23:59:59 * @returns {string} - 格式化后的时间字符串,格式为 YYYY-MM-DD HH:mm:ss */ export const getSpecificTime = ( timePoint: | "today" | "yesterday" | "twoDaysAgo" | "oneWeekAgo" | "lastMonday" | "lastSunday", hourRange: number, needFormat: boolean = true ) => { const now = new Date() const targetTime = new Date(now) if (timePoint === "yesterday") { targetTime.setDate(now.getDate() - 1) } else if (timePoint === "twoDaysAgo") { targetTime.setDate(now.getDate() - 2) } else if (timePoint === "oneWeekAgo") { targetTime.setDate(now.getDate() - 7) } else if (timePoint === "lastMonday") { const day = now.getDay() const diff = day === 0 ? 6 : day - 1 // adjust when day is sunday targetTime.setDate(now.getDate() - diff - 7) } else if (timePoint === "lastSunday") { const day = now.getDay() const diff = day === 0 ? 7 : day // adjust when day is not sunday targetTime.setDate(now.getDate() - diff) } if (hourRange === 24) { targetTime.setHours(23, 59, 59, 999) } else { targetTime.setHours(hourRange, 0, 0, 0) } return needFormat ? formatDate(targetTime) : targetTime } /** * 获取指定时间范围的开始时间和结束时间 * @param {("daily" | "weekly" | "threeDays")} timeScope - 时间范围,可以是 "daily"、"weekly" 或 "threeDays" * @returns {{ startTime: string, endTime: string }} - 格式化后的开始时间和结束时间 */ export const getTimeRange = (timeScope: "daily" | "weekly" | "threeDays") => { const startTimeMap: Record = { daily: "today", weekly: "oneWeekAgo", threeDays: "twoDaysAgo", } return { startTime: getSpecificTime(startTimeMap[timeScope], 0) as string, endTime: getSpecificTime("today", 24) as string, } } /** * 调整时间范围 * 如果开始时间晚于结束时间,则交换两者 * 如果开始时间和结束时间都晚于当前时间,则调整为过去三天 * 如果开始时间早于当前时间且结束时间晚于当前时间,则将结束时间调整为当前时间 * @param {string} startTime - 开始时间,格式为 YYYY-MM-DD HH:mm:ss * @param {string} endTime - 结束时间,格式为 YYYY-MM-DD HH:mm:ss * @returns {{ startTime: string, endTime: string }} - 调整后的开始时间和结束时间 */ export const adjustTimeRange = (startTime: string, endTime: string) => { const now = new Date() let start = parseDate(startTime) let end = parseDate(endTime) if (start > end) { ;[start, end] = [end, start] } if (start > now && end > now) { return getTimeRange("threeDays") } else if (start < now && end > now) { end = now end.setHours(23, 59, 59, 999) } const maxSpan = 60 * 24 * 60 * 60 * 1000 // 60天的毫秒数 if (end.getTime() - start.getTime() > maxSpan) { start = new Date(end.getTime() - maxSpan) } return { startTime: formatDate(start), endTime: formatDate(end), } }