const CommonUtil = { /** * 获取当前时间 */ getCurrenTime(){ // 创建一个 Date 对象,表示当前时间 let now = new Date(); // 获取年、月、日、时、分、秒 // 获取年月日时分秒 let time = { year: now.getFullYear().toString().slice(-2), // 获取年份后两位 month: (now.getMonth() + 1), // 月份从0开始,需加1 day: now.getDate(), hours: now.getHours(), minutes: now.getMinutes(), seconds: now.getSeconds() }; return time; }, /** * 通过时间戳 获取年月日 时分秒 * @param {10位 时间戳} timestamp */ getDateByTimestamp(timestamp){ if(timestamp === 0){ return { year:0, month:0, day:0, hours:0, minutes:0, seconds:0 } } // 将时间戳转为毫秒(JavaScript的Date对象使用毫秒为单位) const date = new Date(timestamp * 1000); // 格式化为年月日时分秒 const formattedDate = `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')} ${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}:${date.getSeconds().toString().padStart(2, '0')}`; console.log(formattedDate); // 输出:2024-12-20 00:00:00 return { year:date.getFullYear() - 2000, month:date.getMonth() + 1, day:date.getDate(), hours:date.getHours(), minutes:date.getMinutes(), seconds:date.getSeconds() } }, /** * 发送屏幕亮度,0~5级别转换 * @param {*} level */ sendSBLevelConv(level){ switch(level){ case 0: return 0x8F; case 1: return 0x88; case 2: return 0x86; case 3: return 0x84; case 4: return 0x82; case 5: return 0x80; default: return 0x84;//如果不是0~5,则默认均衡亮度 } }, /** * 获得屏幕亮度,0~5级别转换 * @param {*} level */ respSBLevelConv(level){ switch(level){ case 0x0F: return 0; case 0x0D: return 1; case 0x0B: return 2; case 0x09: return 3; case 0x07: return 4; case 0x05: return 5; default: return 2;//如果不是0~5,则默认均衡亮度 } }, getWeekBinary(week) { let binaryValue = 0; for (let i = 0; i < week.length; i++) { // 逐位设置,week[0] 代表周天(offset 0) binaryValue |= week[i] << i; } return binaryValue; }, stringToBytes(str) { let encoded = unescape(encodeURIComponent(str)); let bytes = []; for (let i = 0; i < encoded.length; i++) { bytes.push(encoded.charCodeAt(i)); } console.log("bytes:",bytes) return bytes; }, bytesToString(bytes) { let str = ''; for (let i = 0; i < bytes.length; i++) { str += String.fromCharCode(bytes[i]); } return decodeURIComponent(escape(str)); // 确保正确解码 }, /** * 字段转指令 * @param {字段} field */ fieldToCommand(field){ switch(field){ case "sleepLastTime": return 0x53; case "heartRateLastTime": return 0x55; case "temperatureLastTime": return 0x65; case "bloodOxygenLastTime": return 0x66; case "bloodPressureLastTime": return 0x56; case "stepLastTime": return 0x52; default: return 0; } }, /** * 指令转字段 * @param {指令} command */ commandToField(command){ switch(command){ case 0x53: return "sleepLastTime"; case 0x55: return "heartRateLastTime"; case 0x65: return "temperatureLastTime"; case 0x66: return "bloodOxygenLastTime"; case 0x56: return "bloodPressureLastTime"; case 0x52: return "stepLastTime"; default: return 0; } }, /** * 组装睡眠数据 */ assembleSleepData(sleepArray) { let compareDate = sleepArray[0].yyyyMMdd; // 获取第一个数据的时间作为比对时间 let compareMinute = sleepArray[0].minute; let res = []; // 存放最终结果 let resItem = { // 每天的睡眠数据对象 date: '', sleepList: [] }; // 取出第一个数据并初始化 let firstSleepData = sleepArray[0]; resItem.date = firstSleepData.yyyyMMdd; resItem.sleepList.push(firstSleepData); // 将第一个数据放入到 `sleepList` sleepArray.forEach((item,index) => { // 判断是否是同一天的数据 let isSameDay = this.timeComparison(compareDate,compareMinute, item.yyyyMMdd, item.minute); // 如果状态发生变化,且日期不同,就表示开始新的睡眠数据 if (item.status !== firstSleepData.status) { if (isSameDay) { resItem.sleepList.push(item); } else { // 取出数据 let lastItem = sleepArray[index - 1]; lastItem.minute = lastItem.minute + 1;//加1分钟作为起床点 resItem.sleepList.push(lastItem); res.push(resItem); // 否则,将当天的数据推入结果数组 resItem = { // 新的一天开始 date: item.yyyyMMdd, sleepList: [item] // 将当前项作为新的睡眠数据开始 }; compareDate = item.yyyyMMdd; // 更新对比日期,用于比对后续数据 compareMinute = item.minute; } } firstSleepData = item; // 更新当前比对的睡眠数据 }); // 最后一次的睡眠数据也需要被加入到 `res` if (resItem.sleepList.length > 0) { // 获取最后一个数据添加到最后 let lastItem = sleepArray[sleepArray.length - 1]; lastItem.minute = lastItem.minute + 1;//加1分钟作为起床点 resItem.sleepList.push(lastItem); res.push(resItem); } return res; // 返回按天拆分后的睡眠数据 }, /** * 计算出一天的时间范围 * @param {对比日期} compareDate */ getDayTimeRange(compareDate,compareMinute) { // 将 "YYYYMMDD" 格式的日期转换为 "YYYY-MM-DD" 格式,方便解析 const formattedDateStr = compareDate.replace(/(\d{4})(\d{2})(\d{2})/, '$1-$2-$3'); // 创建目标日期对象 // const date = new Date(formattedDateStr); // 例如:2024-12-12 // 获取对比日期的Date,前一天的20:00:00 // const prevDayStart = new Date(date); // prevDayStart.setDate(date.getDate() - 1); //设置为前一天 // prevDayStart.setHours(20, 0, 0, 0); // 设置为20:00:00 // // 获取对比日期的Date,后一天的10:00:00 // const nextDayEnd = new Date(date); // nextDayEnd.setDate(date.getDate()); // 设置为后一天 // nextDayEnd.setHours(10, 0, 0, 0); // 设置为10:00:00 // 获取对比日期的Date,前一天的20:00:00 const date1 = new Date(formattedDateStr) const date2 = new Date(formattedDateStr) const prevDayStart = new Date(date1); if(this.isEveningTime(compareMinute)){ prevDayStart.setDate(date1.getDate()); } else { prevDayStart.setDate(date1.getDate() - 1); } prevDayStart.setHours(20, 0, 0, 0); // 设置为20:00:00 // 获取对比日期的Date,后一天的10:00:00 const nextDayEnd = new Date(date2); if(this.isEveningTime(compareMinute)){ nextDayEnd.setDate(date2.getDate() + 1); } else { nextDayEnd.setDate(date2.getDate()); } nextDayEnd.setHours(10, 0, 0, 0); // 设置为10:00:00 // 返回时间戳 return { startTimestamp: prevDayStart.getTime(), // 转换为10位时间戳 endTimestamp: nextDayEnd.getTime() // 转换为10位时间戳 }; }, /** * 判断是否是晚上的20:00~00:00点 * @param {*} minute */ isEveningTime(minute){ return minute < 1440 && minute > 1200; }, /** * * @param {日期} dateStr * @param {一天的第N分钟} minutes */ getTimestampFromDateAndMinutes(dateStr, minutes) { // 将 "YYYYMMDD" 格式的日期转换为 "YYYY-MM-DD" 格式,方便解析 const formattedDateStr = dateStr.replace(/(\d{4})(\d{2})(\d{2})/, '$1-$2-$3'); // 创建目标日期对象 const date = new Date(formattedDateStr); // 例如:2024-12-12 // 计算总分钟数 const totalMinutes = minutes; // 将分钟数转化为小时和分钟 const hours = Math.floor(totalMinutes / 60); // 计算小时数 const mins = totalMinutes % 60; // 计算剩余的分钟数 // 设置时间为指定的小时和分钟 date.setHours(hours, mins, 0, 0); // 设置为相应的时分秒 // 返回时间戳,转换为10位时间戳 return date.getTime(); }, /** * * @param {对比日期} compareDate * @param {分钟} minute * @param {比较值} comparisonValue */ timeComparison(compareDate,compareMinute,comparisonValue,minute){ let dateRange = this.getDayTimeRange(compareDate,compareMinute); let time = this.getTimestampFromDateAndMinutes(comparisonValue,minute); if(time >= dateRange.startTimestamp && time <= dateRange.endTimestamp){ // 在范围内,是同一天睡眠 return true; } return false; }, sortSleep(data){ data.forEach((item) =>{ // 排序算法 // item.sleepList.sort((a, b) => { // // 先比较 yyyyMMdd // if (a.yyyyMMdd !== b.yyyyMMdd) { // return a.yyyyMMdd.localeCompare(b.yyyyMMdd); // } // // 再比较 minute // return a.minute - b.minute; // }); // 因为后端的接口处理方式为如果第一个数据为清醒,不会作为睡眠时间,故将第一个数据作为浅睡 item.sleepList[0].status = 1 item.date = item.sleepList[item.sleepList.length - 1].yyyyMMdd }) return data; }, /** * * @param {补全数据} data */ completeMissingData(data){ data.sort((a, b) => { // 先比较 yyyyMMdd if (a.yyyyMMdd !== b.yyyyMMdd) { return a.yyyyMMdd.localeCompare(b.yyyyMMdd); } // 再比较 minute return a.minute - b.minute; }); let result = []; // 存放最终结果 for (let i = 0; i < data.length; i++) { result.push(data[i]); // 先将当前数据加入结果集 // 如果当前数据不是最后一个,检查与下一个数据的 minute 是否连续 if (i < data.length - 1) { let currentMinute = data[i].minute; let nextMinute = data[i + 1].minute; if(data[i].yyyyMMdd == data[i + 1].yyyyMMdd && nextMinute - currentMinute < 600){ // 如果不连续,补全缺失的数据 if (nextMinute > currentMinute + 1) { for (let j = currentMinute + 1; j < nextMinute; j++) { result.push({ minute: j, // 补全的 minute status: 3, // 沿用当前数据的 status yyyyMMdd: data[i].yyyyMMdd // 沿用当前数据的日期 }); } } } else { // 还要考虑隔天的情况,如果隔天有数据缺失的也需要补齐 let currentDate = data[i].yyyyMMdd; let nextDate = data[i + 1].yyyyMMdd; // if(CommonUtil.isNextDay(currentDate,nextDate) && // currentMinute > 1200 && nextDate > 480 ){ // console.log(currentDate,currentMinute); // console.log(nextDate,nextMinute); // console.log("相减的差值:",nextMinute - currentMinute); // console.log("是否跨天:",CommonUtil.isNextDay(currentDate,nextDate)); // if(currentMinute < 1439){ // for (let j = currentMinute + 1; j < 1440; j++) { // result.push({ // minute: j, // status: 3, // yyyyMMdd: data[i].yyyyMMdd // }); // } // } // if(0 < nextMinute){ // for (let j = 0; j < nextMinute; j++) { // result.push({ // minute: j, // status: 3, // yyyyMMdd: data[i + 1].yyyyMMdd // }); // } // } // } } } } return result; }, // 获取下一个日期 getNextDay(dateString) { // 解析传入的日期字符串 let date = new Date(dateString); // 将日期加一天 date.setDate(date.getDate() + 1); // 格式化为 "YYYY-MM-DD" 格式 let year = date.getFullYear(); let month = ('0' + (date.getMonth() + 1)).slice(-2); // 月份需要 +1,且补充 0 let day = ('0' + date.getDate()).slice(-2); // 日期补充 0 return `${year}${month}${day}`; }, /** * 删除已上传的睡眠数据 * @param {} arr * @param {*} targetDate */ removeBeforeDate(arr, targetDate) { // 将目标日期字符串转换为 Date 对象 let target = new Date(targetDate.substring(0, 4), targetDate.substring(4, 6) - 1, targetDate.substring(6, 8)); // 过滤掉日期小于或等于目标日期的项 return arr.filter(item => { // 将数组中每个日期转换为 Date 对象 let itemDate = new Date(item.date.substring(0, 4), item.date.substring(4, 6) - 1, item.date.substring(6, 8)); // 只保留日期大于目标日期的项 return itemDate > target; }); }, /** * 是否是下一天 * @param {} date1 * @param {*} date2 */ isNextDay(date1, date2) { // 将日期格式化为 yyyy-MM-dd 形式 const d1 = new Date(date1.toString().slice(0, 4), date1.toString().slice(4, 6) - 1, date1.toString().slice(6, 8)); const d2 = new Date(date2.toString().slice(0, 4), date2.toString().slice(4, 6) - 1, date2.toString().slice(6, 8)); // 将时间部分清零 d1.setHours(0, 0, 0, 0); d2.setHours(0, 0, 0, 0); // 计算日期差值(单位:毫秒) const diffTime = d2 - d1; const oneDayInMillis = 24 * 60 * 60 * 1000; // 一天的毫秒数 // 判断差值是否为一天 return diffTime === oneDayInMillis; }, } // 导出模块 module.exports = CommonUtil;