Spaces:
Running
Running
| // fix_date_add_one_day.js - 将所有记录的日期加1天 | |
| const { mongoose } = require('../index'); | |
| const readline = require('readline'); | |
| const rl = readline.createInterface({ | |
| input: process.stdin, | |
| output: process.stdout | |
| }); | |
| function question(query) { | |
| return new Promise(resolve => { | |
| rl.question(query, resolve); | |
| }); | |
| } | |
| function formatDate(date) { | |
| return new Date(date).toISOString(); | |
| } | |
| function formatLocalDate(date, offset = 8) { | |
| const d = new Date(new Date(date).getTime() + offset * 60 * 60 * 1000); | |
| return `${d.getUTCFullYear()}-${String(d.getUTCMonth() + 1).padStart(2, '0')}-${String(d.getUTCDate()).padStart(2, '0')}`; | |
| } | |
| async function fixDates() { | |
| try { | |
| console.log('='.repeat(80)); | |
| console.log('日期修正脚本 - 所有记录日期加 1 天'); | |
| console.log('='.repeat(80)); | |
| console.log(); | |
| const DailyStat = mongoose.model('DailyStat'); | |
| // 1. 统计数据 | |
| console.log('正在扫描数据库...\n'); | |
| const allStats = await DailyStat.find({}).sort({ date: 1 }); | |
| if (allStats.length === 0) { | |
| console.log('❌ 数据库中没有数据。'); | |
| return; | |
| } | |
| console.log(`📊 找到 ${allStats.length} 条记录\n`); | |
| // 2. 显示日期范围 | |
| const firstDate = allStats[0].date; | |
| const lastDate = allStats[allStats.length - 1].date; | |
| console.log('当前日期范围:'); | |
| console.log(` 最早: ${formatLocalDate(firstDate)} (UTC: ${formatDate(firstDate)})`); | |
| console.log(` 最晚: ${formatLocalDate(lastDate)} (UTC: ${formatDate(lastDate)})`); | |
| console.log(); | |
| // 3. 显示修改后的日期范围 | |
| const newFirstDate = new Date(firstDate.getTime() + 24 * 60 * 60 * 1000); | |
| const newLastDate = new Date(lastDate.getTime() + 24 * 60 * 60 * 1000); | |
| console.log('修改后日期范围:'); | |
| console.log(` 最早: ${formatLocalDate(newFirstDate)} (UTC: ${formatDate(newFirstDate)})`); | |
| console.log(` 最晚: ${formatLocalDate(newLastDate)} (UTC: ${formatDate(newLastDate)})`); | |
| console.log(); | |
| // 4. 显示前5条记录的变化 | |
| console.log('前5条记录的日期变化:'); | |
| console.log('-'.repeat(80)); | |
| for (let i = 0; i < Math.min(5, allStats.length); i++) { | |
| const stat = allStats[i]; | |
| const oldDate = stat.date; | |
| const newDate = new Date(oldDate.getTime() + 24 * 60 * 60 * 1000); | |
| console.log(`记录 ${i + 1}: ${stat.deviceId} | ${stat.appName}`); | |
| console.log(` 旧: ${formatLocalDate(oldDate)} (${formatDate(oldDate)})`); | |
| console.log(` 新: ${formatLocalDate(newDate)} (${formatDate(newDate)})`); | |
| console.log(); | |
| } | |
| // 5. 统计设备 | |
| const deviceCount = new Map(); | |
| allStats.forEach(stat => { | |
| deviceCount.set(stat.deviceId, (deviceCount.get(stat.deviceId) || 0) + 1); | |
| }); | |
| console.log('设备统计:'); | |
| deviceCount.forEach((count, deviceId) => { | |
| console.log(` ${deviceId}: ${count} 条记录`); | |
| }); | |
| console.log(); | |
| // 6. 确认执行 | |
| console.log('='.repeat(80)); | |
| console.log('⚠️ 重要提示:'); | |
| console.log('1. 此操作将修改所有记录的 date 字段'); | |
| console.log('2. 每条记录的日期将增加 24 小时(1天)'); | |
| console.log('3. hourlyUsage 和其他字段保持不变'); | |
| console.log('4. 建议先备份数据库'); | |
| console.log('='.repeat(80)); | |
| console.log(); | |
| const answer = await question('确认执行修正?(yes/no): '); | |
| if (answer.toLowerCase() !== 'yes') { | |
| console.log('\n❌ 修正已取消'); | |
| return; | |
| } | |
| // 7. 执行修正 | |
| console.log('\n开始修正...\n'); | |
| let updatedCount = 0; | |
| let errorCount = 0; | |
| for (const stat of allStats) { | |
| try { | |
| // 只修改日期,加1天(24小时) | |
| stat.date = new Date(stat.date.getTime() + 24 * 60 * 60 * 1000); | |
| await stat.save(); | |
| updatedCount++; | |
| // 进度显示 | |
| const progress = Math.floor((updatedCount / allStats.length) * 100); | |
| process.stdout.write(`\r进度: ${progress}% (${updatedCount}/${allStats.length})`); | |
| } catch (error) { | |
| errorCount++; | |
| console.error(`\n错误处理记录 ${stat._id}: ${error.message}`); | |
| } | |
| } | |
| console.log('\n\n='.repeat(80)); | |
| console.log('✅ 修正完成!'); | |
| console.log('='.repeat(80)); | |
| console.log(`📊 统计:`); | |
| console.log(` - 成功修正:${updatedCount} 条`); | |
| console.log(` - 失败记录:${errorCount} 条`); | |
| console.log('='.repeat(80)); | |
| // 8. 验证结果 | |
| console.log('\n验证修正结果...\n'); | |
| const verifyStats = await DailyStat.find({}).sort({ date: 1 }); | |
| if (verifyStats.length > 0) { | |
| const verifyFirst = verifyStats[0].date; | |
| const verifyLast = verifyStats[verifyStats.length - 1].date; | |
| console.log('修正后的日期范围:'); | |
| console.log(` 最早: ${formatLocalDate(verifyFirst)} (UTC: ${formatDate(verifyFirst)})`); | |
| console.log(` 最晚: ${formatLocalDate(verifyLast)} (UTC: ${formatDate(verifyLast)})`); | |
| console.log(); | |
| console.log('修正后的数据示例(前5条):'); | |
| for (let i = 0; i < Math.min(5, verifyStats.length); i++) { | |
| const stat = verifyStats[i]; | |
| const total = stat.hourlyUsage.reduce((sum, val) => sum + val, 0); | |
| console.log(`\n记录 ${i + 1}:`); | |
| console.log(` 设备: ${stat.deviceId} | 应用: ${stat.appName}`); | |
| console.log(` 日期: ${formatLocalDate(stat.date)} (UTC: ${formatDate(stat.date)})`); | |
| console.log(` 总使用: ${total.toFixed(2)} 分钟`); | |
| } | |
| } | |
| } catch (error) { | |
| console.error('\n❌ 修正过程中发生错误:', error); | |
| throw error; | |
| } | |
| } | |
| async function main() { | |
| try { | |
| await fixDates(); | |
| } catch (error) { | |
| console.error('脚本执行失败:', error); | |
| process.exit(1); | |
| } finally { | |
| rl.close(); | |
| await mongoose.connection.close(); | |
| console.log('\n数据库连接已关闭'); | |
| process.exit(0); | |
| } | |
| } | |
| main(); |