runtime_tracker / services /EyeTimeQuery.js
Murasame52's picture
Upload 5 files
00b9b23 verified
Raw
History Blame Contribute Delete
3.7 kB
// EyeTimeQuery.js - 仅统计用眼分钟数(日/周/月), 支持时区
const { mongoose } = require('../index');
const DateRangeHelper = require('../utils/DateRange');
const TimezoneUtils = require('../utils/timezone');
const DailyEyeTime = mongoose.model('DailyEyeTime');
class EyeTimeQuery {
constructor(timezoneOffset = 8) {
// 初始化时区工具与日期范围助手
this.timezoneOffset = timezoneOffset;
this.timezoneUtils = new TimezoneUtils(timezoneOffset);
this.dateHelper = new DateRangeHelper(timezoneOffset);
}
/**
* 获取某日的用眼分钟数
* @param {Date} date - 查询目标日期(UTC 或本地时间均可)
* @param {number} timezoneOffset - 时区偏移(小时)
*/
async getDailyMinutes(date, timezoneOffset = this.timezoneOffset) {
const tzUtils = new TimezoneUtils(timezoneOffset);
// 解析输入日期为本地日期
const localDate = tzUtils.parseDate(date);
// 构建数据库查询的日期(本地零点对应的 UTC 时间)
const localDayStart = new Date(Date.UTC(
localDate.getUTCFullYear(),
localDate.getUTCMonth(),
localDate.getUTCDate(),
0, 0, 0, 0
));
const dbDate = tzUtils.localToUtc(localDayStart);
// 查询记录
const dayRecords = await DailyEyeTime.find({
date: dbDate
}).lean();
// 初始化小时分布
const hourlyStats = Array(24).fill(0);
for (const rec of dayRecords) {
if (rec.hourlyUsage && Array.isArray(rec.hourlyUsage)) {
for (let i = 0; i < 24; i++) {
hourlyStats[i] += rec.hourlyUsage[i] || 0;
}
}
}
// 总分钟数直接用小时分布求和
const totalUsage = Math.round(hourlyStats.reduce((a, b) => a + b, 0) * 100) / 100;
return {
date: localDate.toISOString().split('T')[0],
totalUsage,
hourlyStats: hourlyStats.map(v => Math.round(v * 100) / 100),
timezoneOffset
};
}
/**
* 获取周统计结果
*/
async getWeeklyMinutes(weekOffset = 0, timezoneOffset = this.timezoneOffset) {
const { startDate, endDate } = this.dateHelper.getWeekRange(weekOffset);
const result = {};
for (let d = new Date(startDate); d <= endDate; d.setDate(d.getDate() + 1)) {
const stats = await this.getDailyMinutes(new Date(d), timezoneOffset);
result[stats.date] = stats.totalUsage;
}
return {
weekOffset,
weekRange: {
start: startDate.toISOString().split('T')[0],
end: endDate.toISOString().split('T')[0]
},
dailyTotals: result,
timezoneOffset
};
}
/**
* 获取月统计结果
*/
async getMonthlyMinutes(monthOffset = 0, timezoneOffset = this.timezoneOffset) {
const { startDate, endDate } = this.dateHelper.getMonthRange(monthOffset, timezoneOffset);
const result = {};
for (let d = new Date(startDate); d <= endDate; d.setDate(d.getDate() + 1)) {
const stats = await this.getDailyMinutes(new Date(d), timezoneOffset);
result[stats.date] = stats.totalUsage;
}
return {
monthOffset,
monthRange: {
start: startDate.toISOString().split('T')[0],
end: endDate.toISOString().split('T')[0]
},
dailyTotals: result,
timezoneOffset
};
}
}
module.exports = EyeTimeQuery;